예제 #1
0
int ssl3_change_cipher_state(SSL *s, int which)
	{
	unsigned char *p,*mac_secret;
	unsigned char exp_key[EVP_MAX_KEY_LENGTH];
	unsigned char exp_iv[EVP_MAX_IV_LENGTH];
	unsigned char *ms,*key,*iv,*er1,*er2;
	EVP_CIPHER_CTX *dd;
	const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
	COMP_METHOD *comp;
#endif
	const EVP_MD *m;
	EVP_MD_CTX md;
	int is_exp,n,i,j,k,cl;
	int reuse_dd = 0;

	is_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
	c=s->s3->tmp.new_sym_enc;
	m=s->s3->tmp.new_hash;
	/* m == NULL will lead to a crash later */
	OPENSSL_assert(m);
#ifndef OPENSSL_NO_COMP
	if (s->s3->tmp.new_compression == NULL)
		comp=NULL;
	else
		comp=s->s3->tmp.new_compression->method;
#endif

	if (which & SSL3_CC_READ)
		{
		if (s->enc_read_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
			goto err;
		else
			/* make sure it's intialized in case we exit later with an error */
			EVP_CIPHER_CTX_init(s->enc_read_ctx);
		dd= s->enc_read_ctx;

		ssl_replace_hash(&s->read_hash,m);
#ifndef OPENSSL_NO_COMP
		/* COMPRESS */
		if (s->expand != NULL)
			{
			COMP_CTX_free(s->expand);
			s->expand=NULL;
			}
		if (comp != NULL)
			{
			s->expand=COMP_CTX_new(comp);
			if (s->expand == NULL)
				{
				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			if (s->s3->rrec.comp == NULL)
				s->s3->rrec.comp=(unsigned char *)
					OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH);
			if (s->s3->rrec.comp == NULL)
				goto err;
			}
#endif
		memset(&(s->s3->read_sequence[0]),0,8);
		mac_secret= &(s->s3->read_mac_secret[0]);
		}
	else
		{
		if (s->enc_write_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_write_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
			goto err;
		else
			/* make sure it's intialized in case we exit later with an error */
			EVP_CIPHER_CTX_init(s->enc_write_ctx);
		dd= s->enc_write_ctx;
		ssl_replace_hash(&s->write_hash,m);
#ifndef OPENSSL_NO_COMP
		/* COMPRESS */
		if (s->compress != NULL)
			{
			COMP_CTX_free(s->compress);
			s->compress=NULL;
			}
		if (comp != NULL)
			{
			s->compress=COMP_CTX_new(comp);
			if (s->compress == NULL)
				{
				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			}
#endif
		memset(&(s->s3->write_sequence[0]),0,8);
		mac_secret= &(s->s3->write_mac_secret[0]);
		}

	if (reuse_dd)
		EVP_CIPHER_CTX_cleanup(dd);

	p=s->s3->tmp.key_block;
	i=EVP_MD_size(m);
	if (i < 0)
		goto err2;
	cl=EVP_CIPHER_key_length(c);
	j=is_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
		 cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
	/* Was j=(is_exp)?5:EVP_CIPHER_key_length(c); */
	k=EVP_CIPHER_iv_length(c);
	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
		{
		ms=  &(p[ 0]); n=i+i;
		key= &(p[ n]); n+=j+j;
		iv=  &(p[ n]); n+=k+k;
		er1= &(s->s3->client_random[0]);
		er2= &(s->s3->server_random[0]);
		}
	else
		{
		n=i;
		ms=  &(p[ n]); n+=i+j;
		key= &(p[ n]); n+=j+k;
		iv=  &(p[ n]); n+=k;
		er1= &(s->s3->server_random[0]);
		er2= &(s->s3->client_random[0]);
		}

	if (n > s->s3->tmp.key_block_length)
		{
		SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
		goto err2;
		}

	EVP_MD_CTX_init(&md);
	memcpy(mac_secret,ms,i);
	if (is_exp)
		{
		/* In here I set both the read and write key/iv to the
		 * same value since only the correct one will be used :-).
		 */
		EVP_DigestInit_ex(&md,EVP_md5(), NULL);
		EVP_DigestUpdate(&md,key,j);
		EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE);
		EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE);
		EVP_DigestFinal_ex(&md,&(exp_key[0]),NULL);
		key= &(exp_key[0]);

		if (k > 0)
			{
			EVP_DigestInit_ex(&md,EVP_md5(), NULL);
			EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE);
			EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE);
			EVP_DigestFinal_ex(&md,&(exp_iv[0]),NULL);
			iv= &(exp_iv[0]);
			}
		}

	s->session->key_arg_length=0;

	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));

	OPENSSL_cleanse(&(exp_key[0]),sizeof(exp_key));
	OPENSSL_cleanse(&(exp_iv[0]),sizeof(exp_iv));
	EVP_MD_CTX_cleanup(&md);
	return(1);
err:
	SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
err2:
	return(0);
	}
예제 #2
0
파일: pem_lib.c 프로젝트: SylvestreG/bitrig
int
PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, void *x,
    const EVP_CIPHER *enc, unsigned char *kstr, int klen,
    pem_password_cb *callback, void *u)
{
	EVP_CIPHER_CTX ctx;
	int dsize = 0, i, j, ret = 0;
	unsigned char *p, *data = NULL;
	const char *objstr = NULL;
	char buf[PEM_BUFSIZE];
	unsigned char key[EVP_MAX_KEY_LENGTH];
	unsigned char iv[EVP_MAX_IV_LENGTH];

	if (enc != NULL) {
		objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
		if (objstr == NULL) {
			PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,
			    PEM_R_UNSUPPORTED_CIPHER);
			goto err;
		}
	}

	if ((dsize = i2d(x, NULL)) < 0) {
		PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_ASN1_LIB);
		dsize = 0;
		goto err;
	}
	/* dzise + 8 bytes are needed */
	/* actually it needs the cipher block size extra... */
	data = malloc((unsigned int)dsize + 20);
	if (data == NULL) {
		PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE);
		goto err;
	}
	p = data;
	i = i2d(x, &p);

	if (enc != NULL) {
		if (kstr == NULL) {
			if (callback == NULL)
				klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u);
			else
				klen = (*callback)(buf, PEM_BUFSIZE, 1, u);
			if (klen <= 0) {
				PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,
				    PEM_R_READ_KEY);
				goto err;
			}
			kstr = (unsigned char *)buf;
		}
		OPENSSL_assert(enc->iv_len <= (int)sizeof(iv));
		if (RAND_pseudo_bytes(iv, enc->iv_len) < 0) /* Generate a salt */
			goto err;
		/* The 'iv' is used as the iv and as a salt.  It is
		 * NOT taken from the BytesToKey function */
		if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1,
		    key, NULL))
			goto err;

		if (kstr == (unsigned char *)buf)
			OPENSSL_cleanse(buf, PEM_BUFSIZE);

		OPENSSL_assert(strlen(objstr) + 23 +
		    2 * enc->iv_len + 13 <= sizeof buf);

		buf[0] = '\0';
		PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
		PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv);
		/* k=strlen(buf); */

		EVP_CIPHER_CTX_init(&ctx);
		ret = 1;
		if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv) ||
		    !EVP_EncryptUpdate(&ctx, data, &j, data, i) ||
		    !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
			ret = 0;
		EVP_CIPHER_CTX_cleanup(&ctx);
		if (ret == 0)
			goto err;
		i += j;
	} else {
		ret = 1;
		buf[0] = '\0';
	}
	i = PEM_write_bio(bp, name, buf, data, i);
	if (i <= 0)
		ret = 0;
err:
	OPENSSL_cleanse(key, sizeof(key));
	OPENSSL_cleanse(iv, sizeof(iv));
	OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
	OPENSSL_cleanse(buf, PEM_BUFSIZE);
	if (data != NULL) {
		OPENSSL_cleanse(data, (unsigned int)dsize);
		free(data);
	}
	return (ret);
}
예제 #3
0
파일: pk7_doit.c 프로젝트: hlcherub/src
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
	{
	int i;
	BIO *out=NULL,*btmp=NULL;
	X509_ALGOR *xa = NULL;
	const EVP_CIPHER *evp_cipher=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	ASN1_OCTET_STRING *os=NULL;

	if (p7 == NULL) {
		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
		return NULL;
	}
	/*
	 * The content field in the PKCS7 ContentInfo is optional, but that really
	 * only applies to inner content (precisely, detached signatures).
	 *
	 * When reading content, missing outer content is therefore treated as an
	 * error.
	 *
	 * When creating content, PKCS7_content_new() must be called before
	 * calling this method, so a NULL p7->d is always an error.
	 */
	if (p7->d.ptr == NULL) {
		PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
		return NULL;
	}

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		md_sk=p7->d.sign->md_algs;
		os = PKCS7_get_octet_string(p7->d.sign->contents);
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
			goto err;
			}
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		xalg=p7->d.enveloped->enc_data->algorithm;
		evp_cipher=p7->d.enveloped->enc_data->cipher;
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
			goto err;
			}
		break;
	case NID_pkcs7_digest:
		xa = p7->d.digest->md;
		os = PKCS7_get_octet_string(p7->d.digest->contents);
		break;
	case NID_pkcs7_data:
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
			goto err;

	if (xa && !PKCS7_bio_add_digest(&out, xa))
			goto err;

	if (evp_cipher != NULL)
		{
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		int keylen,ivlen;
		EVP_CIPHER_CTX *ctx;

		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
			goto err;
			}
		BIO_get_cipher_ctx(btmp, &ctx);
		keylen=EVP_CIPHER_key_length(evp_cipher);
		ivlen=EVP_CIPHER_iv_length(evp_cipher);
		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
		if (ivlen > 0)
			if (RAND_pseudo_bytes(iv,ivlen) <= 0)
				goto err;
		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
			goto err;
		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
			goto err;
		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
			goto err;

		if (ivlen > 0) {
			if (xalg->parameter == NULL) {
				xalg->parameter = ASN1_TYPE_new();
				if (xalg->parameter == NULL)
					goto err;
			}
			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
				goto err;
		}

		/* Lets do the pub key stuff :-) */
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
				goto err;
			}
		OPENSSL_cleanse(key, keylen);

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
		btmp=NULL;
		}

	if (bio == NULL)
		{
		if (PKCS7_is_detached(p7))
			bio=BIO_new(BIO_s_null());
		else if (os && os->length > 0)
			bio = BIO_new_mem_buf(os->data, os->length);
		if(bio == NULL)
			{
			bio=BIO_new(BIO_s_mem());
			if (bio == NULL)
				goto err;
			BIO_set_mem_eof_return(bio,0);
			}
		}
	if (out)
		BIO_push(out,bio);
	else
		out = bio;
	bio=NULL;
	if (0)
		{
err:
		if (out != NULL)
			BIO_free_all(out);
		if (btmp != NULL)
			BIO_free_all(btmp);
		out=NULL;
		}
	return(out);
	}
예제 #4
0
int tls1_change_cipher_state(SSL *s, int which)
	{
	static const unsigned char empty[]="";
	unsigned char *p,*mac_secret;
	unsigned char *exp_label;
	unsigned char tmp1[EVP_MAX_KEY_LENGTH];
	unsigned char tmp2[EVP_MAX_KEY_LENGTH];
	unsigned char iv1[EVP_MAX_IV_LENGTH*2];
	unsigned char iv2[EVP_MAX_IV_LENGTH*2];
	unsigned char *ms,*key,*iv;
	int client_write;
	EVP_CIPHER_CTX *dd;
	const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
	const SSL_COMP *comp;
#endif
	const EVP_MD *m;
	int mac_type;
	int *mac_secret_size;
	EVP_MD_CTX *mac_ctx;
	EVP_PKEY *mac_key;
	int is_export,n,i,j,k,exp_label_len,cl;
	int reuse_dd = 0;

	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
	c=s->s3->tmp.new_sym_enc;
	m=s->s3->tmp.new_hash;
	mac_type = s->s3->tmp.new_mac_pkey_type;
#ifndef OPENSSL_NO_COMP
	comp=s->s3->tmp.new_compression;
#endif

#ifdef KSSL_DEBUG
	printf("tls1_change_cipher_state(which= %d) w/\n", which);
	printf("\talg= %ld/%ld, comp= %p\n",
	       s->s3->tmp.new_cipher->algorithm_mkey,
	       s->s3->tmp.new_cipher->algorithm_auth,
	       comp);
	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", c);
	printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
                c->nid,c->block_size,c->key_len,c->iv_len);
	printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
	{
        int i;
        for (i=0; i<s->s3->tmp.key_block_length; i++)
		printf("%02x", key_block[i]);  printf("\n");
        }
