/*
 * call-seq:
 *    PKCS7.new => pkcs7
 *    PKCS7.new(string) => pkcs7
 *
 * Many methods in this class aren't documented.
 */
static VALUE
ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
{
    PKCS7 *p7, *pkcs = DATA_PTR(self);
    BIO *in;
    VALUE arg;

    if(rb_scan_args(argc, argv, "01", &arg) == 0)
	return self;
    arg = ossl_to_der_if_possible(arg);
    in = ossl_obj2bio(arg);
    p7 = PEM_read_bio_PKCS7(in, &pkcs, NULL, NULL);
    DATA_PTR(self) = pkcs;
    if (!p7) {
	OSSL_BIO_reset(in);
        p7 = d2i_PKCS7_bio(in, &pkcs);
	if (!p7)
	    ossl_raise(rb_eArgError, "Could not parse the PKCS7");
	DATA_PTR(self) = pkcs;
    }
    BIO_free(in);
    ossl_pkcs7_set_data(self, Qnil);
    ossl_pkcs7_set_err_string(self, Qnil);

    return self;
}
Esempio n. 2
0
/* Reads a PKCS7 token and adds default 'granted' status info to it. */
static TS_RESP *read_PKCS7(BIO *in_bio)
{
    int ret = 0;
    PKCS7 *token = NULL;
    TS_TST_INFO *tst_info = NULL;
    TS_RESP *resp = NULL;
    TS_STATUS_INFO *si = NULL;

    if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
        goto end;
    if ((tst_info = PKCS7_to_TS_TST_INFO(token)) == NULL)
        goto end;
    if ((resp = TS_RESP_new()) == NULL)
        goto end;
    if ((si = TS_STATUS_INFO_new()) == NULL)
        goto end;
    if (!TS_STATUS_INFO_set_status(si, TS_STATUS_GRANTED))
        goto end;
    if (!TS_RESP_set_status_info(resp, si))
        goto end;
    TS_RESP_set_tst_info(resp, token, tst_info);
    token = NULL;               /* Ownership is lost. */
    tst_info = NULL;            /* Ownership is lost. */
    ret = 1;

 end:
    PKCS7_free(token);
    TS_TST_INFO_free(tst_info);
    if (!ret) {
        TS_RESP_free(resp);
        resp = NULL;
    }
    TS_STATUS_INFO_free(si);
    return resp;
}
Esempio n. 3
0
static int verify_command(char *data, char *digest, char *queryfile,
			  char *in, int token_in,
			  char *ca_path, char *ca_file, char *untrusted)
	{
	BIO *in_bio = NULL;
	PKCS7 *token = NULL;
	TS_RESP *response = NULL;
	TS_VERIFY_CTX *verify_ctx = NULL;
	int ret = 0;

	/* Decode the token (PKCS7) or response (TS_RESP) files. */
	if (!(in_bio = BIO_new_file(in, "rb"))) goto end;
	if (token_in)
		{
		if (!(token = d2i_PKCS7_bio(in_bio, NULL))) goto end;
		}
	else
		{
		if (!(response = d2i_TS_RESP_bio(in_bio, NULL))) goto end;
		}

	if (!(verify_ctx = create_verify_ctx(data, digest, queryfile, 
					     ca_path, ca_file, untrusted)))
		goto end;

	/* Checking the token or response against the request. */
	ret = token_in ?
		TS_RESP_verify_token(verify_ctx, token) :
		TS_RESP_verify_response(verify_ctx, response);

 end:
	printf("Verification: ");
	if (ret)
		printf("OK\n");
	else
		{
		printf("FAILED\n");
		/* Print errors, if there are any. */
		ERR_print_errors(bio_err);
		}
	
	/* Clean up. */
	BIO_free_all(in_bio);
	PKCS7_free(token);
	TS_RESP_free(response);
	TS_VERIFY_CTX_free(verify_ctx);
	return ret;
	}
Esempio n. 4
0
static int verify_command(char *data, char *digest, char *queryfile,
                          char *in, int token_in,
                          char *CApath, char *CAfile, char *untrusted,
                          X509_VERIFY_PARAM *vpm)
{
    BIO *in_bio = NULL;
    PKCS7 *token = NULL;
    TS_RESP *response = NULL;
    TS_VERIFY_CTX *verify_ctx = NULL;
    int ret = 0;

    if ((in_bio = BIO_new_file(in, "rb")) == NULL)
        goto end;
    if (token_in) {
        if ((token = d2i_PKCS7_bio(in_bio, NULL)) == NULL)
            goto end;
    } else {
        if ((response = d2i_TS_RESP_bio(in_bio, NULL)) == NULL)
            goto end;
    }

    if ((verify_ctx = create_verify_ctx(data, digest, queryfile,
                                        CApath, CAfile, untrusted,
                                        vpm)) == NULL)
        goto end;

    ret = token_in
        ? TS_RESP_verify_token(verify_ctx, token)
        : TS_RESP_verify_response(verify_ctx, response);

 end:
    printf("Verification: ");
    if (ret)
        printf("OK\n");
    else {
        printf("FAILED\n");
        ERR_print_errors(bio_err);
    }

    BIO_free_all(in_bio);
    PKCS7_free(token);
    TS_RESP_free(response);
    TS_VERIFY_CTX_free(verify_ctx);
    return ret;
}
Esempio n. 5
0
/* 
功能:验证签名 
入口: 
char*certFile    证书(含匙) 
char* plainText  明文 
char* cipherText 签名 
出口: 
bool true  签名验证成功 
bool false 验证失败 
*/  
bool PKCS7_VerifySign(char*certFile,char* plainText,char* cipherText )  
{  
    /* Get X509 */  
    FILE* fp = fopen (certFile, "r");  
    if (fp == NULL)   
        return false;  
    X509* x509 = PEM_read_X509(fp, NULL, NULL, NULL);  
    fclose (fp);  
  
    if (x509 == NULL) {  
        ERR_print_errors_fp (stderr);  
        return false;  
    }  
  
    //BASE64解码  
    unsigned char *retBuf[1024*8];  
    int retBufLen = sizeof(retBuf);  
    memset(retBuf,0,sizeof(retBuf));  
    decodeBase64(cipherText,(void *)retBuf,&retBufLen);  
  
    //从签名中取PKCS7对象  
    BIO* vin = BIO_new_mem_buf(retBuf,retBufLen);  
    PKCS7 *p7 = d2i_PKCS7_bio(vin,NULL);  
  
  
    //取STACK_OF(X509)对象  
    STACK_OF(X509) *stack=sk_X509_new_null();//X509_STORE_new()  
    sk_X509_push(stack,x509);  
  
  
    //明码数据转为BIO  
    BIO *bio = BIO_new(BIO_s_mem());    
    BIO_puts(bio,plainText);  
  
    //验证签名  
    int err = PKCS7_verify(p7, stack, NULL,bio, NULL, PKCS7_NOVERIFY);  
  
    if (err != 1) {  
        ERR_print_errors_fp (stderr);  
        return false;  
    }  
  
    return true;  
}  
Esempio n. 6
0
/* Reads a PKCS7 token and adds default 'granted' status info to it. */
static TS_RESP *
read_PKCS7(BIO * in_bio)
{
	int ret = 0;
	PKCS7 *token = NULL;
	TS_TST_INFO *tst_info = NULL;
	TS_RESP *resp = NULL;
	TS_STATUS_INFO *si = NULL;

	/* Read PKCS7 object and extract the signed time stamp info. */
	if (!(token = d2i_PKCS7_bio(in_bio, NULL)))
		goto end;
	if (!(tst_info = PKCS7_to_TS_TST_INFO(token)))
		goto end;

	/* Creating response object. */
	if (!(resp = TS_RESP_new()))
		goto end;

	/* Create granted status info. */
	if (!(si = TS_STATUS_INFO_new()))
		goto end;
	if (!(ASN1_INTEGER_set(si->status, TS_STATUS_GRANTED)))
		goto end;
	if (!TS_RESP_set_status_info(resp, si))
		goto end;

	/* Setting encapsulated token. */
	TS_RESP_set_tst_info(resp, token, tst_info);
	token = NULL;		/* Ownership is lost. */
	tst_info = NULL;	/* Ownership is lost. */

	ret = 1;
end:
	PKCS7_free(token);
	TS_TST_INFO_free(tst_info);
	if (!ret) {
		TS_RESP_free(resp);
		resp = NULL;
	}
	TS_STATUS_INFO_free(si);
	return resp;
}
Esempio n. 7
0
static LUA_FUNCTION(openssl_pkcs7_read)
{
  BIO* bio = load_bio_object(L, 1);
  int fmt = luaL_checkoption(L, 2, "auto", format);
  PKCS7 *p7 = NULL;
  BIO* ctx = NULL;

  if (fmt == FORMAT_AUTO)
  {
    fmt = bio_is_der(bio) ? FORMAT_DER : FORMAT_PEM;
  }

  if (fmt == FORMAT_DER)
  {
    p7 = d2i_PKCS7_bio(bio, NULL);
    BIO_reset(bio);
  }
  else if (fmt == FORMAT_PEM)
  {
    p7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
    BIO_reset(bio);
  }
  else if (fmt == FORMAT_SMIME)
  {
    p7 = SMIME_read_PKCS7(bio, &ctx);
  }

  BIO_free(bio);
  if (p7)
  {
    PUSH_OBJECT(p7, "openssl.pkcs7");
    if (ctx)
    {
      BUF_MEM* mem;
      BIO_get_mem_ptr(ctx, &mem);
      lua_pushlstring(L, mem->data, mem->length);
      BIO_free(ctx);
      return 2;
    }
    return 1;
  }
  return openssl_pushresult(L, 0);
}
Esempio n. 8
0
/*
 * call-seq:
 *    PKCS7.new => pkcs7
 *    PKCS7.new(string) => pkcs7
 *
 * Many methods in this class aren't documented.
 */
static VALUE
ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
{
    PKCS7 *p7;
    BIO *in;
    VALUE arg;

    if(rb_scan_args(argc, argv, "01", &arg) == 0)
	return self;
    arg = ossl_to_der_if_possible(arg);
    in = ossl_obj2bio(arg);
    p7 = PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL);
    if (!p7) {
	BIO_reset(in);
        p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self));
    }
    BIO_free(in);
    ossl_pkcs7_set_data(self, Qnil);
    ossl_pkcs7_set_err_string(self, Qnil);

    return self;
}
Esempio n. 9
0
static PKCS7 *pkcs7_get_signed_file(const char *filename, BIO **content, int format)
{
    PKCS7 *pkcs7;
    BIO *input;

    input = BIO_new_file(filename, "rb");
    if (!input) {
        return NULL;
    }

    *content = NULL;
    switch (format) {
    case PKCS7_INPUT_FORMAT_SMIME:
        pkcs7 = SMIME_read_PKCS7(input, content);
        break;

    case PKCS7_INPUT_FORMAT_PEM:
        pkcs7 = PEM_read_bio_PKCS7(input, NULL, NULL, "");
        break;

    case PKCS7_INPUT_FORMAT_DER:
        pkcs7 = d2i_PKCS7_bio(input, NULL);
        break;

    default:
        abort(); /* Should never reach here. */
        return NULL;
    };

    if (!pkcs7) {
        BIO_free(input);
        return NULL;
    }

    BIO_free(input);
    return pkcs7;
}
Esempio n. 10
0
/*! @brief est_convert_p7b64_to_pem() converts the base64 encoded
    PKCS7 response from the EST server into PEM format.   
 
    @param certs_p7 Points to a buffer containing the base64 encoded pkcs7 data.
    @param certs_len Indicates the size of the *certs_p7 buffer.
    @param pem Double pointer that will receive the PEM encoded data. 
 
    Several of the EST message return data that contains base64 encoded PKCS7
    certificates.  This function is used to convert the data to PEM format.
    This function will allocate memory pointed to by the **pem argument.
    The caller is responsible for releasing this memory.  The return value
    is the length of the PEM buffer, or -1 on error.
 
    @return int.
 */
int est_convert_p7b64_to_pem (unsigned char *certs_p7, int certs_len, unsigned char **pem)
{
    X509 *x;
    STACK_OF(X509) *certs = NULL;
    BIO *b64, *in, *out;
    unsigned char *cacerts_decoded = NULL;
    int  cacerts_decoded_len = 0;
    BIO *p7bio_in = NULL;
    PKCS7 *p7=NULL;
    int i, nid;
    unsigned char *pem_data;
    int pem_len;

    /*
     * Base64 decode the incoming ca certs buffer.  Decoding will
     * always take up no more than the original buffer.
     */
    b64 = BIO_new(BIO_f_base64());
    if (!b64) {
	EST_LOG_ERR("BIO_new failed");
	return (-1);
    }    
    in = BIO_new_mem_buf(certs_p7, certs_len);    
    if (!in) {
	EST_LOG_ERR("BIO_new failed");
	return (-1);
    }
    in = BIO_push(b64, in);    
    cacerts_decoded = malloc(certs_len);
    if (!cacerts_decoded) {
	EST_LOG_ERR("malloc failed");
	return (-1);
    }
    cacerts_decoded_len = BIO_read(in, cacerts_decoded, certs_len);    
    BIO_free_all(in);
    /*
     * Now get the PKCS7 formatted buffer of certificates read into a stack of
     * X509 certs
     */
    p7bio_in = BIO_new_mem_buf(cacerts_decoded, cacerts_decoded_len);
    p7 = d2i_PKCS7_bio(p7bio_in, NULL);
    if (!p7) {
	EST_LOG_ERR("PEM_read_bio_PKCS7 failed");
	ossl_dump_ssl_errors();
        free(cacerts_decoded);
	return (-1);
    }
    BIO_free_all(p7bio_in);
    free(cacerts_decoded);
    
    /*
     * Now that we've decoded the certs, get a reference
     * the the stack of certs
     */
    nid=OBJ_obj2nid(p7->type);
    switch (nid)
        {
        case NID_pkcs7_signed:
            certs = p7->d.sign->cert;
            break;
        case NID_pkcs7_signedAndEnveloped:
            certs = p7->d.signed_and_enveloped->cert;
            break;
        default:
            EST_LOG_ERR("Invalid NID value on PKCS7 structure");
	    PKCS7_free(p7);
	    return (-1);
            break;
        }

    if (!certs) {
        EST_LOG_ERR("Failed to attain X509 cert stack from PKCS7 data");
	PKCS7_free(p7);
	return (-1);
    }

    /*
     * Output the certs to a new BIO using the PEM format 
     */
    out = BIO_new(BIO_s_mem());
    if (!out) {
        EST_LOG_ERR("BIO_new failed");
	PKCS7_free(p7);
	return (-1);
    }
    for (i=0; i<sk_X509_num(certs); i++) {
        x=sk_X509_value(certs, i);
	PEM_write_bio_X509(out, x);
	BIO_puts(out, "\n");
    }
    (void)BIO_flush(out);

    /*
     * Now convert the BIO to char*
     */
    pem_len = (int) BIO_get_mem_data(out, (char**)&pem_data);
    if (pem_len <= 0) {
        EST_LOG_ERR("BIO_get_mem_data failed");
	PKCS7_free(p7);
	return (-1);
    }

    *pem = malloc(pem_len + 1);
    if (!*pem) {
        EST_LOG_ERR("malloc failed");
	PKCS7_free(p7);
	return (-1);
    }
    memcpy(*pem, pem_data, pem_len);   
    (*pem)[pem_len] = 0;  //Make sure it's null termianted
    BIO_free_all(out);
    PKCS7_free(p7);
    return (pem_len);
}
Esempio n. 11
0
extern "C" PKCS7* D2IPkcs7Bio(BIO* bp)
{
    return d2i_PKCS7_bio(bp, nullptr);
}
Esempio n. 12
0
/*
 * Open the inner, decrypted PKCS7 and try to write CA/RA certificates 
 */