#endif	/* KSSL_DEBUG */

	if (which & SSL3_CC_READ)
		{
		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
			s->mac_flags |= SSL_MAC_FLAG_READ_MAC_STREAM;
		else
			s->mac_flags &= ~SSL_MAC_FLAG_READ_MAC_STREAM;

		if (s->enc_read_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_read_ctx=OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
			goto err;
		else
			/* make sure it's intialized in case we exit later with an error */
			EVP_CIPHER_CTX_init(s->enc_read_ctx);
		dd= s->enc_read_ctx;
		mac_ctx=ssl_replace_hash(&s->read_hash,NULL);
#ifndef OPENSSL_NO_COMP
		if (s->expand != NULL)
			{
			COMP_CTX_free(s->expand);
			s->expand=NULL;
			}
		if (comp != NULL)
			{
			s->expand=COMP_CTX_new(comp->method);
			if (s->expand == NULL)
				{
				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			if (s->s3->rrec.comp == NULL)
				s->s3->rrec.comp=(unsigned char *)
					OPENSSL_malloc(SSL3_RT_MAX_ENCRYPTED_LENGTH);
			if (s->s3->rrec.comp == NULL)
				goto err;
			}
#endif
		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
 		if (s->version != DTLS1_VERSION)
			memset(&(s->s3->read_sequence[0]),0,8);
		mac_secret= &(s->s3->read_mac_secret[0]);
		mac_secret_size=&(s->s3->read_mac_secret_size);
		}
	else
		{
		if (s->s3->tmp.new_cipher->algorithm2 & TLS1_STREAM_MAC)
			s->mac_flags |= SSL_MAC_FLAG_WRITE_MAC_STREAM;
			else
			s->mac_flags &= ~SSL_MAC_FLAG_WRITE_MAC_STREAM;
		if (s->enc_write_ctx != NULL && !SSL_IS_DTLS(s))
			reuse_dd = 1;
		else if ((s->enc_write_ctx=EVP_CIPHER_CTX_new()) == NULL)
			goto err;
		dd= s->enc_write_ctx;
		if (SSL_IS_DTLS(s))
			{
			mac_ctx = EVP_MD_CTX_create();
			if (!mac_ctx)
				goto err;
			s->write_hash = mac_ctx;
			}
		else
		       mac_ctx = ssl_replace_hash(&s->write_hash,NULL);
#ifndef OPENSSL_NO_COMP
		if (s->compress != NULL)
			{
			COMP_CTX_free(s->compress);
			s->compress=NULL;
			}
		if (comp != NULL)
			{
			s->compress=COMP_CTX_new(comp->method);
			if (s->compress == NULL)
				{
				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			}
#endif
		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
 		if (s->version != DTLS1_VERSION)
			memset(&(s->s3->write_sequence[0]),0,8);
		mac_secret= &(s->s3->write_mac_secret[0]);
		mac_secret_size = &(s->s3->write_mac_secret_size);
		}

	if (reuse_dd)
		EVP_CIPHER_CTX_cleanup(dd);

	p=s->s3->tmp.key_block;
	i=*mac_secret_size=s->s3->tmp.new_mac_secret_size;

	cl=EVP_CIPHER_key_length(c);
	j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
	               cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
	/* If GCM mode only part of IV comes from PRF */
	if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
		k = EVP_GCM_TLS_FIXED_IV_LEN;
	else
		k=EVP_CIPHER_iv_length(c);
	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
		{
		ms=  &(p[ 0]); n=i+i;
		key= &(p[ n]); n+=j+j;
		iv=  &(p[ n]); n+=k+k;
		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
		client_write=1;
		}
	else
		{
		n=i;
		ms=  &(p[ n]); n+=i+j;
		key= &(p[ n]); n+=j+k;
		iv=  &(p[ n]); n+=k;
		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
		client_write=0;
		}

	if (n > s->s3->tmp.key_block_length)
		{
		SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
		goto err2;
		}

	memcpy(mac_secret,ms,i);

	if (!(EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER))
		{
		mac_key = EVP_PKEY_new_mac_key(mac_type, NULL,
				mac_secret,*mac_secret_size);
		EVP_DigestSignInit(mac_ctx,NULL,m,NULL,mac_key);
		EVP_PKEY_free(mac_key);
		}
#ifdef TLS_DEBUG
printf("which = %04X\nmac key=",which);
{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
#endif
	if (is_export)
		{
		/* In here I set both the read and write key/iv to the
		 * same value since only the correct one will be used :-).
		 */
		if (!tls1_PRF(ssl_get_algorithm2(s),
				exp_label,exp_label_len,
				s->s3->client_random,SSL3_RANDOM_SIZE,
				s->s3->server_random,SSL3_RANDOM_SIZE,
				NULL,0,NULL,0,
				key,j,tmp1,tmp2,EVP_CIPHER_key_length(c)))
			goto err2;
		key=tmp1;

		if (k > 0)
			{
			if (!tls1_PRF(ssl_get_algorithm2(s),
					TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
					s->s3->client_random,SSL3_RANDOM_SIZE,
					s->s3->server_random,SSL3_RANDOM_SIZE,
					NULL,0,NULL,0,
					empty,0,iv1,iv2,k*2))
				goto err2;
			if (client_write)
				iv=iv1;
			else
				iv= &(iv1[k]);
			}
		}

	s->session->key_arg_length=0;
#ifdef KSSL_DEBUG
	{
        int i;
	printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
	printf("\tkey= "); for (i=0; i<c->key_len; i++) printf("%02x", key[i]);
	printf("\n");
	printf("\t iv= "); for (i=0; i<c->iv_len; i++) printf("%02x", iv[i]);
	printf("\n");
	}
#endif	/* KSSL_DEBUG */

	if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
		{
		EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE));
		EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv);
		}
	else	
		EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));

	/* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
	if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size)
		EVP_CIPHER_CTX_ctrl(dd,EVP_CTRL_AEAD_SET_MAC_KEY,
				*mac_secret_size,mac_secret);

#ifdef TLS_DEBUG
printf("which = %04X\nkey=",which);
{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
printf("\niv=");
{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif

	OPENSSL_cleanse(tmp1,sizeof(tmp1));
	OPENSSL_cleanse(tmp2,sizeof(tmp1));
	OPENSSL_cleanse(iv1,sizeof(iv1));
	OPENSSL_cleanse(iv2,sizeof(iv2));
	return(1);
err:
	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
err2:
	return(0);
	}
예제 #5
0
int ASN1_item_sign_ctx(const ASN1_ITEM *it,
		X509_ALGOR *algor1, X509_ALGOR *algor2,
	     	ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
	{
	const EVP_MD *type;
	EVP_PKEY *pkey;
	unsigned char *buf_in=NULL,*buf_out=NULL;
	size_t inl=0,outl=0,outll=0;
	int signid, paramtype;
	int rv;

	type = EVP_MD_CTX_md(ctx);
	pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);

	if (!type || !pkey)
		{
		ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED);
		return 0;
		}

	if (pkey->ameth->item_sign)
		{
		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
						signature);
		if (rv == 1)
			outl = signature->length;
		/* Return value meanings:
		 * <=0: error.
		 *   1: method does everything.
		 *   2: carry on as normal.
		 *   3: ASN1 method sets algorithm identifiers: just sign.
		 */
		if (rv <= 0)
			ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB);
		if (rv <= 1)
			goto err;
		}
	else
		rv = 2;

	if (rv == 2)
		{
		if (type->flags & EVP_MD_FLAG_PKEY_METHOD_SIGNATURE)
			{
			if (!pkey->ameth ||
				!OBJ_find_sigid_by_algs(&signid,
							EVP_MD_nid(type),
							pkey->ameth->pkey_id))
				{
				ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,
					ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
				return 0;
				}
			}
		else
			signid = type->pkey_type;

		if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
			paramtype = V_ASN1_NULL;
		else
			paramtype = V_ASN1_UNDEF;

		if (algor1)
			X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL);
		if (algor2)
			X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL);

		}

	inl=ASN1_item_i2d(asn,&buf_in, it);
	outll=outl=EVP_PKEY_size(pkey);
	buf_out=OPENSSL_malloc((unsigned int)outl);
	if ((buf_in == NULL) || (buf_out == NULL))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
		|| !EVP_DigestSignFinal(ctx, buf_out, &outl))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX,ERR_R_EVP_LIB);
		goto err;
		}
	if (signature->data != NULL) OPENSSL_free(signature->data);
	signature->data=buf_out;
	buf_out=NULL;
	signature->length=outl;
	/* In the interests of compatibility, I'll make sure that
	 * the bit string has a 'not-used bits' value of 0
	 */
	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
err:
	EVP_MD_CTX_cleanup(ctx);
	if (buf_in != NULL)
		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
	if (buf_out != NULL)
		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
	return(outl);
	}
예제 #6
0
파일: enc.c 프로젝트: 375670450/openssl
int enc_main(int argc, char **argv)
{
    static char buf[128];
    static const char magic[] = "Salted__";
    BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio =
        NULL, *wbio = NULL;
    EVP_CIPHER_CTX *ctx = NULL;
    const EVP_CIPHER *cipher = NULL, *c;
    const EVP_MD *dgst = NULL;
    char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
    char *infile = NULL, *outfile = NULL, *prog;
    char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
    char mbuf[sizeof magic - 1];
    OPTION_CHOICE o;
    int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0;
    int enc = 1, printkey = 0, i, k, base64 = 0;
    int ret = 1, inl, nopad = 0, non_fips_allow = 0;
    unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
    unsigned char *buff = NULL, salt[PKCS5_SALT_LEN];
    unsigned long n;
#ifdef ZLIB
    int do_zlib = 0;
    BIO *bzl = NULL;
#endif

    /* first check the program name */
    prog = opt_progname(argv[0]);
    if (strcmp(prog, "base64") == 0)
        base64 = 1;
#ifdef ZLIB
    else if (strcmp(prog, "zlib") == 0)
        do_zlib = 1;
#endif
    else {
        cipher = EVP_get_cipherbyname(prog);
        if (cipher == NULL && strcmp(prog, "enc") != 0) {
            BIO_printf(bio_err, "%s is not a known cipher\n", prog);
            goto end;
        }
    }

    prog = opt_init(argc, argv, enc_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(enc_options);
            ret = 0;
            BIO_printf(bio_err, "Cipher Types\n");
            OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
                                   show_ciphers, bio_err);
            BIO_printf(bio_err, "\n");
            goto end;
        case OPT_E:
            enc = 1;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_PASS:
            passarg = opt_arg();
            break;
        case OPT_ENGINE:
            (void)setup_engine(opt_arg(), 0);
            break;
        case OPT_D:
            enc = 0;
            break;
        case OPT_P:
            printkey = 1;
            break;
        case OPT_V:
            verbose = 1;
            break;
        case OPT_NOPAD:
            nopad = 1;
            break;
        case OPT_SALT:
            nosalt = 0;
            break;
        case OPT_NOSALT:
            nosalt = 1;
            break;
        case OPT_DEBUG:
            debug = 1;
            break;
        case OPT_UPPER_P:
            printkey = 2;
            break;
        case OPT_UPPER_A:
            olb64 = 1;
            break;
        case OPT_A:
            base64 = 1;
            break;
        case OPT_Z:
#ifdef ZLIB
            do_zlib = 1;
#endif
            break;
        case OPT_BUFSIZE:
            p = opt_arg();
            i = (int)strlen(p) - 1;
            k = i >= 1 && p[i] == 'k';
            if (k)
                p[i] = '\0';
            if (!opt_ulong(opt_arg(), &n))
                goto opthelp;
            if (k)
                n *= 1024;
            bsize = (int)n;
            break;
        case OPT_K:
            str = opt_arg();
            break;
        case OPT_KFILE:
            in = bio_open_default(opt_arg(), "r");
            if (in == NULL)
                goto opthelp;
            i = BIO_gets(in, buf, sizeof buf);
            BIO_free(in);
            in = NULL;
            if (i <= 0) {
                BIO_printf(bio_err,
                           "%s Can't read key from %s\n", prog, opt_arg());
                goto opthelp;
            }
            while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n'))
                buf[i] = '\0';
            if (i <= 0) {
                BIO_printf(bio_err, "%s: zero length password\n", prog);
                goto opthelp;
            }
            str = buf;
            break;
        case OPT_UPPER_K:
            hkey = opt_arg();
            break;
        case OPT_UPPER_S:
            hsalt = opt_arg();
            break;
        case OPT_IV:
            hiv = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_arg(), &dgst))
                goto opthelp;
            break;
        case OPT_NON_FIPS_ALLOW:
            non_fips_allow = 1;
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &c))
                goto opthelp;
            cipher = c;
            break;
        case OPT_NONE:
            cipher = NULL;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
        BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog);
        goto end;
    }

    if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) {
        BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog);
        goto end;
    }

    if (dgst == NULL)
        dgst = EVP_md5();

    /* It must be large enough for a base64 encoded line */
    if (base64 && bsize < 80)
        bsize = 80;
    if (verbose)
        BIO_printf(bio_err, "bufsize=%d\n", bsize);

    strbuf = app_malloc(SIZE, "strbuf");
    buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer");

    if (debug) {
        BIO_set_callback(in, BIO_debug_callback);
        BIO_set_callback(out, BIO_debug_callback);
        BIO_set_callback_arg(in, (char *)bio_err);
        BIO_set_callback_arg(out, (char *)bio_err);
    }

    if (infile == NULL) {
        unbuffer(stdin);
        in = dup_bio_in();
    } else
        in = bio_open_default(infile, "r");
    if (in == NULL)
        goto end;

    if (!str && passarg) {
        if (!app_passwd(passarg, NULL, &pass, NULL)) {
            BIO_printf(bio_err, "Error getting password\n");
            goto end;
        }
        str = pass;
    }

    if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) {
        for (;;) {
            char prompt[200];

            BIO_snprintf(prompt, sizeof prompt, "enter %s %s password:"******"encryption" : "decryption");
            strbuf[0] = '\0';
            i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc);
            if (i == 0) {
                if (strbuf[0] == '\0') {
                    ret = 1;
                    goto end;
                }
                str = strbuf;
                break;
            }
            if (i < 0) {
                BIO_printf(bio_err, "bad password read\n");
                goto end;
            }
        }
    }

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

    rbio = in;
    wbio = out;

#ifdef ZLIB
    if (do_zlib) {
        if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
            goto end;
        if (enc)
            wbio = BIO_push(bzl, wbio);
        else
            rbio = BIO_push(bzl, rbio);
    }
#endif

    if (base64) {
        if ((b64 = BIO_new(BIO_f_base64())) == NULL)
            goto end;
        if (debug) {
            BIO_set_callback(b64, BIO_debug_callback);
            BIO_set_callback_arg(b64, (char *)bio_err);
        }
        if (olb64)
            BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
        if (enc)
            wbio = BIO_push(b64, wbio);
        else
            rbio = BIO_push(b64, rbio);
    }

    if (cipher != NULL) {
        /*
         * Note that str is NULL if a key was passed on the command line, so
         * we get no salt in that case. Is this a bug?
         */
        if (str != NULL) {
            /*
             * Salt handling: if encrypting generate a salt and write to
             * output BIO. If decrypting read salt from input BIO.
             */
            unsigned char *sptr;
            if (nosalt)
                sptr = NULL;
            else {
                if (enc) {
                    if (hsalt) {
                        if (!set_hex(hsalt, salt, sizeof salt)) {
                            BIO_printf(bio_err, "invalid hex salt value\n");
                            goto end;
                        }
                    } else if (RAND_bytes(salt, sizeof salt) <= 0)
                        goto end;
                    /*
                     * If -P option then don't bother writing
                     */
                    if ((printkey != 2)
                        && (BIO_write(wbio, magic,
                                      sizeof magic - 1) != sizeof magic - 1
                            || BIO_write(wbio,
                                         (char *)salt,
                                         sizeof salt) != sizeof salt)) {
                        BIO_printf(bio_err, "error writing output file\n");
                        goto end;
                    }
                } else if (BIO_read(rbio, mbuf, sizeof mbuf) != sizeof mbuf
                           || BIO_read(rbio,
                                       (unsigned char *)salt,
                                       sizeof salt) != sizeof salt) {
                    BIO_printf(bio_err, "error reading input file\n");
                    goto end;
                } else if (memcmp(mbuf, magic, sizeof magic - 1)) {
                    BIO_printf(bio_err, "bad magic number\n");
                    goto end;
                }

                sptr = salt;
            }

            if (!EVP_BytesToKey(cipher, dgst, sptr,
                                (unsigned char *)str,
                                strlen(str), 1, key, iv)) {
                BIO_printf(bio_err, "EVP_BytesToKey failed\n");
                goto end;
            }
            /*
             * zero the complete buffer or the string passed from the command
             * line bug picked up by Larry J. Hughes Jr. <*****@*****.**>
             */
            if (str == strbuf)
                OPENSSL_cleanse(str, SIZE);
            else
                OPENSSL_cleanse(str, strlen(str));
        }
        if (hiv != NULL) {
            int siz = EVP_CIPHER_iv_length(cipher);
            if (siz == 0) {
                BIO_printf(bio_err, "warning: iv not use by this cipher\n");
            } else if (!set_hex(hiv, iv, sizeof iv)) {
                BIO_printf(bio_err, "invalid hex iv value\n");
                goto end;
            }
        }
        if ((hiv == NULL) && (str == NULL)
            && EVP_CIPHER_iv_length(cipher) != 0) {
            /*
             * No IV was explicitly set and no IV was generated during
             * EVP_BytesToKey. Hence the IV is undefined, making correct
             * decryption impossible.
             */
            BIO_printf(bio_err, "iv undefined\n");
            goto end;
        }
        if ((hkey != NULL) && !set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) {
            BIO_printf(bio_err, "invalid hex key value\n");
            goto end;
        }

        if ((benc = BIO_new(BIO_f_cipher())) == NULL)
            goto end;

        /*
         * Since we may be changing parameters work on the encryption context
         * rather than calling BIO_set_cipher().
         */

        BIO_get_cipher_ctx(benc, &ctx);

        if (non_fips_allow)
            EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_NON_FIPS_ALLOW);

        if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) {
            BIO_printf(bio_err, "Error setting cipher %s\n",
                       EVP_CIPHER_name(cipher));
            ERR_print_errors(bio_err);
            goto end;
        }

        if (nopad)
            EVP_CIPHER_CTX_set_padding(ctx, 0);

        if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) {
            BIO_printf(bio_err, "Error setting cipher %s\n",
                       EVP_CIPHER_name(cipher));
            ERR_print_errors(bio_err);
            goto end;
        }

        if (debug) {
            BIO_set_callback(benc, BIO_debug_callback);
            BIO_set_callback_arg(benc, (char *)bio_err);
        }

        if (printkey) {
            if (!nosalt) {
                printf("salt=");
                for (i = 0; i < (int)sizeof(salt); i++)
                    printf("%02X", salt[i]);
                printf("\n");
            }
            if (cipher->key_len > 0) {
                printf("key=");
                for (i = 0; i < cipher->key_len; i++)
                    printf("%02X", key[i]);
                printf("\n");
            }
            if (cipher->iv_len > 0) {
                printf("iv =");
                for (i = 0; i < cipher->iv_len; i++)
                    printf("%02X", iv[i]);
                printf("\n");
            }
            if (printkey == 2) {
                ret = 0;
                goto end;
            }
        }
    }

    /* Only encrypt/decrypt as we write the file */
    if (benc != NULL)
        wbio = BIO_push(benc, wbio);

    for (;;) {
        inl = BIO_read(rbio, (char *)buff, bsize);
        if (inl <= 0)
            break;
        if (BIO_write(wbio, (char *)buff, inl) != inl) {
            BIO_printf(bio_err, "error writing output file\n");
            goto end;
        }
    }
    if (!BIO_flush(wbio)) {
        BIO_printf(bio_err, "bad decrypt\n");
        goto end;
    }

    ret = 0;
    if (verbose) {
        BIO_printf(bio_err, "bytes read   :%8ld\n", BIO_number_read(in));
        BIO_printf(bio_err, "bytes written:%8ld\n", BIO_number_written(out));
    }
 end:
    ERR_print_errors(bio_err);
    OPENSSL_free(strbuf);
    OPENSSL_free(buff);
    BIO_free(in);
    BIO_free_all(out);
    BIO_free(benc);
    BIO_free(b64);
#ifdef ZLIB
    BIO_free(bzl);
#endif
    OPENSSL_free(pass);
    return (ret);
}
예제 #7
0
static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA1 *key,
                                         unsigned char *out,
                                         const unsigned char *inp,
                                         size_t inp_len, int n4x)
{                               /* n4x is 1 or 2 */
    HASH_DESC hash_d[8], edges[8];
    CIPH_DESC ciph_d[8];
    unsigned char storage[sizeof(SHA1_MB_CTX) + 32];
    union {
        u64 q[16];
        u32 d[32];
        u8 c[128];
    } blocks[8];
    SHA1_MB_CTX *ctx;
    unsigned int frag, last, packlen, i, x4 = 4 * n4x, minblocks, processed =
        0;
    size_t ret = 0;
    u8 *IVs;
#   if defined(BSWAP8)
    u64 seqnum;
#   endif

    /* ask for IVs in bulk */
    if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0)
        return 0;

    ctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */

    frag = (unsigned int)inp_len >> (1 + n4x);
    last = (unsigned int)inp_len + frag - (frag << (1 + n4x));
    if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) {
        frag++;
        last -= x4 - 1;
    }

    packlen = 5 + 16 + ((frag + 20 + 16) & -16);

    /* populate descriptors with pointers and IVs */
    hash_d[0].ptr = inp;
    ciph_d[0].inp = inp;
    /* 5+16 is place for header and explicit IV */
    ciph_d[0].out = out + 5 + 16;
    memcpy(ciph_d[0].out - 16, IVs, 16);
    memcpy(ciph_d[0].iv, IVs, 16);
    IVs += 16;

    for (i = 1; i < x4; i++) {
        ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag;
        ciph_d[i].out = ciph_d[i - 1].out + packlen;
        memcpy(ciph_d[i].out - 16, IVs, 16);
        memcpy(ciph_d[i].iv, IVs, 16);
        IVs += 16;
    }

#   if defined(BSWAP8)
    memcpy(blocks[0].c, key->md.data, 8);
    seqnum = BSWAP8(blocks[0].q[0]);
#   endif
    for (i = 0; i < x4; i++) {
        unsigned int len = (i == (x4 - 1) ? last : frag);
#   if !defined(BSWAP8)
        unsigned int carry, j;
#   endif

        ctx->A[i] = key->md.h0;
        ctx->B[i] = key->md.h1;
        ctx->C[i] = key->md.h2;
        ctx->D[i] = key->md.h3;
        ctx->E[i] = key->md.h4;

        /* fix seqnum */
#   if defined(BSWAP8)
        blocks[i].q[0] = BSWAP8(seqnum + i);
#   else
        for (carry = i, j = 8; j--;) {
            blocks[i].c[j] = ((u8 *)key->md.data)[j] + carry;
            carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1);
        }
#   endif
        blocks[i].c[8] = ((u8 *)key->md.data)[8];
        blocks[i].c[9] = ((u8 *)key->md.data)[9];
        blocks[i].c[10] = ((u8 *)key->md.data)[10];
        /* fix length */
        blocks[i].c[11] = (u8)(len >> 8);
        blocks[i].c[12] = (u8)(len);

        memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13);
        hash_d[i].ptr += 64 - 13;
        hash_d[i].blocks = (len - (64 - 13)) / 64;

        edges[i].ptr = blocks[i].c;
        edges[i].blocks = 1;
    }

    /* hash 13-byte headers and first 64-13 bytes of inputs */
    sha1_multi_block(ctx, edges, n4x);
    /* hash bulk inputs */
#   define MAXCHUNKSIZE    2048
#   if     MAXCHUNKSIZE%64
#    error  "MAXCHUNKSIZE is not divisible by 64"
#   elif   MAXCHUNKSIZE
    /*
     * goal is to minimize pressure on L1 cache by moving in shorter steps,
     * so that hashed data is still in the cache by the time we encrypt it
     */
    minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64;
    if (minblocks > MAXCHUNKSIZE / 64) {
        for (i = 0; i < x4; i++) {
            edges[i].ptr = hash_d[i].ptr;
            edges[i].blocks = MAXCHUNKSIZE / 64;
            ciph_d[i].blocks = MAXCHUNKSIZE / 16;
        }
        do {
            sha1_multi_block(ctx, edges, n4x);
            aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x);

            for (i = 0; i < x4; i++) {
                edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE;
                hash_d[i].blocks -= MAXCHUNKSIZE / 64;
                edges[i].blocks = MAXCHUNKSIZE / 64;
                ciph_d[i].inp += MAXCHUNKSIZE;
                ciph_d[i].out += MAXCHUNKSIZE;
                ciph_d[i].blocks = MAXCHUNKSIZE / 16;
                memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16);
            }
            processed += MAXCHUNKSIZE;
            minblocks -= MAXCHUNKSIZE / 64;
        } while (minblocks > MAXCHUNKSIZE / 64);
    }
#   endif
#   undef  MAXCHUNKSIZE
    sha1_multi_block(ctx, hash_d, n4x);

    memset(blocks, 0, sizeof(blocks));
    for (i = 0; i < x4; i++) {
        unsigned int len = (i == (x4 - 1) ? last : frag),
            off = hash_d[i].blocks * 64;
        const unsigned char *ptr = hash_d[i].ptr + off;

        off = (len - processed) - (64 - 13) - off; /* remainder actually */
        memcpy(blocks[i].c, ptr, off);
        blocks[i].c[off] = 0x80;
        len += 64 + 13;         /* 64 is HMAC header */
        len *= 8;               /* convert to bits */
        if (off < (64 - 8)) {
#   ifdef BSWAP4
            blocks[i].d[15] = BSWAP4(len);
#   else
            PUTU32(blocks[i].c + 60, len);
#   endif
            edges[i].blocks = 1;
        } else {
#   ifdef BSWAP4
            blocks[i].d[31] = BSWAP4(len);
#   else
            PUTU32(blocks[i].c + 124, len);
#   endif
            edges[i].blocks = 2;
        }
        edges[i].ptr = blocks[i].c;
    }

    /* hash input tails and finalize */
    sha1_multi_block(ctx, edges, n4x);

    memset(blocks, 0, sizeof(blocks));
    for (i = 0; i < x4; i++) {
#   ifdef BSWAP4
        blocks[i].d[0] = BSWAP4(ctx->A[i]);
        ctx->A[i] = key->tail.h0;
        blocks[i].d[1] = BSWAP4(ctx->B[i]);
        ctx->B[i] = key->tail.h1;
        blocks[i].d[2] = BSWAP4(ctx->C[i]);
        ctx->C[i] = key->tail.h2;
        blocks[i].d[3] = BSWAP4(ctx->D[i]);
        ctx->D[i] = key->tail.h3;
        blocks[i].d[4] = BSWAP4(ctx->E[i]);
        ctx->E[i] = key->tail.h4;
        blocks[i].c[20] = 0x80;
        blocks[i].d[15] = BSWAP4((64 + 20) * 8);
#   else
        PUTU32(blocks[i].c + 0, ctx->A[i]);
        ctx->A[i] = key->tail.h0;
        PUTU32(blocks[i].c + 4, ctx->B[i]);
        ctx->B[i] = key->tail.h1;
        PUTU32(blocks[i].c + 8, ctx->C[i]);
        ctx->C[i] = key->tail.h2;
        PUTU32(blocks[i].c + 12, ctx->D[i]);
        ctx->D[i] = key->tail.h3;
        PUTU32(blocks[i].c + 16, ctx->E[i]);
        ctx->E[i] = key->tail.h4;
        blocks[i].c[20] = 0x80;
        PUTU32(blocks[i].c + 60, (64 + 20) * 8);
#   endif
        edges[i].ptr = blocks[i].c;
        edges[i].blocks = 1;
    }

    /* finalize MACs */
    sha1_multi_block(ctx, edges, n4x);

    for (i = 0; i < x4; i++) {
        unsigned int len = (i == (x4 - 1) ? last : frag), pad, j;
        unsigned char *out0 = out;

        memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed);
        ciph_d[i].inp = ciph_d[i].out;

        out += 5 + 16 + len;

        /* write MAC */
        PUTU32(out + 0, ctx->A[i]);
        PUTU32(out + 4, ctx->B[i]);
        PUTU32(out + 8, ctx->C[i]);
        PUTU32(out + 12, ctx->D[i]);
        PUTU32(out + 16, ctx->E[i]);
        out += 20;
        len += 20;

        /* pad */
        pad = 15 - len % 16;
        for (j = 0; j <= pad; j++)
            *(out++) = pad;
        len += pad + 1;

        ciph_d[i].blocks = (len - processed) / 16;
        len += 16;              /* account for explicit iv */

        /* arrange header */
        out0[0] = ((u8 *)key->md.data)[8];
        out0[1] = ((u8 *)key->md.data)[9];
        out0[2] = ((u8 *)key->md.data)[10];
        out0[3] = (u8)(len >> 8);
        out0[4] = (u8)(len);

        ret += len + 5;
        inp += frag;
    }

    aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x);

    OPENSSL_cleanse(blocks, sizeof(blocks));
    OPENSSL_cleanse(ctx, sizeof(*ctx));

    return ret;
}
예제 #8
0
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
	{
	BIO *b;
	EVP_CIPHER_CTX *ctx;
	const EVP_CIPHER *ciph;
	X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
	unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
	unsigned char *tkey = NULL;
	size_t tkeylen = 0;

	int ok = 0;

	int enc, keep_key = 0;

	enc = ec->cipher ? 1 : 0;

	b = BIO_new(BIO_f_cipher());
	if (!b)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							ERR_R_MALLOC_FAILURE);
		return NULL;
		}

	BIO_get_cipher_ctx(b, &ctx);

	if (enc)
		{
		ciph = ec->cipher;
		/* If not keeping key set cipher to NULL so subsequent calls
		 * decrypt.
		 */
		if (ec->key)
			ec->cipher = NULL;
		}
	else
		{
		ciph = EVP_get_cipherbyobj(calg->algorithm);

		if (!ciph)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							CMS_R_UNKNOWN_CIPHER);
			goto err;
			}
		}

	if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_INITIALISATION_ERROR);
		goto err;
		}

	if (enc)
		{
		int ivlen;
		calg->algorithm = OBJ_nid2obj(EVP_CIPHER_CTX_type(ctx));
		/* Generate a random IV if we need one */
		ivlen = EVP_CIPHER_CTX_iv_length(ctx);
		if (ivlen > 0)
			{
			if (RAND_pseudo_bytes(iv, ivlen) <= 0)
				goto err;
			piv = iv;
			}
		}
	else if (EVP_CIPHER_asn1_to_param(ctx, calg->parameter) <= 0)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
		goto err;
		}
	tkeylen = EVP_CIPHER_CTX_key_length(ctx);
	/* Generate random session key */
	if (!enc || !ec->key)
		{
		tkey = OPENSSL_malloc(tkeylen);
		if (!tkey)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (EVP_CIPHER_CTX_rand_key(ctx, tkey) <= 0)
			goto err;
		}

	if (!ec->key)
		{
		ec->key = tkey;
		ec->keylen = tkeylen;
		tkey = NULL;
		if (enc)
			keep_key = 1;
		else
			ERR_clear_error();
		
		}

	if (ec->keylen != tkeylen)
		{
		/* If necessary set key length */
		if (EVP_CIPHER_CTX_set_key_length(ctx, ec->keylen) <= 0)
			{
			/* Only reveal failure if debugging so we don't
			 * leak information which may be useful in MMA.
			 */
			if (enc || ec->debug)
				{
				CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
						CMS_R_INVALID_KEY_LENGTH);
				goto err;
				}
			else
				{
				/* Use random key */
				OPENSSL_cleanse(ec->key, ec->keylen);
				OPENSSL_free(ec->key);
				ec->key = tkey;
				ec->keylen = tkeylen;
				tkey = NULL;
				ERR_clear_error();
				}
			}
		}

	if (EVP_CipherInit_ex(ctx, NULL, NULL, ec->key, piv, enc) <= 0)
		{
		CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_INITIALISATION_ERROR);
		goto err;
		}

	if (piv)
		{
		calg->parameter = ASN1_TYPE_new();
		if (!calg->parameter)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
							ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (EVP_CIPHER_param_to_asn1(ctx, calg->parameter) <= 0)
			{
			CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
				CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
			goto err;
			}
		}
	ok = 1;

	err:
	if (ec->key && !keep_key)
		{
		OPENSSL_cleanse(ec->key, ec->keylen);
		OPENSSL_free(ec->key);
		ec->key = NULL;
		}
	if (tkey)
		{
		OPENSSL_cleanse(tkey, tkeylen);
		OPENSSL_free(tkey);
		}
	if (ok)
		return b;
	BIO_free(b);
	return NULL;
	}