int
write_ca_ra(struct http_reply *s) {
	BIO			*bio;
	PKCS7			*p7;
	STACK_OF(X509)		*certs = NULL;
	X509			*cert = NULL;
	FILE			*fp = NULL;
	int			c, i, index;
        unsigned int		n;
        unsigned char		md[EVP_MAX_MD_SIZE];
	X509_EXTENSION		*ext;

	/* Create read-only memory bio */
	bio = BIO_new_mem_buf(s->payload, s->bytes);
	p7 = d2i_PKCS7_bio(bio, NULL);
	if (p7 == NULL) {
		fprintf(stderr, "%s: error reading PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_FILE);
	}
	/* Get certs */
	i = OBJ_obj2nid(p7->type);
	switch (i) {
		case NID_pkcs7_signed:
			certs = p7->d.sign->cert;
			break;
		default:
			printf("%s: wrong PKCS#7 type\n", pname);
			exit (SCEP_PKISTATUS_FILE);
	}
	/* Check  */
	if (certs == NULL) {
		fprintf(stderr, "%s: cannot find certificates\n", pname);
		exit (SCEP_PKISTATUS_FILE);
	} 

	/* Verify the chain
	 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	 */
	/* Find cert */
	for (i = 0; i < sk_X509_num(certs); i++) {
		char buffer[1024];
		char name[1024];

		memset(buffer, 0, 1024);
		memset(name, 0, 1024);
		cert = sk_X509_value(certs, i);

		/* Create name */
		snprintf(name, 1024, "%s-%d", c_char, i);

		/* Read and print certificate information */
		printf("\n%s: found certificate with\n  subject: %s\n", pname,
		X509_NAME_oneline(X509_get_subject_name(cert),
					buffer, sizeof(buffer)));
		printf("  issuer: %s\n", 
			X509_NAME_oneline(X509_get_issuer_name(cert),
					buffer, sizeof(buffer)));
		if (!X509_digest(cert, fp_alg, md, &n)) {
			ERR_print_errors_fp(stderr);
			exit (SCEP_PKISTATUS_FILE);
		}
		/* Print key usage: */
		index = X509_get_ext_by_NID(cert, NID_key_usage, -1);
		if (index < 0) {
			if (v_flag)
				fprintf(stderr, "%s: cannot find key usage\n",
					pname);
			/* exit (SCEP_PKISTATUS_FILE); */
		} else {
			ext = X509_get_ext(cert, index);
			printf("  usage: ");
			X509V3_EXT_print_fp(stdout, ext, 0, 0);
			printf("\n");
		}

		printf("  %s fingerprint: ", OBJ_nid2sn(EVP_MD_type(fp_alg)));
		for (c = 0; c < (int)n; c++) {
			printf("%02X%c",md[c], (c + 1 == (int)n) ?'\n':':');
		}

		/* Write PEM-formatted file: */
		if (!(fp = fopen(name, "w"))) {
			fprintf(stderr, "%s: cannot open cert file for "
				"writing\n", pname);
			exit (SCEP_PKISTATUS_FILE);
		}
		if (v_flag)
			printf("%s: writing cert\n", pname);
		if (d_flag)
			PEM_write_X509(stdout, cert);
		if (PEM_write_X509(fp, cert) != 1) {
			fprintf(stderr, "%s: error while writing certificate "
				"file\n", pname);
			ERR_print_errors_fp(stderr);
			exit (SCEP_PKISTATUS_FILE);
		}
		printf("%s: certificate written as %s\n", pname, name);
	}
	(void)fclose(fp);
	exit (SCEP_PKISTATUS_SUCCESS);
}
Esempio n. 13
0
static int verify_sig(char *sig, int sig_len, char *file, int (*byte_range)[2], int byte_range_len, char *ebuf, int ebufsize)
{
	PKCS7 *pk7sig = NULL;
	PKCS7 *pk7cert = NULL;
	X509_STORE *st = NULL;
	BIO *bsig = NULL;
	BIO *bcert = NULL;
	BIO *bdata = NULL;
	BIO *bsegs = NULL;
	STACK_OF(X509) *certs = NULL;
	int t;
	int res = 0;

	bsig = BIO_new_mem_buf(sig, sig_len);
	pk7sig = d2i_PKCS7_bio(bsig, NULL);
	if (pk7sig == NULL)
		goto exit;

	bdata = BIO_new(BIO_s_file());
	if (bdata == NULL)
		goto exit;
	BIO_read_filename(bdata, file);

	bsegs = BIO_new(BIO_f_segments());
	if (bsegs == NULL)
		goto exit;

	bsegs->next_bio = bdata;
	BIO_set_segments(bsegs, byte_range, byte_range_len);

	/* Find the certificates in the pk7 file */
	bcert = BIO_new_mem_buf(adobe_ca, sizeof(adobe_ca));
	pk7cert = d2i_PKCS7_bio(bcert, NULL);
	if (pk7cert == NULL)
		goto exit;

	t = OBJ_obj2nid(pk7cert->type);
	switch (t)
	{
	case NID_pkcs7_signed:
		certs = pk7cert->d.sign->cert;
		break;

	case NID_pkcs7_signedAndEnveloped:
		certs = pk7cert->d.sign->cert;
		break;

	default:
		break;
	}

	st = X509_STORE_new();
	if (st == NULL)
		goto exit;

	/* Add the certificates to the store */
	if (certs != NULL)
	{
		int i, n = sk_X509_num(certs);

		for (i = 0; i < n; i++)
		{
			X509 *c = sk_X509_value(certs, i);
			X509_STORE_add_cert(st, c);
		}
	}

	res = pk7_verify(st, pk7sig, bsegs, ebuf, ebufsize);

exit:
	BIO_free(bsig);
	BIO_free(bdata);
	BIO_free(bsegs);
	BIO_free(bcert);
	PKCS7_free(pk7sig);
	PKCS7_free(pk7cert);
	X509_STORE_free(st);

	return res;
}
Esempio n. 14
0
/*******************************************************************************
函数名称: cert_pkcs7_unwrap
功能描述: 解析从服务器收到的信息,包括验证签名以及解密。
输入参数: struct scep *s, SCEP操作的结构体指针。

输出参数: 无
返 回 值: 1,成功;-1,失败
--------------------------------------------------------------------------------
最近一次修改记录:
修改作者:王朝
修改目的:添加新函数
修改日期:2009年12月28日
*********************************************************************************/
s32 cert_pkcs7_unwrap(struct scep *s)
{
	BIO	*memorybio = NULL;
	BIO	*outbio = NULL;
	BIO	*pkcs7bio = NULL;
	s32	bytes, used, retval = -1;
	STACK_OF(PKCS7_SIGNER_INFO)	*sk = NULL;
	PKCS7 *p7enc = NULL;
	PKCS7_SIGNER_INFO *si = NULL;
	STACK_OF(X509_ATTRIBUTE) *attribs = NULL;
	s8 *p = NULL;
	u8 buffer[1024];
	X509 *recipientcert = NULL;
	EVP_PKEY *recipientkey = NULL;


	/* Create new memory BIO for outer PKCS#7 */
	memorybio = BIO_new(BIO_s_mem());

	/* Read in data */
	if ((BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0)
    {
        goto end;
	}

	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY);
	s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL);

    BIO_free(memorybio);
    memorybio = NULL;

	 /* Make sure this is a signed PKCS#7 */
    if (!PKCS7_type_is_signed(s->reply_p7))
    {
        goto end;
    }

	/* Create BIO for content data */
	pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL);
	if (pkcs7bio == NULL)
    {
        goto end;
	}

	/* */
	outbio = BIO_new(BIO_s_mem());
	used = 0;
	for (;;)
    {
		bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer));
		used += bytes;
		if (bytes <= 0) break;
		BIO_write(outbio, buffer, bytes);
	}
	(void)BIO_flush(outbio);

	/* Get signer */
	sk = PKCS7_get_signer_info(s->reply_p7);
	if (sk == NULL)
    {
        goto end;
	}

	/* Verify signature */
	si = sk_PKCS7_SIGNER_INFO_value(sk, 0);

	if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cert_cacert) <= 0)
    {
        goto end;
	}

	/* Get signed attributes */
	attribs = PKCS7_get_signed_attributes(si);
	if (attribs == NULL)
    {
        goto end;
	}

	/* Transaction id */
	if (1 != cert_get_signed_attribute(attribs, nid_transId,	V_ASN1_PRINTABLESTRING, &p))
    {
        goto end;
	}

	if (strncmp(s->transaction_id, p, strlen(p)))
    {
        goto end;
	}
	/* Message type, should be of type CertRep */
	if (1 != cert_get_signed_attribute(attribs, nid_messageType,	V_ASN1_PRINTABLESTRING, &p))
    {
        goto end;
	}
	if (atoi(p) != 3)
    {
        goto end;
	}

	/* Sender and recipient nonces: */
	if (1 == cert_get_signed_attribute(attribs, nid_senderNonce,	V_ASN1_OCTET_STRING, &p))
    {
		s->reply_sender_nonce = (u8 *)p;
	}
    else
    {
	    s->reply_sender_nonce = NULL;
    }
    
	if ( 1 != cert_get_signed_attribute(attribs, nid_recipientNonce,V_ASN1_OCTET_STRING, &p))
    {
		goto end;
	}
	s->reply_recipient_nonce = (u8 *)p;

	/* Get pkiStatus */
	if (1 != cert_get_signed_attribute(attribs, nid_pkiStatus,V_ASN1_PRINTABLESTRING, &p))
    {
		goto end;
	}
	switch (atoi(p))
    {
		case SCEP_PKISTATUS_SUCCESS:
			s->pki_status = SCEP_PKISTATUS_SUCCESS;
			break;
		case SCEP_PKISTATUS_FAILURE:
			s->pki_status = SCEP_PKISTATUS_FAILURE;
			break;
		case SCEP_PKISTATUS_PENDING:
			s->pki_status = SCEP_PKISTATUS_PENDING;
			break;
		default:
			goto end;
	}

	/* Get failInfo */
	if (s->pki_status == SCEP_PKISTATUS_FAILURE)
    {
		if (1 != cert_get_signed_attribute(attribs, nid_failInfo,V_ASN1_PRINTABLESTRING, &p)) 
        {
            goto end;
		}
		switch (atoi(p))
        {
			case SCEP_FAILINFO_BADALG:
				s->fail_info = SCEP_FAILINFO_BADALG;
				break;
			case SCEP_FAILINFO_BADMSGCHK:
				s->fail_info = SCEP_FAILINFO_BADMSGCHK;
				break;
			case SCEP_FAILINFO_BADREQ:
				s->fail_info = SCEP_FAILINFO_BADREQ;
				break;
			case SCEP_FAILINFO_BADTIME:
				s->fail_info = SCEP_FAILINFO_BADTIME;
				break;
			case SCEP_FAILINFO_BADCERTID:
				s->fail_info = SCEP_FAILINFO_BADCERTID;
				break;
			default:
				goto end;
		}
	}
	/* If FAILURE or PENDING, we can return */
	if (s->pki_status != SCEP_PKISTATUS_SUCCESS)
    {
		/* There shouldn't be any more data... */
		retval = 1;
        goto end;
	}
	/* We got success and expect data */
	if (used == 0)
    {
		goto end;
	}

	/* Decrypt the inner PKCS#7 */
	if ((s->request_type == SCEP_REQUEST_PKCSREQ) || (s->request_type == SCEP_REQUEST_GETCERTINIT))
    {
		recipientcert = s->signercert;
		recipientkey = s->signerkey;
	}
	else
    {
		recipientcert = cert_localcert;
		recipientkey = cert_rsa;
	}

	p7enc = d2i_PKCS7_bio(outbio, NULL);
	if (p7enc == NULL)
    {
		goto end;
	}

    BIO_free(outbio);
    outbio = NULL;

	/* Decrypt the data  */
	outbio = BIO_new(BIO_s_mem());
	if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0)
    {
		goto end;
	}
	(void)BIO_flush(outbio);

	/* Write decrypted data */
	s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload);

	BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY);
	s->reply_p7 = d2i_PKCS7_bio(outbio, NULL);

    retval = 1;