예제 #9
0
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
			 int en_de)
{
	EVP_MD_CTX ctx;
	unsigned char md_tmp[EVP_MAX_MD_SIZE];
	unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
	int i;
	PBEPARAM *pbe;
	int saltlen, iter;
	unsigned char *salt;
	const unsigned char *pbuf;
	int mdsize;

	/* Extract useful info from parameter */
	if (param == NULL || param->type != V_ASN1_SEQUENCE ||
	    param->value.sequence == NULL) {
		EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
		return 0;
	}

	pbuf = param->value.sequence->data;
	if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) {
		EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
		return 0;
	}

	if (!pbe->iter) iter = 1;
	else iter = ASN1_INTEGER_get (pbe->iter);
	salt = pbe->salt->data;
	saltlen = pbe->salt->length;

	if(!pass) passlen = 0;
	else if(passlen == -1) passlen = strlen(pass);

	EVP_MD_CTX_init(&ctx);
	EVP_DigestInit_ex(&ctx, md, NULL);
	EVP_DigestUpdate(&ctx, pass, passlen);
	EVP_DigestUpdate(&ctx, salt, saltlen);
	PBEPARAM_free(pbe);
	EVP_DigestFinal_ex(&ctx, md_tmp, NULL);
	mdsize = EVP_MD_size(md);
	if (mdsize < 0)
	    return 0;
	for (i = 1; i < iter; i++) {
		EVP_DigestInit_ex(&ctx, md, NULL);
		EVP_DigestUpdate(&ctx, md_tmp, mdsize);
		EVP_DigestFinal_ex (&ctx, md_tmp, NULL);
	}
	EVP_MD_CTX_cleanup(&ctx);
	OPENSSL_assert(EVP_CIPHER_key_length(cipher) <= (int)sizeof(md_tmp));
	memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher));
	OPENSSL_assert(EVP_CIPHER_iv_length(cipher) <= 16);
	memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)),
						 EVP_CIPHER_iv_length(cipher));
	EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de);
	OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
	OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
	OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
	return 1;
}
예제 #10
0
/* signature verification */
static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
	     unsigned char *to, RSA *rsa, int padding)
	{
	BIGNUM *f,*ret;
	int i,num=0,r= -1;
	unsigned char *p;
	unsigned char *buf=NULL;
	BN_CTX *ctx=NULL;

	if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
		return -1;
		}

	if (BN_ucmp(rsa->n, rsa->e) <= 0)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
		return -1;
		}

	/* for large moduli, enforce exponent limit */
	if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
		{
		if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
			{
			RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
			return -1;
			}
		}
	
	if((ctx = BN_CTX_new()) == NULL) goto err;
	BN_CTX_start(ctx);
	f = BN_CTX_get(ctx);
	ret = BN_CTX_get(ctx);
	num=BN_num_bytes(rsa->n);
	buf = OPENSSL_malloc(num);
	if(!f || !ret || !buf)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	/* This check was for equality but PGP does evil things
	 * and chops off the top '0' bytes */
	if (flen > num)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_DATA_GREATER_THAN_MOD_LEN);
		goto err;
		}

	if (BN_bin2bn(from,flen,f) == NULL) goto err;

	if (BN_ucmp(f, rsa->n) >= 0)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
		goto err;
		}

	if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
		if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
			goto err;

	if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
		rsa->_method_mod_n)) goto err;

	if ((padding == RSA_X931_PADDING) && ((ret->d[0] & 0xf) != 12))
		if (!BN_sub(ret, rsa->n, ret)) goto err;

	p=buf;
	i=BN_bn2bin(ret,p);

	switch (padding)
		{
	case RSA_PKCS1_PADDING:
		r=RSA_padding_check_PKCS1_type_1(to,num,buf,i,num);
		break;
	case RSA_X931_PADDING:
		r=RSA_padding_check_X931(to,num,buf,i,num);
		break;
	case RSA_NO_PADDING:
		r=RSA_padding_check_none(to,num,buf,i,num);
		break;
	default:
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
		goto err;
		}
	if (r < 0)
		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_PADDING_CHECK_FAILED);

err:
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (buf != NULL)
		{
		OPENSSL_cleanse(buf,num);
		OPENSSL_free(buf);
		}
	return(r);
	}
예제 #11
0
static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
	     unsigned char *to, RSA *rsa, int padding)
	{
	BIGNUM f,ret;
	int i,j,k,num=0,r= -1;
	unsigned char *buf=NULL;
	BN_CTX *ctx=NULL;

	BN_init(&f);
	BN_init(&ret);
	if ((ctx=BN_CTX_new()) == NULL) goto err;
	num=BN_num_bytes(rsa->n);
	if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	switch (padding)
		{
	case RSA_PKCS1_PADDING:
		i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen);
		break;
#ifndef OPENSSL_NO_SHA
	case RSA_PKCS1_OAEP_PADDING:
	        i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0);
		break;
#endif
	case RSA_SSLV23_PADDING:
		i=RSA_padding_add_SSLv23(buf,num,from,flen);
		break;
	case RSA_NO_PADDING:
		i=RSA_padding_add_none(buf,num,from,flen);
		break;
	default:
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
		goto err;
		}
	if (i <= 0) goto err;

	if (BN_bin2bn(buf,num,&f) == NULL) goto err;
	
	if (BN_ucmp(&f, rsa->n) >= 0)
		{	
		/* usually the padding functions would catch this */
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
		goto err;
		}

	if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
		{
		BN_MONT_CTX* bn_mont_ctx;
		if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
			goto err;
		if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
			{
			BN_MONT_CTX_free(bn_mont_ctx);
			goto err;
			}
		if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
			{
			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
			if (rsa->_method_mod_n == NULL)
				{
				rsa->_method_mod_n = bn_mont_ctx;
				bn_mont_ctx = NULL;
				}
			CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
			}
		if (bn_mont_ctx)
			BN_MONT_CTX_free(bn_mont_ctx);
		}
		
	if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
		rsa->_method_mod_n)) goto err;

	/* put in leading 0 bytes if the number is less than the
	 * length of the modulus */
	j=BN_num_bytes(&ret);
	i=BN_bn2bin(&ret,&(to[num-j]));
	for (k=0; k<(num-i); k++)
		to[k]=0;

	r=num;
err:
	if (ctx != NULL) BN_CTX_free(ctx);
	BN_clear_free(&f);
	BN_clear_free(&ret);
	if (buf != NULL) 
		{
		OPENSSL_cleanse(buf,num);
		OPENSSL_free(buf);
		}
	return(r);
	}
예제 #12
0
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
	     unsigned char *to, RSA *rsa, int padding)
	{
	BIGNUM *f, *ret;
	int j,num=0,r= -1;
	unsigned char *p;
	unsigned char *buf=NULL;
	BN_CTX *ctx=NULL;
	int local_blinding = 0;
	/* Used only if the blinding structure is shared. A non-NULL unblind
	 * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
	 * the unblinding factor outside the blinding structure. */
	BIGNUM *unblind = NULL;
	BN_BLINDING *blinding = NULL;

	if((ctx = BN_CTX_new()) == NULL) goto err;
	BN_CTX_start(ctx);
	f   = BN_CTX_get(ctx);
	ret = BN_CTX_get(ctx);
	num = BN_num_bytes(rsa->n);
	buf = OPENSSL_malloc(num);
	if(!f || !ret || !buf)
		{
		RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	/* This check was for equality but PGP does evil things
	 * and chops off the top '0' bytes */
	if (flen > num)
		{
		RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_DATA_GREATER_THAN_MOD_LEN);
		goto err;
		}

	/* make data into a big number */
	if (BN_bin2bn(from,(int)flen,f) == NULL) goto err;

	if (BN_ucmp(f, rsa->n) >= 0)
		{
		RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
		goto err;
		}

	if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
		{
		blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
		if (blinding == NULL)
			{
			RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
			goto err;
			}
		}
	
	if (blinding != NULL)
		{
		if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL))
			{
			RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (!rsa_blinding_convert(blinding, f, unblind, ctx))
			goto err;
		}

	/* do the decrypt */
	if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
		((rsa->p != NULL) &&
		(rsa->q != NULL) &&
		(rsa->dmp1 != NULL) &&
		(rsa->dmq1 != NULL) &&
		(rsa->iqmp != NULL)) )
		{
		if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) goto err;
		}
	else
		{
		BIGNUM local_d;
		BIGNUM *d = NULL;
		
		if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
			{
			d = &local_d;
			BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
			}
		else
			d = rsa->d;

		if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
			if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
				goto err;
		if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
				rsa->_method_mod_n))
		  goto err;
		}

	if (blinding)
		if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
			goto err;

	p=buf;
	j=BN_bn2bin(ret,p); /* j is only used with no-padding mode */

	switch (padding)
		{
	case RSA_PKCS1_PADDING:
		r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num);
		break;
#ifndef OPENSSL_NO_SHA
        case RSA_PKCS1_OAEP_PADDING:
	        r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0);
                break;
#endif
 	case RSA_SSLV23_PADDING:
		r=RSA_padding_check_SSLv23(to,num,buf,j,num);
		break;
	case RSA_NO_PADDING:
		r=RSA_padding_check_none(to,num,buf,j,num);
		break;
	default:
		RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
		goto err;
		}
	if (r < 0)
		RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_PADDING_CHECK_FAILED);

err:
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (buf != NULL)
		{
		OPENSSL_cleanse(buf,num);
		OPENSSL_free(buf);
		}
	return(r);
	}
예제 #13
0
/* signing */
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
	     unsigned char *to, RSA *rsa, int padding)
	{
	BIGNUM *f, *ret, *res;
	int i,j,k,num=0,r= -1;
	unsigned char *buf=NULL;
	BN_CTX *ctx=NULL;
	int local_blinding = 0;
	/* Used only if the blinding structure is shared. A non-NULL unblind
	 * instructs rsa_blinding_convert() and rsa_blinding_invert() to store
	 * the unblinding factor outside the blinding structure. */
	BIGNUM *unblind = NULL;
	BN_BLINDING *blinding = NULL;

	if ((ctx=BN_CTX_new()) == NULL) goto err;
	BN_CTX_start(ctx);
	f   = BN_CTX_get(ctx);
	ret = BN_CTX_get(ctx);
	num = BN_num_bytes(rsa->n);
	buf = OPENSSL_malloc(num);
	if(!f || !ret || !buf)
		{
		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	switch (padding)
		{
	case RSA_PKCS1_PADDING:
		i=RSA_padding_add_PKCS1_type_1(buf,num,from,flen);
		break;
	case RSA_X931_PADDING:
		i=RSA_padding_add_X931(buf,num,from,flen);
		break;
	case RSA_NO_PADDING:
		i=RSA_padding_add_none(buf,num,from,flen);
		break;
	case RSA_SSLV23_PADDING:
	default:
		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
		goto err;
		}
	if (i <= 0) goto err;

	if (BN_bin2bn(buf,num,f) == NULL) goto err;
	
	if (BN_ucmp(f, rsa->n) >= 0)
		{	
		/* usually the padding functions would catch this */
		RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
		goto err;
		}

	if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
		{
		blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
		if (blinding == NULL)
			{
			RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
			goto err;
			}
		}
	
	if (blinding != NULL)
		{
		if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL))
			{
			RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		if (!rsa_blinding_convert(blinding, f, unblind, ctx))
			goto err;
		}

	if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
		((rsa->p != NULL) &&
		(rsa->q != NULL) &&
		(rsa->dmp1 != NULL) &&
		(rsa->dmq1 != NULL) &&
		(rsa->iqmp != NULL)) )
		{ 
		if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) goto err;
		}
	else
		{
		BIGNUM local_d;
		BIGNUM *d = NULL;
		
		if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME))
			{
			BN_init(&local_d);
			d = &local_d;
			BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
			}
		else
			d= rsa->d;

		if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
			if(!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
				goto err;

		if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx,
				rsa->_method_mod_n)) goto err;
		}

	if (blinding)
		if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
			goto err;

	if (padding == RSA_X931_PADDING)
		{
		BN_sub(f, rsa->n, ret);
		if (BN_cmp(ret, f))
			res = f;
		else
			res = ret;
		}
	else
		res = ret;

	/* put in leading 0 bytes if the number is less than the
	 * length of the modulus */
	j=BN_num_bytes(res);
	i=BN_bn2bin(res,&(to[num-j]));
	for (k=0; k<(num-i); k++)
		to[k]=0;

	r=num;
err:
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (buf != NULL)
		{
		OPENSSL_cleanse(buf,num);
		OPENSSL_free(buf);
		}
	return(r);
	}
예제 #14
0
static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
	     unsigned char *to, RSA *rsa, int padding)
	{
	BIGNUM *f,*ret;
	int i,j,k,num=0,r= -1;
	unsigned char *buf=NULL;
	BN_CTX *ctx=NULL;

	if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
		return -1;
		}

	if (BN_ucmp(rsa->n, rsa->e) <= 0)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
		return -1;
		}

	/* for large moduli, enforce exponent limit */
	if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
		{
		if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
			{
			RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
			return -1;
			}
		}
	
	if ((ctx=BN_CTX_new()) == NULL) goto err;
	BN_CTX_start(ctx);
	f = BN_CTX_get(ctx);
	ret = BN_CTX_get(ctx);
	num=BN_num_bytes(rsa->n);
	buf = OPENSSL_malloc(num);
	if (!f || !ret || !buf)
		{
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	switch (padding)
		{
	case RSA_PKCS1_PADDING:
		i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen);
		break;
#ifndef OPENSSL_NO_SHA
	case RSA_PKCS1_OAEP_PADDING:
	        i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0);
		break;
#endif
	case RSA_SSLV23_PADDING:
		i=RSA_padding_add_SSLv23(buf,num,from,flen);
		break;
	case RSA_NO_PADDING:
		i=RSA_padding_add_none(buf,num,from,flen);
		break;
	default:
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_UNKNOWN_PADDING_TYPE);
		goto err;
		}
	if (i <= 0) goto err;

	if (BN_bin2bn(buf,num,f) == NULL) goto err;
	
	if (BN_ucmp(f, rsa->n) >= 0)
		{
		/* usually the padding functions would catch this */
		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
		goto err;
		}

	if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
		if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx))
			goto err;

	if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx,
		rsa->_method_mod_n)) goto err;

	/* put in leading 0 bytes if the number is less than the
	 * length of the modulus */
	j=BN_num_bytes(ret);
	i=BN_bn2bin(ret,&(to[num-j]));
	for (k=0; k<(num-i); k++)
		to[k]=0;

	r=num;
err:
	if (ctx != NULL)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (buf != NULL) 
		{
		OPENSSL_cleanse(buf,num);
		OPENSSL_free(buf);
		}
	return(r);
	}
예제 #15
0
static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len)
	{
	EVP_AES_CCM_CTX *cctx = ctx->cipher_data;
	CCM128_CONTEXT *ccm = &cctx->ccm;
	/* If not set up, return error */
	if (!cctx->iv_set && !cctx->key_set)
		return -1;
	if (!ctx->encrypt && !cctx->tag_set)
		return -1;
	if (!out)
		{
		if (!in)
			{
			if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L,len))
				return -1;
			cctx->len_set = 1;
			return len;
			}
		/* If have AAD need message length */
		if (!cctx->len_set && len)
			return -1;
		CRYPTO_ccm128_aad(ccm, in, len);
		return len;
		}
	/* EVP_*Final() doesn't return any data */
	if (!in)
		return 0;
	/* If not set length yet do it */
	if (!cctx->len_set)
		{
		if (CRYPTO_ccm128_setiv(ccm, ctx->iv, 15 - cctx->L, len))
			return -1;
		cctx->len_set = 1;
		}
	if (ctx->encrypt)
		{
		if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
						cctx->str) :
				CRYPTO_ccm128_encrypt(ccm, in, out, len))
			return -1;
		cctx->tag_set = 1;
		return len;
		}
	else
		{
		int rv = -1;
		if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
						cctx->str) :
				!CRYPTO_ccm128_decrypt(ccm, in, out, len))
			{
			unsigned char tag[16];
			if (CRYPTO_ccm128_tag(ccm, tag, cctx->M))
				{
				if (!memcmp(tag, ctx->buf, cctx->M))
					rv = len;
				}
			}
		if (rv == -1)
			OPENSSL_cleanse(out, len);
		cctx->iv_set = 0;
		cctx->tag_set = 0;
		cctx->len_set = 0;
		return rv;
		}

	}
예제 #16
0
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    unsigned char *buf = NULL;
    int i, err = 1;
    const EVP_MD *md = NULL, *m;
    BIO *in = NULL, *inp;
    BIO *bmd = NULL;
    BIO *out = NULL;
#define PROG_NAME_SIZE  39
    char pname[PROG_NAME_SIZE + 1];
    int separator = 0;
    int debug = 0;
    int keyform = FORMAT_PEM;
    const char *outfile = NULL, *keyfile = NULL;
    const char *sigfile = NULL, *randfile = NULL;
    int out_bin = -1, want_pub = 0, do_verify = 0;
    EVP_PKEY *sigkey = NULL;
    unsigned char *sigbuf = NULL;
    int siglen = 0;
    char *passargin = NULL, *passin = NULL;
#ifndef OPENSSL_NO_ENGINE
    char *engine = NULL;
#endif
    char *hmac_key = NULL;
    char *mac_name = NULL;
    STACK_OF(OPENSSL_STRING) *sigopts = NULL, *macopts = NULL;

    apps_startup();

    if ((buf = (unsigned char *)OPENSSL_malloc(BUFSIZE)) == NULL) {
        BIO_printf(bio_err, "out of memory\n");
        goto end;
    }
    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;

    /* first check the program name */
    program_name(argv[0], pname, sizeof pname);

    md = EVP_get_digestbyname(pname);

    argc--;
    argv++;
    while (argc > 0) {
        if ((*argv)[0] != '-')
            break;
        if (strcmp(*argv, "-c") == 0)
            separator = 1;
        else if (strcmp(*argv, "-r") == 0)
            separator = 2;
        else if (strcmp(*argv, "-rand") == 0) {
            if (--argc < 1)
                break;
            randfile = *(++argv);
        } else if (strcmp(*argv, "-out") == 0) {
            if (--argc < 1)
                break;
            outfile = *(++argv);
        } else if (strcmp(*argv, "-sign") == 0) {
            if (--argc < 1)
                break;
            keyfile = *(++argv);
        } else if (!strcmp(*argv, "-passin")) {
            if (--argc < 1)
                break;
            passargin = *++argv;
        } else if (strcmp(*argv, "-verify") == 0) {
            if (--argc < 1)
                break;
            keyfile = *(++argv);
            want_pub = 1;
            do_verify = 1;
        } else if (strcmp(*argv, "-prverify") == 0) {
            if (--argc < 1)
                break;
            keyfile = *(++argv);
            do_verify = 1;
        } else if (strcmp(*argv, "-signature") == 0) {
            if (--argc < 1)
                break;
            sigfile = *(++argv);
        } else if (strcmp(*argv, "-keyform") == 0) {
            if (--argc < 1)
                break;
            keyform = str2fmt(*(++argv));
        }
#ifndef OPENSSL_NO_ENGINE
        else if (strcmp(*argv, "-engine") == 0) {
            if (--argc < 1)
                break;
            engine = *(++argv);
            e = setup_engine(bio_err, engine, 0);
        }
#endif
        else if (strcmp(*argv, "-hex") == 0)
            out_bin = 0;
        else if (strcmp(*argv, "-binary") == 0)
            out_bin = 1;
        else if (strcmp(*argv, "-d") == 0)
            debug = 1;
        else if (!strcmp(*argv, "-hmac")) {
            if (--argc < 1)
                break;
            hmac_key = *++argv;
        } else if (!strcmp(*argv, "-mac")) {
            if (--argc < 1)
                break;
            mac_name = *++argv;
        } else if (strcmp(*argv, "-sigopt") == 0) {
            if (--argc < 1)
                break;
            if (!sigopts)
                sigopts = sk_OPENSSL_STRING_new_null();
            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, *(++argv)))
                break;
        } else if (strcmp(*argv, "-macopt") == 0) {
            if (--argc < 1)
                break;
            if (!macopts)
                macopts = sk_OPENSSL_STRING_new_null();
            if (!macopts || !sk_OPENSSL_STRING_push(macopts, *(++argv)))
                break;
        } else if ((m = EVP_get_digestbyname(&((*argv)[1]))) != NULL)
            md = m;
        else
            break;
        argc--;
        argv++;
    }

    if (do_verify && !sigfile) {
        BIO_printf(bio_err,
                   "No signature to verify: use the -signature option\n");
        goto end;
    }

    if ((argc > 0) && (argv[0][0] == '-')) { /* bad option */
        BIO_printf(bio_err, "unknown option '%s'\n", *argv);
        BIO_printf(bio_err, "options are\n");
        BIO_printf(bio_err,
                   "-c              to output the digest with separating colons\n");
        BIO_printf(bio_err,
                   "-r              to output the digest in coreutils format\n");
        BIO_printf(bio_err, "-d              to output debug info\n");
        BIO_printf(bio_err, "-hex            output as hex dump\n");
        BIO_printf(bio_err, "-binary         output in binary form\n");
        BIO_printf(bio_err,
                   "-sign   file    sign digest using private key in file\n");
        BIO_printf(bio_err,
                   "-verify file    verify a signature using public key in file\n");
        BIO_printf(bio_err,
                   "-prverify file  verify a signature using private key in file\n");
        BIO_printf(bio_err,
                   "-keyform arg    key file format (PEM or ENGINE)\n");
        BIO_printf(bio_err,
                   "-out filename   output to filename rather than stdout\n");
        BIO_printf(bio_err, "-signature file signature to verify\n");
        BIO_printf(bio_err, "-sigopt nm:v    signature parameter\n");
        BIO_printf(bio_err, "-hmac key       create hashed MAC with key\n");
        BIO_printf(bio_err,
                   "-mac algorithm  create MAC (not neccessarily HMAC)\n");
        BIO_printf(bio_err,
                   "-macopt nm:v    MAC algorithm parameters or key\n");
#ifndef OPENSSL_NO_ENGINE
        BIO_printf(bio_err,
                   "-engine e       use engine e, possibly a hardware device.\n");
#endif

        EVP_MD_do_all_sorted(list_md_fn, bio_err);
        goto end;
    }

    in = BIO_new(BIO_s_file());
    bmd = BIO_new(BIO_f_md());
    if (debug) {
        BIO_set_callback(in, BIO_debug_callback);
        /* needed for windows 3.1 */
        BIO_set_callback_arg(in, (char *)bio_err);
    }

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

    if ((in == NULL) || (bmd == NULL)) {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (out_bin == -1) {
        if (keyfile)
            out_bin = 1;
        else
            out_bin = 0;
    }

    if (randfile)
        app_RAND_load_file(randfile, bio_err, 0);

    if (outfile) {
        if (out_bin)
            out = BIO_new_file(outfile, "wb");
        else
            out = BIO_new_file(outfile, "w");
    } 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 (!out) {
        BIO_printf(bio_err, "Error opening output file %s\n",
                   outfile ? outfile : "(stdout)");
        ERR_print_errors(bio_err);
        goto end;
    }
    if ((! !mac_name + ! !keyfile + ! !hmac_key) > 1) {
        BIO_printf(bio_err, "MAC and Signing key cannot both be specified\n");
        goto end;
    }

    if (keyfile) {
        if (want_pub)
            sigkey = load_pubkey(bio_err, keyfile, keyform, 0, NULL,
                                 e, "key file");
        else
            sigkey = load_key(bio_err, keyfile, keyform, 0, passin,
                              e, "key file");
        if (!sigkey) {
            /*
             * load_[pub]key() has already printed an appropriate message
             */
            goto end;
        }
    }

    if (mac_name) {
        EVP_PKEY_CTX *mac_ctx = NULL;
        int r = 0;
        if (!init_gen_str(bio_err, &mac_ctx, mac_name, e, 0))
            goto mac_end;
        if (macopts) {
            char *macopt;
            for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
                macopt = sk_OPENSSL_STRING_value(macopts, i);
                if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
                    BIO_printf(bio_err,
                               "MAC parameter error \"%s\"\n", macopt);
                    ERR_print_errors(bio_err);
                    goto mac_end;
                }
            }
        }
        if (EVP_PKEY_keygen(mac_ctx, &sigkey) <= 0) {
            BIO_puts(bio_err, "Error generating key\n");
            ERR_print_errors(bio_err);
            goto mac_end;
        }
        r = 1;