end:
    if(NULL != outbio)
    {
        BIO_free(outbio);
    }

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

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

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

    return retval;
}
Esempio n. 15
0
int MAIN(int argc, char **argv)
	{
	ENGINE *e = NULL;
	int operation = 0;
	int ret = 0;
	char **args;
	const char *inmode = "r", *outmode = "w";
	char *infile = NULL, *outfile = NULL;
	char *signerfile = NULL, *recipfile = NULL;
	char *certfile = NULL, *keyfile = NULL, *contfile=NULL;
	const EVP_CIPHER *cipher = NULL;
	PKCS7 *p7 = NULL;
	X509_STORE *store = NULL;
	X509 *cert = NULL, *recip = NULL, *signer = NULL;
	EVP_PKEY *key = NULL;
	STACK_OF(X509) *encerts = NULL, *other = NULL;
	BIO *in = NULL, *out = NULL, *indata = NULL;
	int badarg = 0;
	int flags = PKCS7_DETACHED;
	char *to = NULL, *from = NULL, *subject = NULL;
	char *CAfile = NULL, *CApath = NULL;
	char *passargin = NULL, *passin = NULL;
	char *inrand = NULL;
	int need_rand = 0;
	int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
        int keyform = FORMAT_PEM;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif

	X509_VERIFY_PARAM *vpm = NULL;

	args = argv + 1;
	ret = 1;

	apps_startup();

	if (bio_err == NULL)
		{
		if ((bio_err = BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err, stderr, BIO_NOCLOSE|BIO_FP_TEXT);
		}

	if (!load_config(bio_err, NULL))
		goto end;

	while (!badarg && *args && *args[0] == '-')
		{
		if (!strcmp (*args, "-encrypt"))
			operation = SMIME_ENCRYPT;
		else if (!strcmp (*args, "-decrypt"))
			operation = SMIME_DECRYPT;
		else if (!strcmp (*args, "-sign"))
			operation = SMIME_SIGN;
		else if (!strcmp (*args, "-verify"))
			operation = SMIME_VERIFY;
		else if (!strcmp (*args, "-pk7out"))
			operation = SMIME_PK7OUT;
#ifndef OPENSSL_NO_DES
		else if (!strcmp (*args, "-des3")) 
				cipher = EVP_des_ede3_cbc();
		else if (!strcmp (*args, "-des")) 
				cipher = EVP_des_cbc();
#endif
#ifndef OPENSSL_NO_SEED
		else if (!strcmp (*args, "-seed")) 
				cipher = EVP_seed_cbc();
#endif
#ifndef OPENSSL_NO_RC2
		else if (!strcmp (*args, "-rc2-40")) 
				cipher = EVP_rc2_40_cbc();
		else if (!strcmp (*args, "-rc2-128")) 
				cipher = EVP_rc2_cbc();
		else if (!strcmp (*args, "-rc2-64")) 
				cipher = EVP_rc2_64_cbc();
#endif
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args,"-aes128"))
				cipher = EVP_aes_128_cbc();
		else if (!strcmp(*args,"-aes192"))
				cipher = EVP_aes_192_cbc();
		else if (!strcmp(*args,"-aes256"))
				cipher = EVP_aes_256_cbc();
#endif
#ifndef OPENSSL_NO_CAMELLIA
		else if (!strcmp(*args,"-camellia128"))
				cipher = EVP_camellia_128_cbc();
		else if (!strcmp(*args,"-camellia192"))
				cipher = EVP_camellia_192_cbc();
		else if (!strcmp(*args,"-camellia256"))
				cipher = EVP_camellia_256_cbc();
#endif
		else if (!strcmp (*args, "-text")) 
				flags |= PKCS7_TEXT;
		else if (!strcmp (*args, "-nointern")) 
				flags |= PKCS7_NOINTERN;
		else if (!strcmp (*args, "-noverify")) 
				flags |= PKCS7_NOVERIFY;
		else if (!strcmp (*args, "-nochain")) 
				flags |= PKCS7_NOCHAIN;
		else if (!strcmp (*args, "-nocerts")) 
				flags |= PKCS7_NOCERTS;
		else if (!strcmp (*args, "-noattr")) 
				flags |= PKCS7_NOATTR;
		else if (!strcmp (*args, "-nodetach")) 
				flags &= ~PKCS7_DETACHED;
		else if (!strcmp (*args, "-nosmimecap"))
				flags |= PKCS7_NOSMIMECAP;
		else if (!strcmp (*args, "-binary"))
				flags |= PKCS7_BINARY;
		else if (!strcmp (*args, "-nosigs"))
				flags |= PKCS7_NOSIGS;
		else if (!strcmp (*args, "-nooldmime"))
				flags |= PKCS7_NOOLDMIMETYPE;
		else if (!strcmp (*args, "-crlfeol"))
				flags |= PKCS7_CRLFEOL;
		else if (!strcmp(*args,"-rand"))
			{
			if (args[1])
				{
				args++;
				inrand = *args;
				}
			else
				badarg = 1;
			need_rand = 1;
			}
#ifndef OPENSSL_NO_ENGINE
		else if (!strcmp(*args,"-engine"))
			{
			if (args[1])
				{
				args++;
				engine = *args;
				}
			else badarg = 1;
			}
#endif
		else if (!strcmp(*args,"-passin"))
			{
			if (args[1])
				{
				args++;
				passargin = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-to"))
			{
			if (args[1])
				{
				args++;
				to = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-from"))
			{
			if (args[1])
				{
				args++;
				from = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-subject"))
			{
			if (args[1])
				{
				args++;
				subject = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-signer"))
			{
			if (args[1])
				{
				args++;
				signerfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-recip"))
			{
			if (args[1])
				{
				args++;
				recipfile = *args;
				}
			else badarg = 1;
			}
		else if (!strcmp (*args, "-inkey"))
			{
			if (args[1])
				{
				args++;
				keyfile = *args;
				}
			else
				badarg = 1;
		}
		else if (!strcmp (*args, "-keyform"))
			{
			if (args[1])
				{
				args++;
				keyform = str2fmt(*args);
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-certfile"))
			{
			if (args[1])
				{
				args++;
				certfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-CAfile"))
			{
			if (args[1])
				{
				args++;
				CAfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-CApath"))
			{
			if (args[1])
				{
				args++;
				CApath = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-in"))
			{
			if (args[1])
				{
				args++;
				infile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-inform"))
			{
			if (args[1])
				{
				args++;
				informat = str2fmt(*args);
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-outform"))
			{
			if (args[1])
				{
				args++;
				outformat = str2fmt(*args);
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-out"))
			{
			if (args[1])
				{
				args++;
				outfile = *args;
				}
			else
				badarg = 1;
			}
		else if (!strcmp (*args, "-content"))
			{
			if (args[1])
				{
				args++;
				contfile = *args;
				}
			else
				badarg = 1;
			}
		else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
			continue;
		else
			badarg = 1;
		args++;
		}


	if (operation == SMIME_SIGN)
		{
		if (!signerfile)
			{
			BIO_printf(bio_err, "No signer certificate specified\n");
			badarg = 1;
			}
		need_rand = 1;
		}
	else if (operation == SMIME_DECRYPT)
		{
		if (!recipfile && !keyfile)
			{
			BIO_printf(bio_err, "No recipient certificate or key specified\n");
			badarg = 1;
			}
		}
	else if (operation == SMIME_ENCRYPT)
		{
		if (!*args)
			{
			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
			badarg = 1;
			}
		need_rand = 1;
		}
	else if (!operation)
		badarg = 1;

	if (badarg)
		{
		BIO_printf (bio_err, "Usage smime [options] cert.pem ...\n");
		BIO_printf (bio_err, "where options are\n");
		BIO_printf (bio_err, "-encrypt       encrypt message\n");
		BIO_printf (bio_err, "-decrypt       decrypt encrypted message\n");
		BIO_printf (bio_err, "-sign          sign message\n");
		BIO_printf (bio_err, "-verify        verify signed message\n");
		BIO_printf (bio_err, "-pk7out        output PKCS#7 structure\n");
#ifndef OPENSSL_NO_DES
		BIO_printf (bio_err, "-des3          encrypt with triple DES\n");
		BIO_printf (bio_err, "-des           encrypt with DES\n");
#endif
#ifndef OPENSSL_NO_SEED
		BIO_printf (bio_err, "-seed          encrypt with SEED\n");
#endif
#ifndef OPENSSL_NO_RC2
		BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
		BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
		BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
#endif
#ifndef OPENSSL_NO_AES
		BIO_printf (bio_err, "-aes128, -aes192, -aes256\n");
		BIO_printf (bio_err, "               encrypt PEM output with cbc aes\n");
#endif
#ifndef OPENSSL_NO_CAMELLIA
		BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n");
		BIO_printf (bio_err, "               encrypt PEM output with cbc camellia\n");
#endif
		BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
		BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
		BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
		BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
		BIO_printf (bio_err, "-nodetach      use opaque signing\n");
		BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
		BIO_printf (bio_err, "-binary        don't translate message to text\n");
		BIO_printf (bio_err, "-certfile file other certificates file\n");
		BIO_printf (bio_err, "-signer file   signer certificate file\n");
		BIO_printf (bio_err, "-recip  file   recipient certificate file for decryption\n");
		BIO_printf (bio_err, "-in file       input file\n");
		BIO_printf (bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
		BIO_printf (bio_err, "-inkey file    input private key (if not signer or recipient)\n");
		BIO_printf (bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
		BIO_printf (bio_err, "-out file      output file\n");
		BIO_printf (bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
		BIO_printf (bio_err, "-content file  supply or override content for detached signature\n");
		BIO_printf (bio_err, "-to addr       to address\n");
		BIO_printf (bio_err, "-from ad       from address\n");
		BIO_printf (bio_err, "-subject s     subject\n");
		BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
		BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
		BIO_printf (bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
		BIO_printf (bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf (bio_err, "-engine e      use engine e, possibly a hardware device.\n");
#endif
		BIO_printf (bio_err, "-passin arg    input file pass phrase source\n");
		BIO_printf(bio_err,  "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err,  "               load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,  "               the random number generator\n");
		BIO_printf (bio_err, "cert.pem       recipient certificate(s) for encryption\n");
		goto end;
		}

#ifndef OPENSSL_NO_ENGINE
        e = setup_engine(bio_err, engine, 0);
#endif

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

	if (need_rand)
		{
		app_RAND_load_file(NULL, bio_err, (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_SIGN)
		flags &= ~PKCS7_DETACHED;

	if (operation & SMIME_OP)
		{
		if (flags & PKCS7_BINARY)
			inmode = "rb";
		if (outformat == FORMAT_ASN1)
			outmode = "wb";
		}
	else
		{
		if (flags & PKCS7_BINARY)
			outmode = "wb";
		if (informat == FORMAT_ASN1)
			inmode = "rb";
		}

	if (operation == SMIME_ENCRYPT)
		{
		if (!cipher)
			{
#ifndef OPENSSL_NO_RC2			
			cipher = EVP_rc2_40_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
			}
		encerts = sk_X509_new_null();
		while (*args)
			{
			if (!(cert = load_cert(bio_err,*args,FORMAT_PEM,
				NULL, e, "recipient certificate file")))
				{
#if 0				/* An appropriate message is already printed */
				BIO_printf(bio_err, "Can't read recipient certificate file %s\n", *args);
#endif
				goto end;
				}
			sk_X509_push(encerts, cert);
			cert = NULL;
			args++;
			}
		}

	if (signerfile && (operation == SMIME_SIGN))
		{
		if (!(signer = load_cert(bio_err,signerfile,FORMAT_PEM, NULL,
			e, "signer certificate")))
			{
#if 0			/* An appropri message has already been printed */
			BIO_printf(bio_err, "Can't read signer certificate file %s\n", signerfile);
#endif
			goto end;
			}
		}

	if (certfile)
		{
		if (!(other = load_certs(bio_err,certfile,FORMAT_PEM, NULL,
			e, "certificate file")))
			{
#if 0			/* An appropriate message has already been printed */
			BIO_printf(bio_err, "Can't read certificate file %s\n", certfile);
#endif
			ERR_print_errors(bio_err);
			goto end;
			}
		}

	if (recipfile && (operation == SMIME_DECRYPT))
		{
		if (!(recip = load_cert(bio_err,recipfile,FORMAT_PEM,NULL,
			e, "recipient certificate file")))
			{
#if 0			/* An appropriate message has alrady been printed */
			BIO_printf(bio_err, "Can't read recipient certificate file %s\n", recipfile);
#endif
			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(bio_err, keyfile, keyform, 0, passin, e,
			       "signing key file");
		if (!key)
			goto end;
		}

	if (infile)
		{
		if (!(in = BIO_new_file(infile, inmode)))
			{
			BIO_printf (bio_err,
				 "Can't open input file %s\n", infile);
			goto end;
			}
		}
	else
		in = BIO_new_fp(stdin, BIO_NOCLOSE);

	if (outfile)
		{
		if (!(out = BIO_new_file(outfile, outmode)))
			{
			BIO_printf (bio_err,
				 "Can't open output file %s\n", outfile);
			goto end;
			}
		}
	else
		{
		out = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		    BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		    out = BIO_push(tmpbio, out);
		}
#endif
		}

	if (operation == SMIME_VERIFY)
		{
		if (!(store = setup_verify(bio_err, CAfile, CApath)))
			goto end;
		X509_STORE_set_verify_cb_func(store, smime_cb);
		if (vpm)
			X509_STORE_set1_param(store, vpm);
		}


	ret = 3;

	if (operation == SMIME_ENCRYPT)
		p7 = PKCS7_encrypt(encerts, in, cipher, flags);
	else if (operation == SMIME_SIGN)
		{
		/* If detached data and SMIME output enable partial
		 * signing.
		 */
		if ((flags & PKCS7_DETACHED) && (outformat == FORMAT_SMIME))
			flags |= PKCS7_STREAM;
		p7 = PKCS7_sign(signer, key, other, in, flags);
		}
	else
		{
		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")))
				{
				BIO_printf(bio_err, "Can't read content file %s\n", contfile);
				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\n", to);
		if (from)
			BIO_printf(out, "From: %s\n", from);
		if (subject)
			BIO_printf(out, "Subject: %s\n", subject);
		if (outformat == FORMAT_SMIME) 
			SMIME_write_PKCS7(out, p7, in, flags);
		else if (outformat == FORMAT_PEM) 
			PEM_write_bio_PKCS7(out,p7);
		else if (outformat == FORMAT_ASN1) 
			i2d_PKCS7_bio(out,p7);
		else
			{
			BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
			goto end;
			}
		}
	ret = 0;
end:
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
	if (ret) ERR_print_errors(bio_err);
	sk_X509_pop_free(encerts, X509_free);
	sk_X509_pop_free(other, X509_free);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	X509_STORE_free(store);
	X509_free(cert);
	X509_free(recip);
	X509_free(signer);
	EVP_PKEY_free(key);
	PKCS7_free(p7);
	BIO_free(in);
	BIO_free(indata);
	BIO_free_all(out);
	if (passin) OPENSSL_free(passin);
	return (ret);
}
Esempio n. 16
0
File: pkcs7.c Progetto: OPSF/uClinux
/*
 * Unwrap PKCS#7 data and decrypt if necessary
 */
int pkcs7_unwrap(struct scep *s) {
	BIO				*memorybio;
	BIO				*outbio;
	BIO				*pkcs7bio;
	int				i, len, bytes, used;
	STACK_OF(PKCS7_SIGNER_INFO)	*sk;
	PKCS7				*p7enc;
	PKCS7_SIGNER_INFO		*si;
	STACK_OF(X509_ATTRIBUTE)	*attribs;
	char				*p;
	unsigned char			buffer[1024];
	X509				*recipientcert;
	EVP_PKEY			*recipientkey;

	/* Create new memory BIO for outer PKCS#7 */
	memorybio = BIO_new(BIO_s_mem());

	/* Read in data */
	if (v_flag)
		printf("%s: reading outer PKCS#7\n",pname);
	if ((len = BIO_write(memorybio, s->reply_payload, s->reply_len)) <= 0) {
		fprintf(stderr, "%s: error reading PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: PKCS#7 payload size: %d bytes\n", pname, len);
	BIO_set_flags(memorybio, BIO_FLAGS_MEM_RDONLY); 
	s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL);
	if (d_flag) {
		printf("%s: printing PEM fomatted PKCS#7\n", pname);
		PEM_write_PKCS7(stdout, s->reply_p7);
	}

	 /* Make sure this is a signed PKCS#7 */
        if (!PKCS7_type_is_signed(s->reply_p7)) {
		fprintf(stderr, "%s: PKCS#7 is not signed!\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
        }

	/* Create BIO for content data */
	pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL);
	if (pkcs7bio == NULL) {
		fprintf(stderr, "%s: cannot get PKCS#7 data\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Copy enveloped data from PKCS#7 */
	outbio = BIO_new(BIO_s_mem());
	used = 0;
	for (;;) {
		bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer));
		used += bytes;
		if (bytes <= 0) break;
		BIO_write(outbio, buffer, bytes);
	}
	BIO_flush(outbio);
	if (v_flag)
		printf("%s: PKCS#7 contains %d bytes of enveloped data\n",
			pname, used);

	/* Get signer */
	sk = PKCS7_get_signer_info(s->reply_p7);
	if (sk == NULL) {
		fprintf(stderr, "%s: cannot get signer info!\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Verify signature */
	if (v_flag)
		printf("%s: verifying signature\n", pname);
	si = sk_PKCS7_SIGNER_INFO_value(sk, 0);
	if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, cacert) <= 0) {
		fprintf(stderr, "%s: error verifying signature\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: signature ok\n", pname);

	/* Get signed attributes */
	if (v_flag)
		printf("%s: finding signed attributes\n", pname);
	attribs = PKCS7_get_signed_attributes(si);
	if (attribs == NULL) {
		fprintf(stderr, "%s: no attributes found\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Transaction id */
	if ((get_signed_attribute(attribs, nid_transId,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find transId\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: reply transaction id: %s\n", pname, p);
	if (strncmp(s->transaction_id, p, strlen(p))) {
		fprintf(stderr, "%s: transaction id mismatch\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	/* Message type, should be of type CertRep */
	if ((i = get_signed_attribute(attribs, nid_messageType,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find messageType\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	if (atoi(p) != 3) {
		fprintf(stderr, "%s: wrong message type in reply\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	if (v_flag)
		printf("%s: reply message type is good\n", pname);

	/* Sender and recipient nonces: */
	if ((i = get_signed_attribute(attribs, nid_senderNonce,
			V_ASN1_OCTET_STRING, &p)) == 1) {
		if (v_flag)
			fprintf(stderr, "%s: cannot find senderNonce\n", pname);
		/* Some implementations don't put in on reply */
		/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
		exit (SCEP_PKISTATUS_P7); */
	}
	s->reply_sender_nonce = p;
	if (v_flag) {
		printf("%s: senderNonce in reply: ", pname);
		for (i = 0; i < 16; i++) {
			printf("%02X", s->reply_sender_nonce[i]);
		}
		printf("\n");
	}
	if (( i = get_signed_attribute(attribs, nid_recipientNonce,
			V_ASN1_OCTET_STRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find recipientNonce\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}
	s->reply_recipient_nonce = p;
	if (v_flag) {
		printf("%s: recipientNonce in reply: ", pname);
		for (i = 0; i < 16; i++) {
			printf("%02X", s->reply_recipient_nonce[i]);
		}
		printf("\n");
	}
	/*
	 * Compare recipient nonce to original sender nonce 
	 * The draft says nothing about this, but it makes sense to me..
	 * XXXXXXXXXXXXXX check
	 */
	for (i = 0; i < 16; i++) {
		if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) {
			if (v_flag)
				fprintf(stderr, "%s: corrupted nonce "
					"received\n", pname);
			/* Instead of exit, break out */
			break;
		}
	}
	/* Get pkiStatus */
	if ((i = get_signed_attribute(attribs, nid_pkiStatus,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
		fprintf(stderr, "%s: cannot find pkiStatus\n", pname);
		/* This is a mandatory attribute.. */
		exit (SCEP_PKISTATUS_P7);
	}
	switch (atoi(p)) {
		case SCEP_PKISTATUS_SUCCESS:
			printf("%s: pkistatus: SUCCESS\n",pname);
			s->pki_status = SCEP_PKISTATUS_SUCCESS;
			break;
		case SCEP_PKISTATUS_FAILURE:
			printf("%s: pkistatus: FAILURE\n",pname);
			s->pki_status = SCEP_PKISTATUS_FAILURE;
			break;
		case SCEP_PKISTATUS_PENDING:
			printf("%s: pkistatus: PENDING\n",pname);
			s->pki_status = SCEP_PKISTATUS_PENDING;
			break;
		default:
			fprintf(stderr, "%s: wrong pkistatus in reply\n",pname);
			exit (SCEP_PKISTATUS_P7);
	}

	/* Get failInfo */
	if (s->pki_status == SCEP_PKISTATUS_FAILURE) {
		if ((i = get_signed_attribute(attribs, nid_failInfo,
			V_ASN1_PRINTABLESTRING, &p)) == 1) {
				fprintf(stderr, "%s: cannot find failInfo\n",
						pname);
				exit (SCEP_PKISTATUS_P7);
		}
		switch (atoi(p)) {
			case SCEP_FAILINFO_BADALG:
				s->fail_info = SCEP_FAILINFO_BADALG;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADALG_STR);
				break;
			case SCEP_FAILINFO_BADMSGCHK:
				s->fail_info = SCEP_FAILINFO_BADMSGCHK;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADMSGCHK_STR);
				break;
			case SCEP_FAILINFO_BADREQ:
				s->fail_info = SCEP_FAILINFO_BADREQ;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADREQ_STR);
				break;
			case SCEP_FAILINFO_BADTIME:
				s->fail_info = SCEP_FAILINFO_BADTIME;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADTIME_STR);
				break;
			case SCEP_FAILINFO_BADCERTID:		
				s->fail_info = SCEP_FAILINFO_BADCERTID;
				printf("%s: reason: %s\n", pname,
					SCEP_FAILINFO_BADCERTID_STR);
				break;
			default:
				fprintf(stderr, "%s: wrong failInfo in "							"reply\n",pname);
				exit (SCEP_PKISTATUS_P7);
		}
	}
	/* If FAILURE or PENDING, we can return */
	if (s->pki_status != SCEP_PKISTATUS_SUCCESS) {
		/* There shouldn't be any more data... */
		if (v_flag && (used != 0)) {
			fprintf(stderr, "%s: illegal size of payload\n", pname);
		}
		return (0);
	}
	/* We got success and expect data */
	if (used == 0) {
		fprintf(stderr, "%s: illegal size of payload\n", pname);
		exit (SCEP_PKISTATUS_P7);
	}

	/* Decrypt the inner PKCS#7 */
	if ((s->request_type == SCEP_REQUEST_PKCSREQ) ||
	    (s->request_type == SCEP_REQUEST_GETCERTINIT)) {
		recipientcert = s->signercert;
		recipientkey = s->signerkey;
	}
	else {
		recipientcert = localcert;
		recipientkey = rsa;
	}
	if (v_flag)
		printf("%s: reading inner PKCS#7\n",pname);
	p7enc = d2i_PKCS7_bio(outbio, NULL);
	if (p7enc == NULL) {
		fprintf(stderr, "%s: cannot read inner 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, p7enc);
	}

	/* Decrypt the data  */
	outbio = BIO_new(BIO_s_mem());
	if (v_flag)
		printf("%s: decrypting inner PKCS#7\n",pname);
	if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) {
		fprintf(stderr, "%s: error decrypting inner PKCS#7\n", pname);
		ERR_print_errors_fp(stderr);
		exit (SCEP_PKISTATUS_P7);
	}
	BIO_flush(outbio);

	/* Write decrypted data */
	s->reply_len = BIO_get_mem_data(outbio, &s->reply_payload);
	if (v_flag)
		printf("%s: PKCS#7 payload size: %d bytes\n", pname,
			s->reply_len);
	BIO_set_flags(outbio, BIO_FLAGS_MEM_RDONLY); 
	s->reply_p7 = d2i_PKCS7_bio(outbio, NULL);

	return (0);

}
Esempio n. 17
0
static int parse_pkcs7_data(const options_t *options, const CRYPT_DATA_BLOB *blob)
{
	int result = 0;
	const cert_format_e input_fmt = CERT_FORMAT_DER;
	PKCS7 *p7 = NULL;
	BIO *in = NULL;

	CRYPTO_malloc_init();
	ERR_load_crypto_strings();
	OpenSSL_add_all_algorithms();

	in = BIO_new_mem_buf(blob->pbData, blob->cbData);
	if (in == NULL) {
		result = -2;
		goto error;
	}

	switch (input_fmt) {
		default: EXIT_ERROR("unhandled input format for certificate");
		case CERT_FORMAT_DER:
			p7 = d2i_PKCS7_bio(in, NULL);
			break;
		case CERT_FORMAT_PEM:
			p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
			break;
	}
	if (p7 == NULL) {
		ERR_print_errors_fp(stderr);
		result = -3;
		goto error;
	}

	STACK_OF(X509) *certs = NULL;

	int type = OBJ_obj2nid(p7->type);
	switch (type) {
		default: break;
		case NID_pkcs7_signed: // PKCS7_type_is_signed(p7)
			certs = p7->d.sign->cert;
			break;
		case NID_pkcs7_signedAndEnveloped: // PKCS7_type_is_signedAndEnveloped(p7)
			certs = p7->d.signed_and_enveloped->cert;
			break;
	}

	const int numcerts = certs != NULL ? sk_X509_num(certs) : 0;
	for (int i = 0; i < numcerts; i++) {
		X509 *cert = sk_X509_value(certs, i);
		print_certificate(options->certout, options->certoutform, cert);
		// NOTE: Calling X509_free(cert) is unnecessary.
	}

	// Print whether certificate signature is valid
	if (numcerts > 0) {
		X509 *subject = sk_X509_value(certs, 0);
		X509 *issuer = sk_X509_value(certs, numcerts - 1);
		int valid_sig = X509_verify(subject, X509_get_pubkey(issuer));
		output("Signature", valid_sig == 1 ? "valid" : "invalid");
	}

	// Print signers
	if (numcerts > 0) {
		output_open_scope("signers", OUTPUT_SCOPE_TYPE_ARRAY);
		for (int i = 0; i < numcerts; i++) {
			X509 *cert = sk_X509_value(certs, i);
			X509_NAME *name = X509_get_subject_name(cert);

			int issuer_name_len = X509_NAME_get_text_by_NID(name, NID_commonName, NULL, 0);
			if (issuer_name_len > 0) {
				output_open_scope("signer", OUTPUT_SCOPE_TYPE_OBJECT);
				char issuer_name[issuer_name_len + 1];
				X509_NAME_get_text_by_NID(name, NID_commonName, issuer_name, issuer_name_len + 1);
				output("Issuer", issuer_name);
				output_close_scope(); // signer
			}
		}
		output_close_scope(); // signers
	}

error:
	if (p7 != NULL)
		PKCS7_free(p7);
	if (in != NULL)
		BIO_free(in);

	// Deallocate everything from OpenSSL_add_all_algorithms
	EVP_cleanup();
	// Deallocate everything from ERR_load_crypto_strings
	ERR_free_strings();

	return result;
}
Esempio n. 18
0
int pkcs7_main(int argc, char **argv)
{
    ENGINE *e = NULL;
    PKCS7 *p7 = NULL;
    BIO *in = NULL, *out = NULL;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM;
    char *infile = NULL, *outfile = NULL, *prog;
    int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1;
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, pkcs7_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(pkcs7_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_NOOUT:
            noout = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_PRINT:
            p7_print = 1;
            break;
        case OPT_PRINT_CERTS:
            print_certs = 1;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        }
    }
    argc = opt_num_rest();
    if (argc != 0)
        goto opthelp;

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

    if (informat == FORMAT_ASN1)
        p7 = d2i_PKCS7_bio(in, NULL);
    else
        p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
    if (p7 == NULL) {
        BIO_printf(bio_err, "unable to load PKCS7 object\n");
        ERR_print_errors(bio_err);
        goto end;
    }

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

    if (p7_print)
        PKCS7_print_ctx(out, p7, 0, NULL);

    if (print_certs) {
        STACK_OF(X509) *certs = NULL;
        STACK_OF(X509_CRL) *crls = NULL;

        i = OBJ_obj2nid(p7->type);
        switch (i) {
        case NID_pkcs7_signed:
            if (p7->d.sign != NULL) {
                certs = p7->d.sign->cert;
                crls = p7->d.sign->crl;
            }
            break;
        case NID_pkcs7_signedAndEnveloped:
            if (p7->d.signed_and_enveloped != NULL) {
                certs = p7->d.signed_and_enveloped->cert;
                crls = p7->d.signed_and_enveloped->crl;
            }
            break;
        default:
            break;
        }

        if (certs != NULL) {
            X509 *x;

            for (i = 0; i < sk_X509_num(certs); i++) {
                x = sk_X509_value(certs, i);
                if (text)
                    X509_print(out, x);
                else
                    dump_cert_text(out, x);

                if (!noout)
                    PEM_write_bio_X509(out, x);
                BIO_puts(out, "\n");
            }
        }
        if (crls != NULL) {
            X509_CRL *crl;

            for (i = 0; i < sk_X509_CRL_num(crls); i++) {
                crl = sk_X509_CRL_value(crls, i);

                X509_CRL_print_ex(out, crl, get_nameopt());

                if (!noout)
                    PEM_write_bio_X509_CRL(out, crl);
                BIO_puts(out, "\n");
            }
        }

        ret = 0;
        goto end;
    }

    if (!noout) {
        if (outformat == FORMAT_ASN1)
            i = i2d_PKCS7_bio(out, p7);
        else
            i = PEM_write_bio_PKCS7(out, p7);

        if (!i) {
            BIO_printf(bio_err, "unable to write pkcs7 object\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    }
    ret = 0;
 end:
    PKCS7_free(p7);
    release_engine(e);
    BIO_free(in);
    BIO_free_all(out);
    return ret;
}
Esempio n. 19
0
PKCS7* CryptoNative_D2IPkcs7Bio(BIO* bp)
{
    return d2i_PKCS7_bio(bp, NULL);
}
Esempio n. 20
0
extern "C" PKCS7* CryptoNative_D2IPkcs7Bio(BIO* bp)
{
    return d2i_PKCS7_bio(bp, nullptr);
}
Esempio n. 21
0
/*
 * This function performs a basic simple enroll using
 * a UID/PWD to identify the client to the server.  This
 * is used for a variet of test cases in this module.
 */
static void us898_test1 (void) 
{
    EST_CTX *ectx;
    EVP_PKEY *key;
    int rv;
    int pkcs7_len = 0;
    unsigned char *new_cert = NULL;
    PKCS7 *p7 = NULL;
    BIO *b64, *out;
    X509 *cert = NULL;
    STACK_OF(X509) *certs = NULL;
    int i;
    unsigned char *attr_data = NULL;
    int attr_len;

    LOG_FUNC_NM;

    /*
     * Create a client context 
     */
    ectx = est_client_init(cacerts, cacerts_len, 
                           EST_CERT_FORMAT_PEM,
                           client_manual_cert_verify);
    CU_ASSERT(ectx != NULL);

    /*
     * Set the authentication mode to use a user id/password
     */
    rv = est_client_set_auth(ectx, US898_UID, US898_PWD, NULL, NULL);
    CU_ASSERT(rv == EST_ERR_NONE);

    /*
     * Set the EST server address/port
     */
    est_client_set_server(ectx, US898_SERVER_IP, US898_SERVER_PORT);

    /*
     * generate a private key
     */
    key = generate_private_key();
    CU_ASSERT(key != NULL);

    /*
     * Get the latest CSR attributes
     */
    rv = est_client_get_csrattrs(ectx, &attr_data, &attr_len);
    CU_ASSERT(rv == EST_ERR_NONE);

    /*
     * Use the simplified API to enroll a CSR
     */
    rv = est_client_enroll(ectx, "TC-US898-1", &pkcs7_len, key);
    CU_ASSERT(rv == EST_ERR_NONE);
    if (rv != EST_ERR_NONE) return;

    /*
     * Retrieve the cert that was given to us by the EST server
     */
    if (rv == EST_ERR_NONE) {
	new_cert = malloc(pkcs7_len);
	CU_ASSERT(new_cert != NULL);
	rv = est_client_copy_enrolled_cert(ectx, new_cert);
	CU_ASSERT(rv == EST_ERR_NONE);
    }

    /*
     * Convert the cert to an X509.  Be warned this is
     * pure hackery.  
     */
    b64 = BIO_new(BIO_f_base64());
    out = BIO_new_mem_buf(new_cert, pkcs7_len);
    out = BIO_push(b64, out);
    p7 = d2i_PKCS7_bio(out,NULL);
    CU_ASSERT(p7 != NULL);
    BIO_free_all(out);
    i=OBJ_obj2nid(p7->type);
    switch (i) {
    case NID_pkcs7_signed:
	certs = p7->d.sign->cert;
	break;
    case NID_pkcs7_signedAndEnveloped:
	certs = p7->d.signed_and_enveloped->cert;
	break;
    default:
	break;
    }
    CU_ASSERT(certs != NULL);
    if (!certs) return;
    /* our new cert should be the one and only
     * cert in the pkcs7 blob.  We shouldn't have to
     * iterate through the full list to find it. */
    cert = sk_X509_value(certs, 0);
    CU_ASSERT(cert != NULL);


    /* 
     * Wow, that's a lot of work, but we finally have the X509.
     * (don't you just love OpenSSL!!!)
     * Now that we have an X509 representation of the cert,
     * let's try to re-enroll this cert with the CA
     */
    rv = est_client_reenroll(ectx, cert, &pkcs7_len, key);
    CU_ASSERT(rv == EST_ERR_NONE);

    /*
     * Cleanup
     */
    if (cert) X509_free(cert);
    EVP_PKEY_free(key);
    if (new_cert) free(new_cert);
    est_destroy(ectx);
}
Esempio n. 22
0
DVT_STATUS CERTIFICATE_FILE_CLASS::importPkcs7(const char* filename, bool, const char*)

//  DESCRIPTION     : Import certificates from a PKCS#7 formated file.
//  PRECONDITIONS   :
//  POSTCONDITIONS  :
//  EXCEPTIONS      : 
//  NOTES           : Returns MSG_OK, MSG_ERROR, MSG_FILE_NOT_EXIST, MSG_NO_VALUE, MSG_INVALID_PASSWORD
//<<===========================================================================
{
	DVT_STATUS status = MSG_ERROR;
	BIO* bio_ptr;
	unsigned long err;
	PKCS7 *p7_ptr = NULL;
	STACK_OF(X509) *certStack_ptr = NULL;
	int count = 0;


	// clear the error queue
	ERR_clear_error();

	// open the file
	bio_ptr = BIO_new(BIO_s_file_internal());
	if (bio_ptr == NULL)
	{
		openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "setting up to read PKCS #7 file");
		status = MSG_ERROR;
		goto end;
	}
	if (BIO_read_filename(bio_ptr, filename) <= 0)
	{
		err = ERR_peek_error();
		if ((ERR_GET_LIB(err) == ERR_LIB_SYS) && (ERR_GET_REASON(err) == ERROR_FILE_NOT_FOUND))
		{
			// file does not exist
			ERR_clear_error(); // eat any errors
			status = MSG_FILE_NOT_EXIST;
		}
		else
		{
			openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "opening PKCS #7 file for reading");
			status = MSG_ERROR;
		}
		goto end;
	}

	// try reading the file as a PEM file
	p7_ptr = PEM_read_bio_PKCS7(bio_ptr, NULL, NULL, NULL);

	if (p7_ptr == NULL)
	{
		err = ERR_peek_error();
		if ((ERR_GET_LIB(err) == ERR_LIB_PEM) && (ERR_GET_REASON(err) == PEM_R_NO_START_LINE))
		{
			// no PEM start line
			ERR_clear_error(); // eat any errors
			BIO_reset(bio_ptr); // reset the file to the beginning

			// try reading the file as DER
			p7_ptr = d2i_PKCS7_bio(bio_ptr, NULL);
		}
	}

	if (p7_ptr == NULL)
	{
		openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "reading PKCS #7 file");
		status = MSG_ERROR;
	}
	else
	{
		// get the certificates from the p7 structure
		int p7Type = OBJ_obj2nid(p7_ptr->type);
		switch (p7Type)
		{
		case NID_pkcs7_signed:
			certStack_ptr = p7_ptr->d.sign->cert;
			break;
		case NID_pkcs7_signedAndEnveloped:
			certStack_ptr = p7_ptr->d.signed_and_enveloped->cert;
			break;
		default:
			openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "unsupported PKCS #7 file type");
			status = MSG_ERROR;
			goto end;
		}


		if ((certStack_ptr != NULL) && (sk_X509_num(certStack_ptr) > 0))
		{
			X509* x509_ptr;

			// save each of the certificates
			while ((x509_ptr = sk_X509_shift(certStack_ptr)) != NULL)
			{
				if (!push(x509_ptr))
				{
					status = MSG_ERROR;
					goto end;
				}
				count++;
			}
		}

		if (count == 0)
		{
			status = MSG_NO_VALUE;
		}
		else
		{
			status = MSG_OK;
		}
	}

end:
	//	certStack_ptr freed by the PKCS7_free() below
	if (p7_ptr != NULL) PKCS7_free(p7_ptr);
	if (bio_ptr != NULL) BIO_free(bio_ptr);

	return status;
}
Esempio n. 23
0
int
smime_main(int argc, char **argv)
{
	ENGINE *e = NULL;
	int operation = 0;
	int ret = 0;
	char **args;
	const char *inmode = "r", *outmode = "w";
	char *infile = NULL, *outfile = NULL;
	char *signerfile = NULL, *recipfile = NULL;
	STACK_OF(OPENSSL_STRING) * sksigners = NULL, *skkeys = NULL;
	char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
	const EVP_CIPHER *cipher = NULL;
	PKCS7 *p7 = NULL;
	X509_STORE *store = NULL;
	X509 *cert = NULL, *recip = NULL, *signer = NULL;
	EVP_PKEY *key = NULL;
	STACK_OF(X509) * encerts = NULL, *other = NULL;
	BIO *in = NULL, *out = NULL, *indata = NULL;
	int badarg = 0;
	int flags = PKCS7_DETACHED;
	char *to = NULL, *from = NULL, *subject = NULL;
	char *CAfile = NULL, *CApath = NULL;
	char *passargin = NULL, *passin = NULL;
	int indef = 0;
	const EVP_MD *sign_md = NULL;
	int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
	int keyform = FORMAT_PEM;
#ifndef OPENSSL_NO_ENGINE
	char *engine = NULL;
#endif

	X509_VERIFY_PARAM *vpm = NULL;

	args = argv + 1;
	ret = 1;

	while (!badarg && *args && *args[0] == '-') {
		if (!strcmp(*args, "-encrypt"))
			operation = SMIME_ENCRYPT;
		else if (!strcmp(*args, "-decrypt"))
			operation = SMIME_DECRYPT;
		else if (!strcmp(*args, "-sign"))
			operation = SMIME_SIGN;
		else if (!strcmp(*args, "-resign"))
			operation = SMIME_RESIGN;
		else if (!strcmp(*args, "-verify"))
			operation = SMIME_VERIFY;
		else if (!strcmp(*args, "-pk7out"))
			operation = SMIME_PK7OUT;
#ifndef OPENSSL_NO_DES
		else if (!strcmp(*args, "-des3"))
			cipher = EVP_des_ede3_cbc();
		else if (!strcmp(*args, "-des"))
			cipher = EVP_des_cbc();
#endif
#ifndef OPENSSL_NO_RC2
		else if (!strcmp(*args, "-rc2-40"))
			cipher = EVP_rc2_40_cbc();
		else if (!strcmp(*args, "-rc2-128"))
			cipher = EVP_rc2_cbc();
		else if (!strcmp(*args, "-rc2-64"))
			cipher = EVP_rc2_64_cbc();
#endif
#ifndef OPENSSL_NO_AES
		else if (!strcmp(*args, "-aes128"))
			cipher = EVP_aes_128_cbc();
		else if (!strcmp(*args, "-aes192"))
			cipher = EVP_aes_192_cbc();
		else if (!strcmp(*args, "-aes256"))
			cipher = EVP_aes_256_cbc();
#endif
#ifndef OPENSSL_NO_CAMELLIA
		else if (!strcmp(*args, "-camellia128"))
			cipher = EVP_camellia_128_cbc();
		else if (!strcmp(*args, "-camellia192"))
			cipher = EVP_camellia_192_cbc();
		else if (!strcmp(*args, "-camellia256"))
			cipher = EVP_camellia_256_cbc();
#endif
		else if (!strcmp(*args, "-text"))
			flags |= PKCS7_TEXT;
		else if (!strcmp(*args, "-nointern"))
			flags |= PKCS7_NOINTERN;
		else if (!strcmp(*args, "-noverify"))
			flags |= PKCS7_NOVERIFY;
		else if (!strcmp(*args, "-nochain"))
			flags |= PKCS7_NOCHAIN;
		else if (!strcmp(*args, "-nocerts"))
			flags |= PKCS7_NOCERTS;
		else if (!strcmp(*args, "-noattr"))
			flags |= PKCS7_NOATTR;
		else if (!strcmp(*args, "-nodetach"))
			flags &= ~PKCS7_DETACHED;
		else if (!strcmp(*args, "-nosmimecap"))
			flags |= PKCS7_NOSMIMECAP;
		else if (!strcmp(*args, "-binary"))
			flags |= PKCS7_BINARY;
		else if (!strcmp(*args, "-nosigs"))
			flags |= PKCS7_NOSIGS;
		else if (!strcmp(*args, "-stream"))
			indef = 1;
		else if (!strcmp(*args, "-indef"))
			indef = 1;
		else if (!strcmp(*args, "-noindef"))
			indef = 0;
		else if (!strcmp(*args, "-nooldmime"))
			flags |= PKCS7_NOOLDMIMETYPE;
		else if (!strcmp(*args, "-crlfeol"))
			flags |= PKCS7_CRLFEOL;
#ifndef OPENSSL_NO_ENGINE
		else if (!strcmp(*args, "-engine")) {
			if (!args[1])
				goto argerr;
			engine = *++args;
		}
#endif
		else if (!strcmp(*args, "-passin")) {
			if (!args[1])
				goto argerr;
			passargin = *++args;
		} else if (!strcmp(*args, "-to")) {
			if (!args[1])
				goto argerr;
			to = *++args;
		} else if (!strcmp(*args, "-from")) {
			if (!args[1])
				goto argerr;
			from = *++args;
		} else if (!strcmp(*args, "-subject")) {
			if (!args[1])
				goto argerr;
			subject = *++args;
		} else if (!strcmp(*args, "-signer")) {
			if (!args[1])
				goto argerr;
			/* If previous -signer argument add signer to list */

			if (signerfile) {
				if (!sksigners)
					sksigners = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(sksigners, signerfile);
				if (!keyfile)
					keyfile = signerfile;
				if (!skkeys)
					skkeys = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(skkeys, keyfile);
				keyfile = NULL;
			}
			signerfile = *++args;
		} else if (!strcmp(*args, "-recip")) {
			if (!args[1])
				goto argerr;
			recipfile = *++args;
		} else if (!strcmp(*args, "-md")) {
			if (!args[1])
				goto argerr;
			sign_md = EVP_get_digestbyname(*++args);
			if (sign_md == NULL) {
				BIO_printf(bio_err, "Unknown digest %s\n",
				    *args);
				goto argerr;
			}
		} else if (!strcmp(*args, "-inkey")) {
			if (!args[1])
				goto argerr;
			/* If previous -inkey arument add signer to list */
			if (keyfile) {
				if (!signerfile) {
					BIO_puts(bio_err, "Illegal -inkey without -signer\n");
					goto argerr;
				}
				if (!sksigners)
					sksigners = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(sksigners, signerfile);
				signerfile = NULL;
				if (!skkeys)
					skkeys = sk_OPENSSL_STRING_new_null();
				sk_OPENSSL_STRING_push(skkeys, keyfile);
			}
			keyfile = *++args;
		} else if (!strcmp(*args, "-keyform")) {
			if (!args[1])
				goto argerr;
			keyform = str2fmt(*++args);
		} else if (!strcmp(*args, "-certfile")) {
			if (!args[1])
				goto argerr;
			certfile = *++args;
		} else if (!strcmp(*args, "-CAfile")) {
			if (!args[1])
				goto argerr;
			CAfile = *++args;
		} else if (!strcmp(*args, "-CApath")) {
			if (!args[1])
				goto argerr;
			CApath = *++args;
		} else if (!strcmp(*args, "-in")) {
			if (!args[1])
				goto argerr;
			infile = *++args;
		} else if (!strcmp(*args, "-inform")) {
			if (!args[1])
				goto argerr;
			informat = str2fmt(*++args);
		} else if (!strcmp(*args, "-outform")) {
			if (!args[1])
				goto argerr;
			outformat = str2fmt(*++args);
		} else if (!strcmp(*args, "-out")) {
			if (!args[1])
				goto argerr;
			outfile = *++args;
		} else if (!strcmp(*args, "-content")) {
			if (!args[1])
				goto argerr;
			contfile = *++args;
		} else if (args_verify(&args, NULL, &badarg, bio_err, &vpm))
			continue;
		else if ((cipher = EVP_get_cipherbyname(*args + 1)) == NULL)
			badarg = 1;
		args++;
	}

	if (!(operation & SMIME_SIGNERS) && (skkeys || sksigners)) {
		BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
		goto argerr;
	}
	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 argerr;
		}
		if (signerfile) {
			if (!sksigners)
				sksigners = sk_OPENSSL_STRING_new_null();
			sk_OPENSSL_STRING_push(sksigners, signerfile);
			if (!skkeys)
				skkeys = sk_OPENSSL_STRING_new_null();
			if (!keyfile)
				keyfile = signerfile;
			sk_OPENSSL_STRING_push(skkeys, keyfile);
		}
		if (!sksigners) {
			BIO_printf(bio_err, "No signer certificate specified\n");
			badarg = 1;
		}
		signerfile = NULL;
		keyfile = NULL;
	} else if (operation == SMIME_DECRYPT) {
		if (!recipfile && !keyfile) {
			BIO_printf(bio_err, "No recipient certificate or key specified\n");
			badarg = 1;
		}
	} else if (operation == SMIME_ENCRYPT) {
		if (!*args) {
			BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
			badarg = 1;
		}
	} else if (!operation)
		badarg = 1;

	if (badarg) {
argerr:
		BIO_printf(bio_err, "Usage smime [options] cert.pem ...\n");
		BIO_printf(bio_err, "where options are\n");
		BIO_printf(bio_err, "-encrypt       encrypt message\n");
		BIO_printf(bio_err, "-decrypt       decrypt encrypted message\n");
		BIO_printf(bio_err, "-sign          sign message\n");
		BIO_printf(bio_err, "-verify        verify signed message\n");
		BIO_printf(bio_err, "-pk7out        output PKCS#7 structure\n");
#ifndef OPENSSL_NO_DES
		BIO_printf(bio_err, "-des3          encrypt with triple DES\n");
		BIO_printf(bio_err, "-des           encrypt with DES\n");
#endif
#ifndef OPENSSL_NO_RC2
		BIO_printf(bio_err, "-rc2-40        encrypt with RC2-40 (default)\n");
		BIO_printf(bio_err, "-rc2-64        encrypt with RC2-64\n");
		BIO_printf(bio_err, "-rc2-128       encrypt with RC2-128\n");
#endif
#ifndef OPENSSL_NO_AES
		BIO_printf(bio_err, "-aes128, -aes192, -aes256\n");
		BIO_printf(bio_err, "               encrypt PEM output with cbc aes\n");
#endif
#ifndef OPENSSL_NO_CAMELLIA
		BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n");
		BIO_printf(bio_err, "               encrypt PEM output with cbc camellia\n");
#endif
		BIO_printf(bio_err, "-nointern      don't search certificates in message for signer\n");
		BIO_printf(bio_err, "-nosigs        don't verify message signature\n");
		BIO_printf(bio_err, "-noverify      don't verify signers certificate\n");
		BIO_printf(bio_err, "-nocerts       don't include signers certificate when signing\n");
		BIO_printf(bio_err, "-nodetach      use opaque signing\n");
		BIO_printf(bio_err, "-noattr        don't include any signed attributes\n");
		BIO_printf(bio_err, "-binary        don't translate message to text\n");
		BIO_printf(bio_err, "-certfile file other certificates file\n");
		BIO_printf(bio_err, "-signer file   signer certificate file\n");
		BIO_printf(bio_err, "-recip  file   recipient certificate file for decryption\n");
		BIO_printf(bio_err, "-in file       input file\n");
		BIO_printf(bio_err, "-inform arg    input format SMIME (default), PEM or DER\n");
		BIO_printf(bio_err, "-inkey file    input private key (if not signer or recipient)\n");
		BIO_printf(bio_err, "-keyform arg   input private key format (PEM or ENGINE)\n");
		BIO_printf(bio_err, "-out file      output file\n");
		BIO_printf(bio_err, "-outform arg   output format SMIME (default), PEM or DER\n");
		BIO_printf(bio_err, "-content file  supply or override content for detached signature\n");
		BIO_printf(bio_err, "-to addr       to address\n");
		BIO_printf(bio_err, "-from ad       from address\n");
		BIO_printf(bio_err, "-subject s     subject\n");
		BIO_printf(bio_err, "-text          include or delete text MIME headers\n");
		BIO_printf(bio_err, "-CApath dir    trusted certificates directory\n");
		BIO_printf(bio_err, "-CAfile file   trusted certificates file\n");
		BIO_printf(bio_err, "-crl_check     check revocation status of signer's certificate using CRLs\n");
		BIO_printf(bio_err, "-crl_check_all check revocation status of signer's certificate chain using CRLs\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err, "-engine e      use engine e, possibly a hardware device.\n");
#endif
		BIO_printf(bio_err, "-passin arg    input file pass phrase source\n");
		BIO_printf(bio_err, "cert.pem       recipient certificate(s) for encryption\n");
		goto end;
	}
#ifndef OPENSSL_NO_ENGINE
	e = setup_engine(bio_err, engine, 0);
#endif

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

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

	if (operation & SMIME_OP) {
		if (outformat == FORMAT_ASN1)
			outmode = "wb";
	} else {
		if (flags & PKCS7_BINARY)
			outmode = "wb";
	}

	if (operation & SMIME_IP) {
		if (informat == FORMAT_ASN1)
			inmode = "rb";
	} else {
		if (flags & PKCS7_BINARY)
			inmode = "rb";
	}

	if (operation == SMIME_ENCRYPT) {
		if (!cipher) {
#ifndef OPENSSL_NO_RC2
			cipher = EVP_rc2_40_cbc();
#else
			BIO_printf(bio_err, "No cipher selected\n");
			goto end;
#endif
		}
		encerts = sk_X509_new_null();
		while (*args) {
			if (!(cert = load_cert(bio_err, *args, FORMAT_PEM,
			    NULL, e, "recipient certificate file"))) {
				goto end;
			}
			sk_X509_push(encerts, cert);
			cert = NULL;
			args++;
		}
	}
	if (certfile) {
		if (!(other = load_certs(bio_err, certfile, FORMAT_PEM, NULL,
			    e, "certificate file"))) {
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	if (recipfile && (operation == SMIME_DECRYPT)) {
		if (!(recip = load_cert(bio_err, recipfile, FORMAT_PEM, NULL,
			    e, "recipient certificate file"))) {
			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(bio_err, keyfile, keyform, 0, passin, e,
		    "signing key file");
		if (!key)
			goto end;
	}
	if (infile) {
		if (!(in = BIO_new_file(infile, inmode))) {
			BIO_printf(bio_err,
			    "Can't open input file %s\n", infile);
			goto end;
		}
	} else
		in = BIO_new_fp(stdin, BIO_NOCLOSE);

	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"))) {
				BIO_printf(bio_err, "Can't read content file %s\n", contfile);
				goto end;
			}
		}
	}
	if (outfile) {
		if (!(out = BIO_new_file(outfile, outmode))) {
			BIO_printf(bio_err,
			    "Can't open output file %s\n", outfile);
			goto end;
		}
	} else {
		out = BIO_new_fp(stdout, BIO_NOCLOSE);
	}

	if (operation == SMIME_VERIFY) {
		if (!(store = setup_verify(bio_err, CAfile, CApath)))
			goto end;
		X509_STORE_set_verify_cb(store, smime_cb);
		if (vpm)
			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;
		} 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(bio_err, signerfile, FORMAT_PEM, NULL,
			    e, "signer certificate");
			if (!signer)
				goto end;
			key = load_key(bio_err, 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\n", to);
		if (from)
			BIO_printf(out, "From: %s\n", from);
		if (subject)
			BIO_printf(out, "Subject: %s\n", subject);
		if (outformat == FORMAT_SMIME) {
			if (operation == SMIME_RESIGN)
				SMIME_write_PKCS7(out, p7, indata, flags);
			else
				SMIME_write_PKCS7(out, p7, in, flags);
		} else if (outformat == FORMAT_PEM)
			PEM_write_bio_PKCS7_stream(out, p7, in, flags);
		else if (outformat == FORMAT_ASN1)
			i2d_PKCS7_bio_stream(out, p7, in, flags);
		else {
			BIO_printf(bio_err, "Bad output format for PKCS#7 file\n");
			goto end;
		}
	}
	ret = 0;
end:
	if (ret)
		ERR_print_errors(bio_err);
	sk_X509_pop_free(encerts, X509_free);
	sk_X509_pop_free(other, X509_free);
	if (vpm)
		X509_VERIFY_PARAM_free(vpm);
	if (sksigners)
		sk_OPENSSL_STRING_free(sksigners);
	if (skkeys)
		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);
	BIO_free(in);
	BIO_free(indata);
	BIO_free_all(out);
	free(passin);

	return (ret);
}
Esempio n. 24
0
int MAIN(int argc, char **argv)
	{
	PKCS7 *p7=NULL;
	int i,badops=0;
	BIO *in=NULL,*out=NULL;
	int informat,outformat;
	char *infile,*outfile,*prog;
	int print_certs=0,text=0,noout=0,p7_print=0;
	int ret=1;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif

	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,OPENSSL_TYPE__FILE_STDERR,BIO_NOCLOSE|BIO_FP_TEXT);

	if (!load_config(bio_err, NULL))
		goto end;

	infile=NULL;
	outfile=NULL;
	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

	prog=argv[0];
	argc--;
	argv++;
	while (argc >= 1)
		{
		if 	(TINYCLR_SSL_STRCMP(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-noout") == 0)
			noout=1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-text") == 0)
			text=1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-print") == 0)
			p7_print=1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-print_certs") == 0)
			print_certs=1;
#ifndef OPENSSL_NO_ENGINE
		else if (TINYCLR_SSL_STRCMP(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
#endif
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
		BIO_printf(bio_err,"where options are\n");
		BIO_printf(bio_err," -inform arg   input format - DER or PEM\n");
		BIO_printf(bio_err," -outform arg  output format - DER or PEM\n");
		BIO_printf(bio_err," -in arg       input file\n");
		BIO_printf(bio_err," -out arg      output file\n");
		BIO_printf(bio_err," -print_certs  print any certs or crl in the input\n");
		BIO_printf(bio_err," -text         print full details of certificates\n");
		BIO_printf(bio_err," -noout        don't output encoded data\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err," -engine e     use engine e, possibly a hardware device.\n");
#endif
		ret = 1;
		goto end;
		}

	ERR_load_crypto_strings();

#ifndef OPENSSL_NO_ENGINE
        setup_engine(bio_err, engine, 0);
#endif

	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		{
		ERR_print_errors(bio_err);
                goto end;
                }

	if (infile == NULL)
		BIO_set_fp(in,OPENSSL_TYPE__FILE_STDIN,BIO_NOCLOSE);
	else
		{
		if (BIO_read_filename(in,infile) <= 0)
		if (in == NULL)
			{
			TINYCLR_SSL_PERROR(infile);
			goto end;
			}
		}

	if	(informat == FORMAT_ASN1)
		p7=d2i_PKCS7_bio(in,NULL);
	else if (informat == FORMAT_PEM)
		p7=PEM_read_bio_PKCS7(in,NULL,NULL,NULL);
	else
		{
		BIO_printf(bio_err,"bad input format specified for pkcs7 object\n");
		goto end;
		}
	if (p7 == NULL)
		{
		BIO_printf(bio_err,"unable to load PKCS7 object\n");
		ERR_print_errors(bio_err);
		goto end;
		}

	if (outfile == NULL)
		{
		BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outfile) <= 0)
			{
			TINYCLR_SSL_PERROR(outfile);
			goto end;
			}
		}

	if (p7_print)
		PKCS7_print_ctx(out, p7, 0, NULL);

	if (print_certs)
		{
		STACK_OF(X509) *certs=NULL;
		STACK_OF(X509_CRL) *crls=NULL;

		i=OBJ_obj2nid(p7->type);
		switch (i)
			{
		case NID_pkcs7_signed:
			certs=p7->d.sign->cert;
			crls=p7->d.sign->crl;
			break;
		case NID_pkcs7_signedAndEnveloped:
			certs=p7->d.signed_and_enveloped->cert;
			crls=p7->d.signed_and_enveloped->crl;
			break;
		default:
			break;
			}

		if (certs != NULL)
			{
			X509 *x;

			for (i=0; i<sk_X509_num(certs); i++)
				{
				x=sk_X509_value(certs,i);
				if(text) X509_print(out, x);
				else dump_cert_text(out, x);

				if(!noout) PEM_write_bio_X509(out,x);
				BIO_puts(out,"\n");
				}
			}
		if (crls != NULL)
			{
			X509_CRL *crl;

			for (i=0; i<sk_X509_CRL_num(crls); i++)
				{
				crl=sk_X509_CRL_value(crls,i);

				X509_CRL_print(out, crl);

				if(!noout)PEM_write_bio_X509_CRL(out,crl);
				BIO_puts(out,"\n");
				}
			}

		ret=0;
		goto end;
		}

	if(!noout) {
		if 	(outformat == FORMAT_ASN1)
			i=i2d_PKCS7_bio(out,p7);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_PKCS7(out,p7);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}

		if (!i)
			{
			BIO_printf(bio_err,"unable to write pkcs7 object\n");
			ERR_print_errors(bio_err);
			goto end;
			}
	}
	ret=0;
end:
	if (p7 != NULL) PKCS7_free(p7);
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Esempio n. 25
0
int
pkcs7_main(int argc, char **argv)
{
	PKCS7 *p7 = NULL;
	BIO *in = NULL, *out = NULL;
	int ret = 1;
	int i;

	memset(&pkcs7_config, 0, sizeof(pkcs7_config));

	pkcs7_config.informat = FORMAT_PEM;
	pkcs7_config.outformat = FORMAT_PEM;

	if (options_parse(argc, argv, pkcs7_options, NULL, NULL) != 0) {
		pkcs7_usage();
		goto end;
	}

#ifndef OPENSSL_NO_ENGINE
	setup_engine(bio_err, pkcs7_config.engine, 0);
#endif

	in = BIO_new(BIO_s_file());
	out = BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL)) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (pkcs7_config.infile == NULL)
		BIO_set_fp(in, stdin, BIO_NOCLOSE);
	else {
		if (BIO_read_filename(in, pkcs7_config.infile) <= 0) {
			perror(pkcs7_config.infile);
			goto end;
		}
	}

	if (pkcs7_config.informat == FORMAT_ASN1)
		p7 = d2i_PKCS7_bio(in, NULL);
	else if (pkcs7_config.informat == FORMAT_PEM)
		p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
	else {
		BIO_printf(bio_err, "bad input format specified for pkcs7 object\n");
		goto end;
	}
	if (p7 == NULL) {
		BIO_printf(bio_err, "unable to load PKCS7 object\n");
		ERR_print_errors(bio_err);
		goto end;
	}
	if (pkcs7_config.outfile == NULL) {
		BIO_set_fp(out, stdout, BIO_NOCLOSE);
	} else {
		if (BIO_write_filename(out, pkcs7_config.outfile) <= 0) {
			perror(pkcs7_config.outfile);
			goto end;
		}
	}

	if (pkcs7_config.p7_print)
		PKCS7_print_ctx(out, p7, 0, NULL);

	if (pkcs7_config.print_certs) {
		STACK_OF(X509) * certs = NULL;
		STACK_OF(X509_CRL) * crls = NULL;

		i = OBJ_obj2nid(p7->type);
		switch (i) {
		case NID_pkcs7_signed:
			certs = p7->d.sign->cert;
			crls = p7->d.sign->crl;
			break;
		case NID_pkcs7_signedAndEnveloped:
			certs = p7->d.signed_and_enveloped->cert;
			crls = p7->d.signed_and_enveloped->crl;
			break;
		default:
			break;
		}

		if (certs != NULL) {
			X509 *x;

			for (i = 0; i < sk_X509_num(certs); i++) {
				x = sk_X509_value(certs, i);
				if (pkcs7_config.text)
					X509_print(out, x);
				else
					dump_cert_text(out, x);

				if (!pkcs7_config.noout)
					PEM_write_bio_X509(out, x);
				BIO_puts(out, "\n");
			}
		}
		if (crls != NULL) {
			X509_CRL *crl;

			for (i = 0; i < sk_X509_CRL_num(crls); i++) {
				crl = sk_X509_CRL_value(crls, i);

				X509_CRL_print(out, crl);

				if (!pkcs7_config.noout)
					PEM_write_bio_X509_CRL(out, crl);
				BIO_puts(out, "\n");
			}
		}
		ret = 0;
		goto end;
	}
	if (!pkcs7_config.noout) {
		if (pkcs7_config.outformat == FORMAT_ASN1)
			i = i2d_PKCS7_bio(out, p7);
		else if (pkcs7_config.outformat == FORMAT_PEM)
			i = PEM_write_bio_PKCS7(out, p7);
		else {
			BIO_printf(bio_err, "bad output format specified for outfile\n");
			goto end;
		}

		if (!i) {
			BIO_printf(bio_err, "unable to write pkcs7 object\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	ret = 0;
end:
	if (p7 != NULL)
		PKCS7_free(p7);
	if (in != NULL)
		BIO_free(in);
	if (out != NULL)
		BIO_free_all(out);

	return (ret);
}
Esempio n. 26
0
/* Verifies that the file and the signature exists, and does a signature check
 * afterwards. If any error is to be considered a verify failure, then
 * ERRORS_FATAL should be set to true.
 *
 * returns: true if able to validate the signature, false otherwise */
static bool verify_signature(const char *data_filename, const char *sig_filename, bool errors_fatal)
{
	int ret;
	bool result = false;
	struct stat st;
	char *errorstr = NULL;

	int data_fd = -1;
	size_t data_len;
	unsigned char *data = NULL;
	BIO *data_BIO = NULL;

	int sig_fd = -1;
	size_t sig_len;
	unsigned char *sig = NULL;
	BIO *sig_BIO = NULL;

	PKCS7 *p7 = NULL;
	BIO *verify_BIO = NULL;

	/* get the signature */
	sig_fd = open(sig_filename, O_RDONLY);
	if (sig_fd == -1) {
		string_or_die(&errorstr, "Failed open %s: %s\n", sig_filename, strerror(errno));
		goto error;
	}
	if (fstat(sig_fd, &st) != 0) {
		string_or_die(&errorstr, "Failed to stat %s file\n", sig_filename);
		goto error;
	}
	sig_len = st.st_size;
	sig = mmap(NULL, sig_len, PROT_READ, MAP_PRIVATE, sig_fd, 0);
	if (sig == MAP_FAILED) {
		string_or_die(&errorstr, "Failed to mmap %s signature\n", sig_filename);
		goto error;
	}
	sig_BIO = BIO_new_mem_buf(sig, sig_len);
	if (!sig_BIO) {
		string_or_die(&errorstr, "Failed to read %s signature into BIO\n", sig_filename);
		goto error;
	}

	/* the signature is in DER format, so d2i it into verification pkcs7 form */
	p7 = d2i_PKCS7_bio(sig_BIO, NULL);
	if (p7 == NULL) {
		string_or_die(&errorstr, "NULL PKCS7 File\n");
		goto error;
	}

	/* get the data to be verified */
	data_fd = open(data_filename, O_RDONLY);
	if (data_fd == -1) {
		string_or_die(&errorstr, "Failed open %s\n", data_filename);
		goto error;
	}
	if (fstat(data_fd, &st) != 0) {
		string_or_die(&errorstr, "Failed to stat %s\n", data_filename);
		goto error;
	}
	data_len = st.st_size;
	data = mmap(NULL, data_len, PROT_READ, MAP_PRIVATE, data_fd, 0);
	if (data == MAP_FAILED) {
		string_or_die(&errorstr, "Failed to mmap %s\n", data_filename);
		goto error;
	}
	data_BIO = BIO_new_mem_buf(data, data_len);
	if (!data_BIO) {
		string_or_die(&errorstr, "Failed to read %s into BIO\n", data_filename);
		goto error;
	}

	/* munge the signature and data into a verifiable format */
	verify_BIO = PKCS7_dataInit(p7, data_BIO);
	if (!verify_BIO) {
		string_or_die(&errorstr, "Failed PKCS7_dataInit()\n");
		goto error;
	}

	/* Verify the signature, outdata can be NULL because we don't use it */
	ret = PKCS7_verify(p7, x509_stack, store, verify_BIO, NULL, 0);
	if (ret == 1) {
		result = true;
	} else {
		string_or_die(&errorstr, "Signature check failed!\n");
	}

error:
	if (!result && errors_fatal) {
		fputs(errorstr, stderr);
		ERR_print_errors_fp(stderr);
	}

	free(errorstr);

	if (sig) {
		munmap(sig, sig_len);
	}
	if (sig_fd >= 0) {
		close(sig_fd);
	}
	if (data) {
		munmap(data, data_len);
	}
	if (data_fd >= 0) {
		close(data_fd);
	}
	if (sig_BIO) {
		BIO_free(sig_BIO);
	}
	if (data_BIO) {
		BIO_free(data_BIO);
	}
	if (verify_BIO) {
		BIO_free(verify_BIO);
	}
	if (p7) {
		PKCS7_free(p7);
	}

	return result;
}
Esempio n. 27
0
/*
 * Unwrap PKCS#7 data and decrypt if necessary
 */
int pkcs7_unwrap(struct scep *s, struct sscep_ctx *ctx, struct sscep_operation_info *op_info, char* data, int datalen)
{
    BIO *memorybio = NULL;
    BIO *outbio = NULL;
    BIO *pkcs7bio = NULL;
    int i, bytes, used;
    STACK_OF(PKCS7_SIGNER_INFO) *sk;
    PKCS7 *p7enc = NULL;
    PKCS7_SIGNER_INFO *si;
    STACK_OF(X509_ATTRIBUTE) *attribs;
    char *p = NULL;
    unsigned char buffer[1024];
    X509 *recipientcert;
    EVP_PKEY *recipientkey;
    int ret = SCEP_PKISTATUS_P7;

    /* Create new memory BIO for outer PKCS#7 */
    memorybio = BIO_new(BIO_s_mem());

    /* Read in data */
    if (ctx->verbose){
        qeo_log_i("reading outer PKCS#7");
    }
    if (BIO_write(memorybio, data, datalen) <= 0) {
        qeo_log_e("error reading PKCS#7 data");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("PKCS#7 payload size: %d bytes", datalen);
    }
    s->reply_p7 = d2i_PKCS7_bio(memorybio, NULL );
    if (s->reply_p7 == NULL ) {
        qeo_log_e("error retrieving PKCS#7 data");
        goto error;
    }
    if (ctx->debug) {
        qeo_log_i("printing PEM fomatted PKCS#7");
        PEM_write_PKCS7(stdout, s->reply_p7);
    }

    /* Make sure this is a signed PKCS#7 */
    if (!PKCS7_type_is_signed(s->reply_p7)) {
        qeo_log_e("PKCS#7 is not signed!");
        goto error;
    }

    /* Create BIO for content data */
    pkcs7bio = PKCS7_dataInit(s->reply_p7, NULL );
    if (pkcs7bio == NULL ) {
        qeo_log_e("cannot get PKCS#7 data");
        goto error;
    }

    /* Copy enveloped data from PKCS#7 */
    outbio = BIO_new(BIO_s_mem());
    used = 0;
    for (;;) {
        bytes = BIO_read(pkcs7bio, buffer, sizeof(buffer));
        used += bytes;
        if (bytes <= 0)
            break;
        BIO_write(outbio, buffer, bytes);
    }
    (void)BIO_flush(outbio);
    if (ctx->verbose){
        qeo_log_i("PKCS#7 contains %d bytes of enveloped data", used);
    }

    /* Get signer */
    sk = PKCS7_get_signer_info(s->reply_p7);
    if (sk == NULL ) {
        qeo_log_e("cannot get signer info!");
        goto error;
    }

    /* Verify signature */
    if (ctx->verbose){
        qeo_log_i("verifying signature");
    }
    si = sk_PKCS7_SIGNER_INFO_value(sk, 0);
    if (PKCS7_signatureVerify(pkcs7bio, s->reply_p7, si, op_info->racert) <= 0) {
        qeo_log_e("error verifying signature");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("signature ok");
    }

    /* Get signed attributes */
    if (ctx->verbose){
        qeo_log_i("finding signed attributes");
    }
    attribs = PKCS7_get_signed_attributes(si);
    if (attribs == NULL ) {
        qeo_log_e("no attributes found");
        goto error;
    }

    /* Transaction id */
    if ((get_signed_attribute(attribs, ctx->nid_transId, V_ASN1_PRINTABLESTRING, &p, ctx)) == 1) {
        qeo_log_e("cannot find transId");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("reply transaction id: %s", p);
    }
    if (strncmp(s->transaction_id, p, strlen(p))) {
        qeo_log_e("transaction id mismatch");
        goto error;
    }
    free(p);
    p=NULL;
    /* Message type, should be of type CertRep */
    if (get_signed_attribute(attribs, ctx->nid_messageType, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) {
        qeo_log_e("cannot find messageType");
        goto error;
    }
    if (atoi(p) != 3) {
        qeo_log_e("wrong message type in reply");
        goto error;
    }
    if (ctx->verbose){
        qeo_log_i("reply message type is good");
    }

    free(p);
    p=NULL;
    /* Recipient nonces: */
    if (get_signed_attribute(attribs, ctx->nid_recipientNonce, V_ASN1_OCTET_STRING, &p, ctx) == 1) {
        qeo_log_e("cannot find recipientNonce");
        goto error;
    }
    s->reply_recipient_nonce = p;
    p = NULL;
    if (ctx->verbose) {
        qeo_log_i("recipientNonce in reply");
    }
    /*
     * Compare recipient nonce to original sender nonce
     * The draft says nothing about this, but it makes sense to me..
     * XXXXXXXXXXXXXX check
     */
    for (i = 0; i < 16; i++) {
        if (s->sender_nonce[i] != s->reply_recipient_nonce[i]) {
            if (ctx->verbose)
                qeo_log_e("corrupted nonce received");
            /* Instead of exit, break out */
            break;
        }
    }
    /* Get pkiStatus */
    if (get_signed_attribute(attribs, ctx->nid_pkiStatus, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) {
        qeo_log_e("cannot find pkiStatus");
        /* This is a mandatory attribute.. */
        goto error;
    }
    switch (atoi(p)) {
        case SCEP_PKISTATUS_SUCCESS:
            qeo_log_i("pkistatus: SUCCESS");
            s->pki_status = SCEP_PKISTATUS_SUCCESS;
            break;
        case SCEP_PKISTATUS_FAILURE:
            qeo_log_i("pkistatus: FAILURE");
            s->pki_status = SCEP_PKISTATUS_FAILURE;
            break;
        case SCEP_PKISTATUS_PENDING:
            qeo_log_i("pkistatus: PENDING");
            s->pki_status = SCEP_PKISTATUS_PENDING;
            break;
        default:
            qeo_log_e("wrong pkistatus in reply");
            goto error;
    }
    free(p);
    p=NULL;

    /* Get failInfo */
    if (s->pki_status == SCEP_PKISTATUS_FAILURE) {
        if (get_signed_attribute(attribs, ctx->nid_failInfo, V_ASN1_PRINTABLESTRING, &p, ctx) == 1) {
            qeo_log_e("cannot find failInfo");
            goto error;
        }
        switch (atoi(p)) {
            case SCEP_FAILINFO_BADALG:
                s->fail_info = SCEP_FAILINFO_BADALG;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADALG_STR);
                break;
            case SCEP_FAILINFO_BADMSGCHK:
                s->fail_info = SCEP_FAILINFO_BADMSGCHK;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADMSGCHK_STR);
                break;
            case SCEP_FAILINFO_BADREQ:
                s->fail_info = SCEP_FAILINFO_BADREQ;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADREQ_STR);
                break;
            case SCEP_FAILINFO_BADTIME:
                s->fail_info = SCEP_FAILINFO_BADTIME;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADTIME_STR);
                break;
            case SCEP_FAILINFO_BADCERTID:
                s->fail_info = SCEP_FAILINFO_BADCERTID;
                qeo_log_i("reason: %s", SCEP_FAILINFO_BADCERTID_STR);
                break;
            default:
                qeo_log_e("wrong failInfo in " "reply");
                goto error;
        }
        free(p);
        p=NULL;
    }
    /* If FAILURE or PENDING, we can return */
    if (s->pki_status != SCEP_PKISTATUS_SUCCESS) {
        /* There shouldn't be any more data... */
        if (ctx->verbose && (used != 0)) {
            qeo_log_e("illegal size of payload");
        }
        return (0);
    }
    /* We got success and expect data */
    if (used == 0) {
        qeo_log_e("illegal size of payload");
        goto error;
    }

    /* Decrypt the inner PKCS#7 */
    recipientcert = s->signercert;
    recipientkey = s->signerkey;

    if (ctx->verbose){
        qeo_log_i("reading inner PKCS#7");
    }
    p7enc = d2i_PKCS7_bio(outbio, NULL );
    if (p7enc == NULL ) {
        qeo_log_e("cannot read inner PKCS#7");
        goto error;
    }
    BIO_free(outbio);/* No longer need it */
    outbio = NULL;
    if (ctx->debug) {
        qeo_log_i("printing PEM fomatted PKCS#7");
        PEM_write_PKCS7(stdout, p7enc);
    }

    /* Decrypt the data  */

    outbio = BIO_new(BIO_s_mem());
    if (ctx->verbose){
        qeo_log_i("decrypting inner PKCS#7");
    }
    if (PKCS7_decrypt(p7enc, recipientkey, recipientcert, outbio, 0) == 0) {
        qeo_log_e("error decrypting inner PKCS#7");
        goto error;
    }
    (void)BIO_flush(outbio);

    /* Write decrypted data */
    PKCS7_free(s->reply_p7);
    s->reply_p7 = d2i_PKCS7_bio(outbio, NULL );
    ret = 0;
error:
    free(p);
    BIO_free(outbio);
    BIO_free_all(pkcs7bio);
    BIO_free(memorybio);
    PKCS7_free(p7enc);
    return ret;
}
Esempio n. 28
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);
}
Esempio n. 29
0
/* Load a DER formatted file into internal SCEP_MSG structure */
SCEP_MSG *d2i_SCEP_MSG_bio (BIO *inbio) {

	BIO *outbio = NULL;
	BIO *p7bio = NULL;
	PKCS7 *p7 = NULL;
	// BIO *bio_err = NULL;

	SCEP_MSG *msg = NULL;

	int bytes, length, fd, used;
	int nMessageType = -1, nPkiStatus = -1;

	PKCS7_SIGNER_INFO *si = NULL;
	PKCS7_RECIP_INFO *ri = NULL;

	STACK_OF(X509_ATTRIBUTE) *sig_attribs = NULL;
	PKCS7 *p7env = NULL;

	SCEP_RECIP_INFO *rinfo = NULL;

	char buffer[1024];
	char *data = NULL;
	char *tmp_string = NULL;

	int debug = 0;
	int i;

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

	msg = (SCEP_MSG *) OPENSSL_malloc ( sizeof(SCEP_MSG));
	if( msg == NULL ) return (NULL);

	/* decode the data */
	p7 = d2i_PKCS7_bio(inbio, NULL);
	if (p7 == NULL) goto err;

	/* make sure this is a signed data PKCS#7			*/
	// if (!PKCS7_type_is_signed(p7)) {
	// 	BIO_printf(bio_err, "%s:%d: supplied PKCS#7 is not signed "
	// 		"data\n", __FILE__, __LINE__);
	// 	goto err;
	// }

	/* create BIOs to read signed content data from			*/
	p7bio = PKCS7_dataInit(p7, NULL);
	if (p7bio == NULL) goto err;

	/* Use an outbio and fill it with data from the p7 */
	outbio = BIO_new(BIO_s_mem());
	used = 0;
	for (;;) {
		bytes = BIO_read(p7bio, buffer, sizeof(buffer));
		used += bytes;
		if (bytes <= 0) break;
		BIO_write(outbio, buffer, bytes);
	}
	BIO_flush(outbio);

	/* there should be exactly one signer info			*/
	msg->sk_signer_info = PKCS7_get_signer_info(p7);
	if (msg->sk_signer_info == NULL) {
		goto err;
	}
	if (sk_PKCS7_SIGNER_INFO_num(msg->sk_signer_info) != 1) {
		goto err;
	}

	si = sk_PKCS7_SIGNER_INFO_value(msg->sk_signer_info, 0);
	msg->signer_ias = si->issuer_and_serial;
	msg->signer_cert = PKCS7_cert_from_signer_info( p7, si );

	/* If msg->signer_cert == NULL there is no signer certificate,
	 * otherwise the certificate is included into the PKCS#7 envelope
	 * this certificate may be self signed, but for the PKCS7_
	 * signatureVerify method, this does not matter */

	/* verify the PKCS#7 using the store just constructed		*/
	if (PKCS7_signatureVerify(p7bio, p7, si, 
				msg->signer_cert) <= 0) {
		// BIO_printf(bio_err, "%s:%d: verification failed\n", __FILE__,
		// 	__LINE__);
		goto err;
	}

	/* extract the signed attributes				*/
	msg->attrs = PKCS7_get_signed_attributes(si);
	if ((msg->attrs == NULL) || (sk_X509_ATTRIBUTE_num(msg->attrs) == 0)){
		goto err;
	}

	tmp_string = (char *) 
		SCEP_get_string_attr_by_name(msg->attrs, "messageType");

	if( tmp_string != NULL ) {
		msg->messageType = atoi( tmp_string );
		free( tmp_string );
		tmp_string = NULL;
	} else {
		msg->messageType = -1;
	}

	/* unpack the internal PKCS#7					*/
	p7env = d2i_PKCS7_bio(outbio, NULL);
	if (p7env == NULL) return msg;

	i=OBJ_obj2nid(p7env->type);
	msg->env_data.NID_p7data = i;
	msg->env_data.p7env = p7env;

	/* use a commodity variable */
	rinfo = &(msg->env_data.recip_info);

	switch(i) {
		case NID_pkcs7_signed:
			break;
		case NID_pkcs7_signedAndEnveloped:
			rinfo->sk_recip_info =
				p7env->d.signed_and_enveloped->recipientinfo;
			break;
		case  NID_pkcs7_enveloped:
			rinfo->sk_recip_info =
				p7env->d.enveloped->recipientinfo;
			break;
		default:
			// BIO_printf( bio_err, "%s:%d: unknown PKCS7 structure\n",
			// 		__FILE__, __LINE__);
			break;
	}

	/* Lets do the pub key stuff :-) */
	// FIXME: usaly only 1, but pix has 4 in structure - to be clarified...
	// so currently set to 4 to get it working with cisco-pix
	if( sk_PKCS7_RECIP_INFO_num(rinfo->sk_recip_info) > 4 ) {
		goto err;
	}

	/* Let's get the recipient info at stack num 0, the first and
	 * hopefully, the only one */
	ri = sk_PKCS7_RECIP_INFO_value( rinfo->sk_recip_info, 0);

	/* Usually certificates are not present, but in case the standard
	 * will be updated... */
	// if (debug && ri->cert == NULL) {
	// 	BIO_printf( bio_err, 
	// 		"%s:%d: Recipient info cert %d missing\n",
	// 		__FILE__, __LINE__, 0);
	// }

	rinfo->ias = ri->issuer_and_serial;
	/*
	if( rinfo->ias != NULL ) {
		BIO_printf(bio_err, "%s:%d: Recip cert issued by ",
			__FILE__, __LINE__);
                X509_NAME_print_ex (bio_err, rinfo->ias->issuer,  
                                    0, XN_FLAG_RFC2253&(~ASN1_STRFLGS_ESC_MSB));
		BIO_printf(bio_err, "\n%s:%d: Recip cert serial: %s\n",
			__FILE__, __LINE__,
			BN_bn2hex(ASN1_INTEGER_to_BN(rinfo->ias->serial,
			NULL)));
	};
	*/

	if( ri->cert ) {
		/* Usually this does not happen to be included in
		 * the pkcs7env data, but in case we just get it */
		sk_X509_push( rinfo->sk_recip_certs, ri->cert );
        /*
		if ( debug ) {
                        BIO_printf(bio_err, "%s:%d: Recipient cert for ",
                              __FILE__, __LINE__);
                        X509_NAME_print_ex (bio_err, X509_get_subject_name(ri->cert),
                                0, XN_FLAG_RFC2253&(~ASN1_STRFLGS_ESC_MSB));	
                        BIO_printf(bio_err, "\n");
		}
        */
	}

	/* perform some consistency checks				*/

	/* UniCert 3.1.2 seems to out the message type, so fudge 	*/
	/* the value of 3 (CertRep) if it is missing (problem pointed	*/
	/* out by Peter Onion						*/
	/*
	if (NULL == req->messageType) {
		BIO_printf(bio_err, "%s:%d: no message type (setting to 3)\n",
			__FILE__, __LINE__);
		req->messageType = "3";	// XXX should we strdup here?
	}
	*/

	/* UniCert doesn't seem to bother to put in a senderNonce,	*/
	/* so don't get upset if it is missing.				*/
	/*
	if (NULL == scep->senderNonce) {
		BIO_printf(bio_err, "%s:%d: senderNonce missing\n",
			__FILE__, __LINE__);
	}

	*/

	/* perform some type/status dependent checks			*/
	/*
	if ((used == 0) && (nMessageType != 3)) {
		BIO_printf(bio_err, "%s:%d: only CertRep message may be "
			"empty\n", __FILE__, __LINE__);
		goto err;
	}
	if ((used == 0) && (nMessageType == 3) && (nPkiStatus == 0)) {
		BIO_printf(bio_err, "%s:%d: CertRep may only be empty for "
			"failure or pending\n", __FILE__, __LINE__);
		goto err;
	}
	*/

	/* no content is only allowed if the message is a CertRep with	*/
	/* a pkiStatus of failure or pending				*/
	/*
	if (used == 0) {
		BIO_printf(bio_err, "%s:%d: empty PKCSReq, must be failure or "
			"pending\n", __FILE__, __LINE__);
		goto signedonly;
	}
	if (debug)
		BIO_printf(bio_err, "%s:%d: working on inner pkcs#7\n",
			__FILE__, __LINE__);

	*/

	BIO_free(outbio);
signedonly:

	/* we were successfull in extracting the telescoping PKCS#7's	*/
	return(msg);
err:
	// if( debug ) ERR_print_errors(bio_err);
	return(NULL);
}