mac_end:
        if (mac_ctx)
            EVP_PKEY_CTX_free(mac_ctx);
        if (r == 0)
            goto end;
    }

    if (hmac_key) {
        sigkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, e,
                                      (unsigned char *)hmac_key, -1);
        if (!sigkey)
            goto end;
    }

    if (sigkey) {
        EVP_MD_CTX *mctx = NULL;
        EVP_PKEY_CTX *pctx = NULL;
        int r;
        if (!BIO_get_md_ctx(bmd, &mctx)) {
            BIO_printf(bio_err, "Error getting context\n");
            ERR_print_errors(bio_err);
            goto end;
        }
        if (do_verify)
            r = EVP_DigestVerifyInit(mctx, &pctx, md, NULL, sigkey);
        else
            r = EVP_DigestSignInit(mctx, &pctx, md, NULL, sigkey);
        if (!r) {
            BIO_printf(bio_err, "Error setting context\n");
            ERR_print_errors(bio_err);
            goto end;
        }
        if (sigopts) {
            char *sigopt;
            for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
                sigopt = sk_OPENSSL_STRING_value(sigopts, i);
                if (pkey_ctrl_string(pctx, sigopt) <= 0) {
                    BIO_printf(bio_err, "parameter error \"%s\"\n", sigopt);
                    ERR_print_errors(bio_err);
                    goto end;
                }
            }
        }
    }
    /* we use md as a filter, reading from 'in' */
    else {
        if (md == NULL)
            md = EVP_md5();
        if (!BIO_set_md(bmd, md)) {
            BIO_printf(bio_err, "Error setting digest %s\n", pname);
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (sigfile && sigkey) {
        BIO *sigbio;
        sigbio = BIO_new_file(sigfile, "rb");
        siglen = EVP_PKEY_size(sigkey);
        sigbuf = OPENSSL_malloc(siglen);
        if (!sigbio) {
            BIO_printf(bio_err, "Error opening signature file %s\n", sigfile);
            ERR_print_errors(bio_err);
            goto end;
        }
        siglen = BIO_read(sigbio, sigbuf, siglen);
        BIO_free(sigbio);
        if (siglen <= 0) {
            BIO_printf(bio_err, "Error reading signature file %s\n", sigfile);
            ERR_print_errors(bio_err);
            goto end;
        }
    }
    inp = BIO_push(bmd, in);

    if (md == NULL) {
        EVP_MD_CTX *tctx;
        BIO_get_md_ctx(bmd, &tctx);
        md = EVP_MD_CTX_md(tctx);
    }

    if (argc == 0) {
        BIO_set_fp(in, stdin, BIO_NOCLOSE);
        err = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
                    siglen, NULL, NULL, "stdin", bmd);
    } else {
        const char *md_name = NULL, *sig_name = NULL;
        if (!out_bin) {
            if (sigkey) {
                const EVP_PKEY_ASN1_METHOD *ameth;
                ameth = EVP_PKEY_get0_asn1(sigkey);
                if (ameth)
                    EVP_PKEY_asn1_get0_info(NULL, NULL,
                                            NULL, NULL, &sig_name, ameth);
            }
            md_name = EVP_MD_name(md);
        }
        err = 0;
        for (i = 0; i < argc; i++) {
            int r;
            if (BIO_read_filename(in, argv[i]) <= 0) {
                perror(argv[i]);
                err++;
                continue;
            } else
                r = do_fp(out, buf, inp, separator, out_bin, sigkey, sigbuf,
                          siglen, sig_name, md_name, argv[i], bmd);
            if (r)
                err = r;
            (void)BIO_reset(bmd);
        }
    }
end:
    if (buf != NULL) {
        OPENSSL_cleanse(buf, BUFSIZE);
        OPENSSL_free(buf);
    }
    if (in != NULL)
        BIO_free(in);
    if (passin)
        OPENSSL_free(passin);
    BIO_free_all(out);
    EVP_PKEY_free(sigkey);
    if (sigopts)
        sk_OPENSSL_STRING_free(sigopts);
    if (macopts)
        sk_OPENSSL_STRING_free(macopts);
    if (sigbuf)
        OPENSSL_free(sigbuf);
    if (bmd != NULL)
        BIO_free(bmd);
    apps_shutdown();
    OPENSSL_EXIT(err);
}
예제 #17
0
static int read_string_inner(UI *ui, UI_STRING *uis, int echo, int strip_nl)
	{
	static int ps;
	int ok;
	char result[BUFSIZ];
	int maxsize = BUFSIZ-1;
#if !defined(OPENSSL_SYS_WIN16) && !defined(OPENSSL_SYS_WINCE)
	char *p;

	intr_signal=0;
	ok=0;
	ps=0;

	pushsig();
	ps=1;

	if (!echo && !noecho_console(ui))
		goto error;
	ps=2;

	result[0]='\0';
#ifdef OPENSSL_SYS_MSDOS
	if (!echo)
		{
		noecho_fgets(result,maxsize,tty_in);
		p=result; /* FIXME: noecho_fgets doesn't return errors */
		}
	else
		p=fgets(result,maxsize,tty_in);
#else
	p=fgets(result,maxsize,tty_in);
#endif
	if(!p)
		goto error;
	if (feof(tty_in)) goto error;
	if (ferror(tty_in)) goto error;
	if ((p=(char *)strchr(result,'\n')) != NULL)
		{
		if (strip_nl)
			*p='\0';
		}
	else
		if (!read_till_nl(tty_in))
			goto error;
	if (UI_set_result(ui, uis, result) >= 0)
		ok=1;

error:
	if (intr_signal == SIGINT)
		ok=-1;
	if (!echo) fprintf(tty_out,"\n");
	if (ps >= 2 && !echo && !echo_console(ui))
		ok=0;

	if (ps >= 1)
		popsig();
#else
	ok=1;
#endif

	OPENSSL_cleanse(result,BUFSIZ);
	return ok;
	}
예제 #18
0
/**
*ハッシュ値生成関数
* @author University of Tsukuba
* @param *ptr ハッシュ対象データ
* @param lLenIn ハッシュデータ長
* @param lalgorithm ハッシュアルゴリズム
* @param *ptrData  	ハッシュ値
* @param *lLenOut	ハッシュ値データ長
* @return	long	0:正常 -1:異常
* @since 2008.02
* @version 1.0
*/
long IDMan_CmMkHash(void *ptr, long lLenIn, long lalgorithm, void *ptrData, long *lLenOut)
{
	long 			lRet = -1L;
	SHA_CTX 		ctx;
	SHA256_CTX 		ctx2;
	SHA512_CTX 		ctx3;
	char 			szErrBuff[1024];

	ERR_load_crypto_strings();

	IDMan_StMemset(szErrBuff, 0x00, sizeof(szErrBuff));
	/** ハッシュ対象データパラメータチェックを行う。 */
	/** エラー発生した場合、 */
	if ( ptr == 0x00 )
	{ 
		/** −処理を中断する。 */
		return lRet;
	}
	/** ハッシュデータ長パラメータチェックを行う。 */
	/** エラー発生した場合、 */
	if ( lLenIn == 0 ){
		/** −処理を中断する。 */
		return lRet;
	}
	/** ハッシュ値パラメータチェックを行う。 */
	/** エラー発生した場合、 */
	if ( ptrData == 0x00 )
	{
		/** −処理を中断する。 */
		return lRet;
	}
	/** ハッシュ値データ長パラメータチェックを行う。 */
	/** エラー発生した場合、 */
	if ( lLenOut == 0x00 ) 
	{
		/** −処理を中断する。 */
		return lRet;
	}
	else
	{
		/** −戻り値の初期化を行う。 */
		*lLenOut=0;
	}

	/** ハッシュ化を行う。 */
	switch(lalgorithm)
	{
		case 0:
			break;
		/** アルゴリズムが0x220の場合、 */
		case ALGORITHM_SHA1:
			/** −ハッシュ変換 SHA1を行う。 */
			SHA1_Init (&ctx);
			SHA1_Update (&ctx, ptr, lLenIn);
			SHA1_Final (ptrData, &ctx);
			OPENSSL_cleanse (&ctx, sizeof (ctx));
			/** −ハッシュ変換が成功の場合、 */
			if ( ptrData != 0x00)
			{
				/** −−長さを設定する。 */
				*lLenOut = HASH_LEN_SHA1;
				lRet =0;
			}
			/** −ハッシュ変換が失敗の場合、 */
			else
			{
				/** −−エラーログを出力する。 */
				ERR_error_string(ERR_get_error(), szErrBuff);
			}
			break;
		/** アルゴリズムが0x250の場合、 */
		case ALGORITHM_SHA256:
			/** −ハッシュ変換 SHA256を行う。 */
			SHA256_Init (&ctx2);
			SHA256_Update (&ctx2, ptr, lLenIn);
			SHA256_Final (ptrData, &ctx2);
			OPENSSL_cleanse (&ctx2, sizeof (ctx2));
			/** −ハッシュ変換が成功の場合、 */
			if ( ptrData != 0x00)
			{
				/** −−長さを設定する。 */
				*lLenOut = HASH_LEN_SHA256;
				lRet =0;
			}
			/** −ハッシュ変換が失敗の場合、 */
			else
			{
				/** −−エラーログを出力する。 */
				ERR_error_string(ERR_get_error(), szErrBuff);
			}
			break;
		/** アルゴリズムが0x270の場合、 */
		case ALGORITHM_SHA512:
			/** −ハッシュ変換 SHA512を行う。 */
			SHA512_Init (&ctx3);
			SHA512_Update (&ctx3, ptr, lLenIn);
			SHA512_Final (ptrData, &ctx3);
			OPENSSL_cleanse (&ctx3, sizeof (ctx3));
			/** −ハッシュ変換が成功の場合、 */
			if ( ptrData != 0x00)
			{
				/** −−長さを設定する。 */
				*lLenOut = HASH_LEN_SHA512;
				lRet =0;
			}
			/** −ハッシュ変換が失敗の場合、 */
			else
			{
				/** −−エラーログを出力する。 */
				ERR_error_string(ERR_get_error(), szErrBuff);
			}
			break;
		default:
			break;
	}
	return lRet;
}
예제 #19
0
static DSA_SIG *capi_dsa_do_sign(const unsigned char *digest, int dlen,
								DSA *dsa)
	{
	HCRYPTHASH hash;
	DWORD slen;
	DSA_SIG *ret = NULL;
	CAPI_KEY *capi_key;
	CAPI_CTX *ctx;
	unsigned char csigbuf[40];

	ctx = ENGINE_get_ex_data(dsa->engine, capi_idx);

	CAPI_trace(ctx, "Called CAPI_dsa_do_sign()\n");

	capi_key = DSA_get_ex_data(dsa, dsa_capi_idx);

	if (!capi_key)
		{
		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_GET_KEY);
		return NULL;
		}

	if (dlen != 20)
		{
		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_INVALID_DIGEST_LENGTH);
		return NULL;
		}

	/* Create the hash object */
	if(!CryptCreateHash(capi_key->hprov, CALG_SHA1, 0, 0, &hash))
		{
		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_CREATE_HASH_OBJECT);
		capi_addlasterror();
		return NULL;
		}

	/* Set the hash value to the value passed */
	if(!CryptSetHashParam(hash, HP_HASHVAL, (unsigned char *)digest, 0))
		{
		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_CANT_SET_HASH_VALUE);
		capi_addlasterror();
		goto err;
		}


	/* Finally sign it */
	slen = sizeof(csigbuf);
	if(!CryptSignHash(hash, capi_key->keyspec, NULL, 0, csigbuf, &slen))
		{
		CAPIerr(CAPI_F_CAPI_DSA_DO_SIGN, CAPI_R_ERROR_SIGNING_HASH);
		capi_addlasterror();
		goto err;
		}
	else
		{
		ret = DSA_SIG_new();
		if (!ret)
			goto err;
		ret->r = BN_new();
		ret->s = BN_new();
		if (!ret->r || !ret->s)
			goto err;
		if (!lend_tobn(ret->r, csigbuf, 20)
			|| !lend_tobn(ret->s, csigbuf + 20, 20))
			{
			DSA_SIG_free(ret);
			ret = NULL;
			goto err;
			}
		}

	/* Now cleanup */

err:
	OPENSSL_cleanse(csigbuf, 40);
	CryptDestroyHash(hash);
	return ret;
	}
예제 #20
0
int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
                       void *x, const EVP_CIPHER *enc, unsigned char *kstr,
                       int klen, pem_password_cb *callback, void *u)
{
    EVP_CIPHER_CTX *ctx = NULL;
    int dsize = 0, i = 0, j = 0, ret = 0;
    unsigned char *p, *data = NULL;
    const char *objstr = NULL;
    char buf[PEM_BUFSIZE];
    unsigned char key[EVP_MAX_KEY_LENGTH];
    unsigned char iv[EVP_MAX_IV_LENGTH];

    if (enc != NULL) {
        objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
        if (objstr == NULL || EVP_CIPHER_iv_length(enc) == 0) {
            PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER);
            goto err;
        }
    }

    if ((dsize = i2d(x, NULL)) < 0) {
        PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_ASN1_LIB);
        dsize = 0;
        goto err;
    }
    /* dzise + 8 bytes are needed */
    /* actually it needs the cipher block size extra... */
    data = OPENSSL_malloc((unsigned int)dsize + 20);
    if (data == NULL) {
        PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    p = data;
    i = i2d(x, &p);

    if (enc != NULL) {
        if (kstr == NULL) {
            if (callback == NULL)
                klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u);
            else
                klen = (*callback) (buf, PEM_BUFSIZE, 1, u);
            if (klen <= 0) {
                PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_READ_KEY);
                goto err;
            }
#ifdef CHARSET_EBCDIC
            /* Convert the pass phrase from EBCDIC */
            ebcdic2ascii(buf, buf, klen);
#endif
            kstr = (unsigned char *)buf;
        }
        RAND_add(data, i, 0);   /* put in the RSA key. */
        OPENSSL_assert(EVP_CIPHER_iv_length(enc) <= (int)sizeof(iv));
        if (RAND_bytes(iv, EVP_CIPHER_iv_length(enc)) <= 0) /* Generate a salt */
            goto err;
        /*
         * The 'iv' is used as the iv and as a salt.  It is NOT taken from
         * the BytesToKey function
         */
        if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL))
            goto err;

        if (kstr == (unsigned char *)buf)
            OPENSSL_cleanse(buf, PEM_BUFSIZE);

        OPENSSL_assert(strlen(objstr) + 23 + 2 * EVP_CIPHER_iv_length(enc) + 13
                       <= sizeof buf);

        buf[0] = '\0';
        PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
        PEM_dek_info(buf, objstr, EVP_CIPHER_iv_length(enc), (char *)iv);
        /* k=strlen(buf); */

        ret = 1;
        if ((ctx = EVP_CIPHER_CTX_new()) == NULL
            || !EVP_EncryptInit_ex(ctx, enc, NULL, key, iv)
            || !EVP_EncryptUpdate(ctx, data, &j, data, i)
            || !EVP_EncryptFinal_ex(ctx, &(data[j]), &i))
            ret = 0;
        if (ret == 0)
            goto err;
        i += j;
    } else {
        ret = 1;
        buf[0] = '\0';
    }
    i = PEM_write_bio(bp, name, buf, data, i);
    if (i <= 0)
        ret = 0;
 err:
    OPENSSL_cleanse(key, sizeof(key));
    OPENSSL_cleanse(iv, sizeof(iv));
    EVP_CIPHER_CTX_free(ctx);
    OPENSSL_cleanse(buf, PEM_BUFSIZE);
    OPENSSL_clear_free(data, (unsigned int)dsize);
    return (ret);
}
예제 #21
0
/* seed1 through seed5 are virtually concatenated */
static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
			int sec_len,
			const void *seed1, int seed1_len,
			const void *seed2, int seed2_len,
			const void *seed3, int seed3_len,
			const void *seed4, int seed4_len,
			const void *seed5, int seed5_len,
			unsigned char *out, int olen)
	{
	int chunk;
	size_t j;
	EVP_MD_CTX ctx, ctx_tmp;
	EVP_PKEY *mac_key;
	unsigned char A1[EVP_MAX_MD_SIZE];
	size_t A1_len;
	int ret = 0;
	
	chunk=EVP_MD_size(md);
	OPENSSL_assert(chunk >= 0);

	EVP_MD_CTX_init(&ctx);
	EVP_MD_CTX_init(&ctx_tmp);
	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
	EVP_MD_CTX_set_flags(&ctx_tmp, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
	mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
	if (!mac_key)
		goto err;
	if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
		goto err;
	if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
		goto err;
	if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
		goto err;
	if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
		goto err;
	if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
		goto err;
	if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
		goto err;
	if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
		goto err;
	if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
		goto err;

	for (;;)
		{
		/* Reinit mac contexts */
		if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
			goto err;
		if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
			goto err;
		if (!EVP_DigestSignUpdate(&ctx,A1,A1_len))
			goto err;
		if (!EVP_DigestSignUpdate(&ctx_tmp,A1,A1_len))
			goto err;
		if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
			goto err;
		if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
			goto err;
		if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
			goto err;
		if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
			goto err;
		if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
			goto err;

		if (olen > chunk)
			{
			if (!EVP_DigestSignFinal(&ctx,out,&j))
				goto err;
			out+=j;
			olen-=j;
			/* calc the next A1 value */
			if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len))
				goto err;
			}
		else	/* last one */
			{
			if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
				goto err;
			memcpy(out,A1,olen);
			break;
			}
		}
	ret = 1;
err:
	EVP_PKEY_free(mac_key);
	EVP_MD_CTX_cleanup(&ctx);
	EVP_MD_CTX_cleanup(&ctx_tmp);
	OPENSSL_cleanse(A1,sizeof(A1));
	return ret;
	}
예제 #22
0
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total)
{
	int r, i;
	BIGNUM *prime;
	BIGNUM *secret;
	unsigned char buf[64];
	char hex[64];
	int l;

	secret_share_t *shares = NULL;
	secret_share_t *sp;

	u8 rngseed[16];

	if ((password_shares_threshold == -1) || (password_shares_total == -1)) {
		fprintf(stderr, "Must specify both, --pwd-shares-total and --pwd-shares-threshold\n");
		return -1;
	}

	if (password_shares_total < 3) {
		fprintf(stderr, "--pwd-shares-total must be 3 or larger\n");
		return -1;
	}

	if (password_shares_threshold < 2) {
		fprintf(stderr, "--pwd-shares-threshold must 2 or larger\n");
		return -1;
	}

	if (password_shares_threshold > password_shares_total) {
		fprintf(stderr, "--pwd-shares-threshold must be smaller or equal to --pwd-shares-total\n");
		return -1;
	}

	printf(	"\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n");
	printf(	"This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total);

	printf(	"Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n");
	printf(	"to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n");
	printf(	"of the file can be generated using \"openssl base64 -in <filename>\".\n");

	printf("\n\nPress <enter> to continue");

	waitForEnterKeyPressed();

	*pwd = calloc(1, 8);
	*pwdlen = 8;

	r = sc_get_challenge(card, (unsigned char *)*pwd, 8);
	if (r < 0) {
		printf("Error generating random key failed with %s", sc_strerror(r));
		OPENSSL_cleanse(*pwd, *pwdlen);
		free(*pwd);
		return r;
	}
	**pwd &= 0x7F; // Make sure the bit size of the secret is not bigger than 63 bits

	/*
	 * Initialize prime and secret
	 */
	prime = BN_new();
	secret = BN_new();

	/*
	 * Encode the secret value
	 */
	BN_bin2bn((unsigned char *)*pwd, *pwdlen, secret);

	/*
	 * Generate seed and calculate a prime depending on the size of the secret
	 */
	r = sc_get_challenge(card, rngseed, SEED_LENGTH);
	if (r < 0) {
		printf("Error generating random seed failed with %s", sc_strerror(r));
		OPENSSL_cleanse(*pwd, *pwdlen);
		free(*pwd);
		return r;
	}

	r = generatePrime(prime, secret, 64, rngseed, SEED_LENGTH);
	if (r < 0) {
		printf("Error generating valid prime number. Please try again.");
		OPENSSL_cleanse(*pwd, *pwdlen);
		free(*pwd);
		return r;
	}

	// Allocate data buffer for the generated shares
	shares = malloc(password_shares_total * sizeof(secret_share_t));

	createShares(secret, password_shares_threshold, password_shares_total, prime, shares);

	sp = shares;
	for (i = 0; i < password_shares_total; i++) {
		clearScreen();

		printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total);
		waitForEnterKeyPressed();

		clearScreen();

		printf("Share %i of %i\n\n", i + 1, password_shares_total);

		l = BN_bn2bin(prime, buf);
		sc_bin_to_hex(buf, l, hex, 64, ':');
		printf("\nPrime       : %s\n", hex);

		printf("Share ID    : %s\n", BN_bn2dec((sp->x)));
		l = BN_bn2bin((sp->y), buf);
		sc_bin_to_hex(buf, l, hex, 64, ':');
		printf("Share value : %s\n", hex);

		printf("\n\nPlease note ALL values above and press <enter> when finished");
		waitForEnterKeyPressed();

		sp++;
	}

	clearScreen();

	cleanUpShares(shares, password_shares_total);

	BN_clear_free(prime);
	BN_clear_free(secret);

	return 0;
}
예제 #23
0
int tls1_setup_key_block(SSL *s)
	{
	unsigned char *p1,*p2=NULL;
	const EVP_CIPHER *c;
	const EVP_MD *hash;
	int num;
	SSL_COMP *comp;
	int mac_type= NID_undef,mac_secret_size=0;
	int ret=0;

#ifdef KSSL_DEBUG
	printf ("tls1_setup_key_block()\n");
#endif	/* KSSL_DEBUG */

	if (s->s3->tmp.key_block_length != 0)
		return(1);

	if (!ssl_cipher_get_evp(s->session,&c,&hash,&mac_type,&mac_secret_size,&comp))
		{
		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
		return(0);
		}

	s->s3->tmp.new_sym_enc=c;
	s->s3->tmp.new_hash=hash;
	s->s3->tmp.new_mac_pkey_type = mac_type;
	s->s3->tmp.new_mac_secret_size = mac_secret_size;
	num=EVP_CIPHER_key_length(c)+mac_secret_size+EVP_CIPHER_iv_length(c);
	num*=2;

	ssl3_cleanup_key_block(s);

	if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL)
		{
		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	s->s3->tmp.key_block_length=num;
	s->s3->tmp.key_block=p1;

	if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL)
		{
		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
		goto err;
		}

#ifdef TLS_DEBUG
printf("client random\n");
{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); }
printf("server random\n");
{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); }
printf("pre-master\n");
{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
#endif
	if (!tls1_generate_key_block(s,p1,p2,num))
		goto err;
#ifdef TLS_DEBUG
printf("\nkey block\n");
{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
#endif

	if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)
		&& s->method->version <= TLS1_VERSION)
		{
		/* enable vulnerability countermeasure for CBC ciphers with
		 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt)
		 */
		s->s3->need_empty_fragments = 1;

		if (s->session->cipher != NULL)
			{
			if (s->session->cipher->algorithm_enc == SSL_eNULL)
				s->s3->need_empty_fragments = 0;
			
#ifndef OPENSSL_NO_RC4
			if (s->session->cipher->algorithm_enc == SSL_RC4)
				s->s3->need_empty_fragments = 0;
#endif
			}
		}
		
	ret = 1;
err:
	if (p2)
		{
		OPENSSL_cleanse(p2,num);
		OPENSSL_free(p2);
		}
	return(ret);
	}
예제 #24
0
static int create_dkek_share(sc_card_t *card, const char *outf, int iter, const char *password, int password_shares_threshold, int password_shares_total)
{
	EVP_CIPHER_CTX *ctx = NULL;
	FILE *out = NULL;
	u8 filebuff[64], key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
	u8 dkek_share[32];
	char *pwd = NULL;
	int r = 0, outlen, pwdlen = 0;

	if (outf == NULL) {
		fprintf(stderr, "No file name specified for DKEK share\n");
		return -1;
	}

	if (password == NULL) {
		if ((password_shares_threshold == -1) && (password_shares_total == -1)) {
			ask_for_password(&pwd, &pwdlen);
		} else { // create password using threshold scheme
			r = generate_pwd_shares(card, &pwd, &pwdlen, password_shares_threshold, password_shares_total);
		}

	} else {
		pwd = (char *) password;
		pwdlen = strlen(password);
	}

	if (r < 0) {
		fprintf(stderr, "Creating DKEK share failed\n");
		return -1;
	}

	memcpy(filebuff, magic, sizeof(magic) - 1);

	r = sc_get_challenge(card, filebuff + 8, 8);
	if (r < 0) {
		fprintf(stderr, "Error generating random number failed with %s\n", sc_strerror(r));
		return -1;
	}

	printf("Enciphering DKEK share, please wait...\n");
	EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv);

	if (password == NULL) {
		OPENSSL_cleanse(pwd, pwdlen);
		free(pwd);
	}

	r = sc_get_challenge(card, dkek_share, sizeof(dkek_share));
	if (r < 0) {
		fprintf(stderr, "Error generating random number failed with %s\n", sc_strerror(r));
		return -1;
	}

	ctx = EVP_CIPHER_CTX_new();
	EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
	if (!EVP_EncryptUpdate(ctx, filebuff + 16, &outlen, dkek_share, sizeof(dkek_share))) {
		fprintf(stderr, "Error encrypting DKEK share\n");
		return -1;
	}

	if (!EVP_EncryptFinal_ex(ctx, filebuff + 16 + outlen, &r)) {
		fprintf(stderr, "Error encrypting DKEK share\n");
		return -1;
	}

	out = fopen(outf, "wb");

	if (out == NULL) {
		perror(outf);
		return -1;
	}

	if (fwrite(filebuff, 1, sizeof(filebuff), out) != sizeof(filebuff)) {
		perror(outf);
		fclose(out);
		return -1;
	}

	fclose(out);

	OPENSSL_cleanse(filebuff, sizeof(filebuff));
	EVP_CIPHER_CTX_free(ctx);

	printf("DKEK share created and saved to %s\n", outf);
	return 0;
}
예제 #25
0
int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2,
	      ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey,
	      const EVP_MD *type)
	{
	EVP_MD_CTX ctx;
	unsigned char *p,*buf_in=NULL,*buf_out=NULL;
	int i,inl=0,outl=0,outll=0;
	X509_ALGOR *a;

	EVP_MD_CTX_init(&ctx);
	for (i=0; i<2; i++)
		{
		if (i == 0)
			a=algor1;
		else
			a=algor2;
		if (a == NULL) continue;
                if (type->pkey_type == NID_dsaWithSHA1)
			{
			/* special case: RFC 2459 tells us to omit 'parameters'
			 * with id-dsa-with-sha1 */
			ASN1_TYPE_free(a->parameter);
			a->parameter = NULL;
			}
		else if ((a->parameter == NULL) || 
			(a->parameter->type != V_ASN1_NULL))
			{
			ASN1_TYPE_free(a->parameter);
			if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err;
			a->parameter->type=V_ASN1_NULL;
			}
		ASN1_OBJECT_free(a->algorithm);
		a->algorithm=OBJ_nid2obj(type->pkey_type);
		if (a->algorithm == NULL)
			{
			ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_UNKNOWN_OBJECT_TYPE);
			goto err;
			}
		if (a->algorithm->length == 0)
			{
			ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
			goto err;
			}
		}
	inl=i2d(data,NULL);
	buf_in=(unsigned char *)OPENSSL_malloc((unsigned int)inl);
	outll=outl=EVP_PKEY_size(pkey);
	buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl);
	if ((buf_in == NULL) || (buf_out == NULL))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	p=buf_in;

	i2d(data,&p);
	if (!EVP_SignInit_ex(&ctx,type, NULL)
		|| !EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl)
		|| !EVP_SignFinal(&ctx,(unsigned char *)buf_out,
			(unsigned int *)&outl,pkey))
		{
		outl=0;
		ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB);
		goto err;
		}
	if (signature->data != NULL) OPENSSL_free(signature->data);
	signature->data=buf_out;
	buf_out=NULL;
	signature->length=outl;
	/* In the interests of compatibility, I'll make sure that
	 * the bit string has a 'not-used bits' value of 0
	 */
	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
err:
	EVP_MD_CTX_cleanup(&ctx);
	if (buf_in != NULL)
		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
	if (buf_out != NULL)
		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
	return(outl);
	}
예제 #26
0
static int print_dkek_share(sc_card_t *card, const char *inf, int iter, const char *password, int num_of_password_shares)
{
	// hex output can be used in the SCSH shell with the 
	// decrypt_keyblob.js file
	sc_cardctl_sc_hsm_dkek_t dkekinfo;
	EVP_CIPHER_CTX *ctx = NULL;
	FILE *in = NULL;
	u8 filebuff[64],key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH],outbuff[64];
	char *pwd = NULL;
	int r, outlen, pwdlen;
	u8 i;

	if (inf == NULL) {
		fprintf(stderr, "No file name specified for DKEK share\n");
		return -1;
	}

	in = fopen(inf, "rb");

	if (in == NULL) {
		perror(inf);
		return -1;
	}

	if (fread(filebuff, 1, sizeof(filebuff), in) != sizeof(filebuff)) {
		perror(inf);
		fclose(in);
		return -1;
	}

	fclose(in);

	if (memcmp(filebuff, magic, sizeof(magic) - 1)) {
		fprintf(stderr, "File %s is not a DKEK share\n", inf);
		return -1;
	}

	if (password == NULL) {

		if (num_of_password_shares == -1) {
			printf("Enter password to decrypt DKEK share : ");
			util_getpass(&pwd, NULL, stdin);
			pwdlen = strlen(pwd);
			printf("\n");
		} else {
			r = recreate_password_from_shares(&pwd, &pwdlen, num_of_password_shares);
			if (r < 0) {
				return -1;
			}
		}

	} else {
		pwd = (char *) password;
		pwdlen = strlen(password);
	}

	printf("Deciphering DKEK share, please wait...\n");
	EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv);
	OPENSSL_cleanse(pwd, strlen(pwd));

	if (password == NULL) {
		free(pwd);
	}

	ctx = EVP_CIPHER_CTX_new();
	EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv);
	if (!EVP_DecryptUpdate(ctx, outbuff, &outlen, filebuff + 16, sizeof(filebuff) - 16)) {
		fprintf(stderr, "Error decrypting DKEK share. Password correct ?\n");
		return -1;
	}

	if (!EVP_DecryptFinal_ex(ctx, outbuff + outlen, &r)) {
		fprintf(stderr, "Error decrypting DKEK share. Password correct ?\n");
		return -1;
	}

	memset(&dkekinfo, 0, sizeof(dkekinfo));
	memcpy(dkekinfo.dkek_share, outbuff, sizeof(dkekinfo.dkek_share));
	dkekinfo.importShare = 1;

	OPENSSL_cleanse(outbuff, sizeof(outbuff));

	printf("DKEK Share HEX: \n\n");

	for (i = 0; i < sizeof(dkekinfo.dkek_share); i++)
	{
	    printf("%02X", dkekinfo.dkek_share[i]);
	}
	printf("\n\n");

	OPENSSL_cleanse(&dkekinfo.dkek_share, sizeof(dkekinfo.dkek_share));
	EVP_CIPHER_CTX_free(ctx);

	if (r == SC_ERROR_INS_NOT_SUPPORTED) {			// Not supported or not initialized for key shares
		fprintf(stderr, "Not supported by card or card not initialized for key share usage\n");
		return -1;
	}

	if (r < 0) {
		fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, *) failed with %s\n", sc_strerror(r));
		return -1;
	}
	//printf("DKEK share imported\n");
	//print_dkek_info(&dkekinfo);
	return 0;
}
예제 #27
0
파일: pk7_doit.c 프로젝트: hlcherub/src
static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
			       PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey)
	{
	EVP_PKEY_CTX *pctx = NULL;
	unsigned char *ek = NULL;
	size_t eklen;

	int ret = -1;

	pctx = EVP_PKEY_CTX_new(pkey, NULL);
	if (!pctx)
		return -1;

	if (EVP_PKEY_decrypt_init(pctx) <= 0)
		goto err;

	if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT,
				EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0)
		{
		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR);
		goto err;
		}

	if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
				ri->enc_key->data, ri->enc_key->length) <= 0)
		goto err;

	ek = OPENSSL_malloc(eklen);

	if (ek == NULL)
		{
		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (EVP_PKEY_decrypt(pctx, ek, &eklen,
				ri->enc_key->data, ri->enc_key->length) <= 0)
		{
		ret = 0;
		PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB);
		goto err;
		}

	ret = 1;

	if (*pek)
		{
		OPENSSL_cleanse(*pek, *peklen);
		OPENSSL_free(*pek);
		}

	*pek = ek;
	*peklen = eklen;

	err:
	if (pctx)
		EVP_PKEY_CTX_free(pctx);
	if (!ret && ek)
		OPENSSL_free(ek);

	return ret;
	}
예제 #28
0
static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len)
	{
	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
	int rv = -1;
	/* Encrypt/decrypt must be performed in place */
	if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN+EVP_GCM_TLS_TAG_LEN))
		return -1;
	/* Set IV from start of buffer or generate IV and write to start
	 * of buffer.
	 */
	if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ?
				EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
				EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
		goto err;
	/* Use saved AAD */
	if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
		goto err;
	/* Fix buffer and length to point to payload */
	in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
	out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
	len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
	if (ctx->encrypt)
		{
		/* Encrypt payload */
		if (gctx->ctr)
			{
			if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
							in, out, len,
							gctx->ctr))
				goto err;
			}
		else	{
			if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
				goto err;
			}
		out += len;
		/* Finally write tag */
		CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
		rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
		}
	else
		{
		/* Decrypt */
		if (gctx->ctr)
			{
			if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
							in, out, len,
							gctx->ctr))
				goto err;
			}
		else	{
			if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
				goto err;
			}
		/* Retrieve tag */
		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf,
					EVP_GCM_TLS_TAG_LEN);
		/* If tag mismatch wipe buffer */
		if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN))
			{
			OPENSSL_cleanse(out, len);
			goto err;
			}
		rv = len;
		}

	err:
	gctx->iv_set = 0;
	gctx->tls_aad_len = -1;
	return rv;
	}
예제 #29
0
파일: pk7_doit.c 프로젝트: hlcherub/src
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
       unsigned char *ek = NULL, *tkey = NULL;
       int eklen = 0, tkeylen = 0;

	if (p7 == NULL) {
		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
		return NULL;
	}

	if (p7->d.ptr == NULL) {
		PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
		return NULL;
	}

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
		if (!PKCS7_is_detached(p7) && data_body == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_INVALID_SIGNED_DATA_TYPE);
			goto err;
			}
		md_sk=p7->d.sign->md_algs;
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		enc_alg=p7->d.enveloped->enc_data->algorithm;
		data_body=p7->d.enveloped->enc_data->enc_data;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

    /* Detached content must be supplied via in_bio instead. */
    if (data_body == NULL && in_bio == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
        goto err;
    }

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
			{
			xa=sk_X509_ALGOR_value(md_sk,i);
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbynid(j);
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
			btmp=NULL;
			}
		}

	if (evp_cipher != NULL)
		{
#if 0
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char *p;
		int keylen,ivlen;
		int max;
		X509_OBJECT ret;
#endif

		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
			goto err;
			}

		/* It was encrypted, we need to decrypt the secret key
		 * with the private key */

		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
		 */

		if (pcert)
			{
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
				{
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				if (!pkcs7_cmp_ri(ri, pcert))
					break;
				ri=NULL;
				}
			if (ri == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
				goto err;
				}
			}

		/* If we haven't got a certificate try each ri in turn */
		if (pcert == NULL)
			{
			/* Always attempt to decrypt all rinfo even
			 * after sucess as a defence against MMA timing
			 * attacks.
			 */
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
				{
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				
				if (pkcs7_decrypt_rinfo(&ek, &eklen,
							ri, pkey) < 0)
					goto err;
				ERR_clear_error();
				}
			}
		else
			{
			/* Only exit on fatal errors, not decrypt failure */
			if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0)
				goto err;
			ERR_clear_error();
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
			goto err;
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
			goto err;
		/* Generate random key as MMA defence */
		tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
		tkey = OPENSSL_malloc(tkeylen);
		if (!tkey)
			goto err;
		if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
			goto err;
		if (ek == NULL)
			{
			ek = tkey;
			eklen = tkeylen;
			tkey = NULL;
			}

		if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
			/* Some S/MIME clients don't use the same key
			 * and effective key length. The key length is
			 * determined by the size of the decrypted RSA key.
			 */
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen))
				{
				/* Use random key as MMA defence */
				OPENSSL_cleanse(ek, eklen);
				OPENSSL_free(ek);
				ek = tkey;
				eklen = tkeylen;
				tkey = NULL;
				}
		} 
		/* Clear errors so we don't leak information useful in MMA */
		ERR_clear_error();
		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,ek,NULL,0) <= 0)
			goto err;

		if (ek)
			{
			OPENSSL_cleanse(ek,eklen);
			OPENSSL_free(ek);
                       ek = NULL;
			}
		if (tkey)
			{
			OPENSSL_cleanse(tkey,tkeylen);
			OPENSSL_free(tkey);
                       tkey = NULL;
			}

		if (out == NULL)
			out=etmp;
		else
			BIO_push(out,etmp);
		etmp=NULL;
		}

#if 1
	if (in_bio != NULL)
		{
		bio=in_bio;
		}
	else 
		{
#if 0
		bio=BIO_new(BIO_s_mem());
		/* We need to set this so that when we have read all
		 * the data, the encrypt BIO, if present, will read
		 * EOF and encode the last few bytes */
		BIO_set_mem_eof_return(bio,0);

		if (data_body->length > 0)
			BIO_write(bio,(char *)data_body->data,data_body->length);
#else
		if (data_body->length > 0)
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
		else {
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
		}
		if (bio == NULL)
			goto err;
#endif
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
err:
               if (ek)
                       {
                       OPENSSL_cleanse(ek,eklen);
                       OPENSSL_free(ek);
                       }
               if (tkey)
                       {
                       OPENSSL_cleanse(tkey,tkeylen);
                       OPENSSL_free(tkey);
                       }
		if (out != NULL) BIO_free_all(out);
		if (btmp != NULL) BIO_free_all(btmp);
		if (etmp != NULL) BIO_free_all(etmp);
		if (bio != NULL) BIO_free_all(bio);
		out=NULL;
		}
	return(out);
	}
예제 #30
0
/* ========= ClientKeyExchange ========= */
int ssl3_decode_client_key_exchange( DSSL_Session* sess, u_char* data, uint32_t len )
{
	EVP_PKEY *pk = NULL;
	u_char* org_data = data;
	uint32_t org_len = len;
	int pms_len = 0;
	int rc = DSSL_RC_OK;

	if( sess->version < SSL3_VERSION || sess->version > TLS1_2_VERSION )
	{
		return NM_ERROR( DSSL_E_SSL_UNKNOWN_VERSION );
	}

	/* 
	TLS is different as it sends the record length, while SSL3 implementaions don't
	(due to a bug in Netscape implementation)
	*/
	if( sess->version > SSL3_VERSION )
	{
		uint16_t recLen = 0;
		if( !IS_ENOUGH_LENGTH( org_data, org_len, data, 2 ) ) 
		{
			return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		recLen = MAKE_UINT16( data[0], data[1] );
		if( len != (uint32_t)recLen + 2 )
		{
			/*TODO: set an option to tolerate this bug?*/
			return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
		}

		/* advance */
		data += len - recLen;
		len = recLen;
	}

	if( !IS_ENOUGH_LENGTH( org_data, org_len, data, SSL_MAX_MASTER_KEY_LENGTH ) )
	{
		return NM_ERROR( DSSL_E_SSL_INVALID_RECORD_LENGTH );
	}

	pk = ssls_get_session_private_key( sess );

	/* if SSL server key is not found, try to find a matching one from the key pool */
	if(pk == NULL) 
	{
		_ASSERT( sess->last_packet);
		pk = ssls_try_ssl_keys( sess, data, len );

		/* if a matching key found, register it with the server IP:port */
		if(pk != NULL)
		{
			if( ssls_register_ssl_key( sess, pk ) == DSSL_RC_OK)
			{
				/* ssls_register_ssl_key clones the key, query the key back */
				pk = ssls_get_session_private_key( sess );
			}
			else
			{
				pk = NULL;
			}
		}
	}

	if(!pk) 
	{
		ssls_register_missing_key_server( sess );
		return NM_ERROR( DSSL_E_SSL_SERVER_KEY_UNKNOWN );
	}

	if(pk->type != EVP_PKEY_RSA) return NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT_NON_RSA );

	pms_len = RSA_private_decrypt( len, data, sess->PMS, pk->pkey.rsa, RSA_PKCS1_PADDING );

	if( pms_len != SSL_MAX_MASTER_KEY_LENGTH )
	{
		return NM_ERROR( DSSL_E_SSL_CORRUPTED_PMS );
	}

	if( MAKE_UINT16( sess->PMS[0], sess->PMS[1] ) != sess->client_version )
	{
		return NM_ERROR( DSSL_E_SSL_PMS_VERSION_ROLLBACK );
	}

	rc = ssls_decode_master_secret( sess );
	OPENSSL_cleanse(sess->PMS, sizeof(sess->PMS) );

	if( rc != DSSL_RC_OK ) return rc;

	rc = ssls_generate_keys( sess );
	if( rc == DSSL_RC_OK )
	{
		ssls_store_session( sess );
	}
	return rc;
}