Example #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);
	}
Example #2
0
HANDSHAKE_RESULT do_handshake(SSL_CTX *server_ctx, SSL_CTX *client_ctx,
                              const SSL_TEST_CTX *test_ctx)
{
    SSL *server, *client;
    BIO *client_to_server, *server_to_client;
    HANDSHAKE_EX_DATA server_ex_data, client_ex_data;
    HANDSHAKE_RESULT ret;
    int client_turn = 1;
    peer_status_t client_status = PEER_RETRY, server_status = PEER_RETRY;
    handshake_status_t status = HANDSHAKE_RETRY;
    unsigned char* tick = NULL;
    size_t len = 0;
    SSL_SESSION* sess = NULL;

    configure_handshake_ctx(server_ctx, client_ctx, test_ctx);

    server = SSL_new(server_ctx);
    client = SSL_new(client_ctx);
    OPENSSL_assert(server != NULL && client != NULL);

    configure_handshake_ssl(server, client, test_ctx);

    memset(&server_ex_data, 0, sizeof(server_ex_data));
    memset(&client_ex_data, 0, sizeof(client_ex_data));
    memset(&ret, 0, sizeof(ret));
    ret.result = SSL_TEST_INTERNAL_ERROR;

    client_to_server = BIO_new(BIO_s_mem());
    server_to_client = BIO_new(BIO_s_mem());

    OPENSSL_assert(client_to_server != NULL && server_to_client != NULL);

    /* Non-blocking bio. */
    BIO_set_nbio(client_to_server, 1);
    BIO_set_nbio(server_to_client, 1);

    SSL_set_connect_state(client);
    SSL_set_accept_state(server);

    /* The bios are now owned by the SSL object. */
    SSL_set_bio(client, server_to_client, client_to_server);
    OPENSSL_assert(BIO_up_ref(server_to_client) > 0);
    OPENSSL_assert(BIO_up_ref(client_to_server) > 0);
    SSL_set_bio(server, client_to_server, server_to_client);

    ex_data_idx = SSL_get_ex_new_index(0, "ex data", NULL, NULL, NULL);
    OPENSSL_assert(ex_data_idx >= 0);

    OPENSSL_assert(SSL_set_ex_data(server, ex_data_idx,
                                   &server_ex_data) == 1);
    OPENSSL_assert(SSL_set_ex_data(client, ex_data_idx,
                                   &client_ex_data) == 1);

    SSL_set_info_callback(server, &info_callback);
    SSL_set_info_callback(client, &info_callback);

    /*
     * Half-duplex handshake loop.
     * Client and server speak to each other synchronously in the same process.
     * We use non-blocking BIOs, so whenever one peer blocks for read, it
     * returns PEER_RETRY to indicate that it's the other peer's turn to write.
     * The handshake succeeds once both peers have succeeded. If one peer
     * errors out, we also let the other peer retry (and presumably fail).
     */
    for(;;) {
        if (client_turn) {
            client_status = do_handshake_step(client);
            status = handshake_status(client_status, server_status,
                                      1 /* client went last */);
        } else {
            server_status = do_handshake_step(server);
            status = handshake_status(server_status, client_status,
                                      0 /* server went last */);
        }

        switch (status) {
        case HANDSHAKE_SUCCESS:
            ret.result = SSL_TEST_SUCCESS;
            goto err;
        case CLIENT_ERROR:
            ret.result = SSL_TEST_CLIENT_FAIL;
            goto err;
        case SERVER_ERROR:
            ret.result = SSL_TEST_SERVER_FAIL;
            goto err;
        case INTERNAL_ERROR:
            ret.result = SSL_TEST_INTERNAL_ERROR;
            goto err;
        case HANDSHAKE_RETRY:
            /* Continue. */
            client_turn ^= 1;
            break;
        }
    }
 err:
    ret.server_alert_sent = server_ex_data.alert_sent;
    ret.server_alert_received = client_ex_data.alert_received;
    ret.client_alert_sent = client_ex_data.alert_sent;
    ret.client_alert_received = server_ex_data.alert_received;
    ret.server_protocol = SSL_version(server);
    ret.client_protocol = SSL_version(client);
    ret.servername = ((SSL_get_SSL_CTX(server) == server_ctx)
                      ? SSL_TEST_SERVERNAME_SERVER1
                      : SSL_TEST_SERVERNAME_SERVER2);
    if ((sess = SSL_get0_session(client)) != NULL)
        SSL_SESSION_get0_ticket(sess, &tick, &len);
    if (tick == NULL || len == 0)
        ret.session_ticket = SSL_TEST_SESSION_TICKET_NO;
    else
        ret.session_ticket = SSL_TEST_SESSION_TICKET_YES;
    ret.session_ticket_do_not_call = server_ex_data.session_ticket_do_not_call;

    SSL_free(server);
    SSL_free(client);
    return ret;
}
Example #3
0
static long
dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
{
	long ret = 1;
	int *ip;
	struct sockaddr *to = NULL;
	bio_dgram_data *data = NULL;
#if defined(OPENSSL_SYS_LINUX) && (defined(IP_MTU_DISCOVER) || defined(IP_MTU))
	int sockopt_val = 0;
	socklen_t sockopt_len;	/* assume that system supporting IP_MTU is
				 * modern enough to define socklen_t */
	socklen_t addr_len;
	union	{
		struct sockaddr	sa;
		struct sockaddr_in s4;
		struct sockaddr_in6 s6;
	} addr;
#endif

	data = (bio_dgram_data *)b->ptr;

	switch (cmd) {
	case BIO_CTRL_RESET:
		num = 0;
	case BIO_C_FILE_SEEK:
		ret = 0;
		break;
	case BIO_C_FILE_TELL:
	case BIO_CTRL_INFO:
		ret = 0;
		break;
	case BIO_C_SET_FD:
		dgram_clear(b);
		b->num= *((int *)ptr);
		b->shutdown = (int)num;
		b->init = 1;
		break;
	case BIO_C_GET_FD:
		if (b->init) {
			ip = (int *)ptr;
			if (ip != NULL)
				*ip = b->num;
			ret = b->num;
		} else
			ret = -1;
		break;
	case BIO_CTRL_GET_CLOSE:
		ret = b->shutdown;
		break;
	case BIO_CTRL_SET_CLOSE:
		b->shutdown = (int)num;
		break;
	case BIO_CTRL_PENDING:
	case BIO_CTRL_WPENDING:
		ret = 0;
		break;
	case BIO_CTRL_DUP:
	case BIO_CTRL_FLUSH:
		ret = 1;
		break;
	case BIO_CTRL_DGRAM_CONNECT:
		to = (struct sockaddr *)ptr;
		switch (to->sa_family) {
		case AF_INET:
			memcpy(&data->peer, to, sizeof(data->peer.sa_in));
			break;
		case AF_INET6:
			memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
			break;
		default:
			memcpy(&data->peer, to, sizeof(data->peer.sa));
			break;
		}
		break;
		/* (Linux)kernel sets DF bit on outgoing IP packets */
	case BIO_CTRL_DGRAM_MTU_DISCOVER:
#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
		addr_len = (socklen_t)sizeof(addr);
		memset((void *)&addr, 0, sizeof(addr));
		if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
			ret = 0;
			break;
		}
		switch (addr.sa.sa_family) {
		case AF_INET:
			sockopt_val = IP_PMTUDISC_DO;
			if ((ret = setsockopt(b->num, IPPROTO_IP,
			    IP_MTU_DISCOVER, &sockopt_val,
			    sizeof(sockopt_val))) < 0)
				perror("setsockopt");
			break;
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
		case AF_INET6:
			sockopt_val = IPV6_PMTUDISC_DO;
			if ((ret = setsockopt(b->num, IPPROTO_IPV6,
			    IPV6_MTU_DISCOVER, &sockopt_val,
			    sizeof(sockopt_val))) < 0)
				perror("setsockopt");
			break;
#endif
		default:
			ret = -1;
			break;
		}
		ret = -1;
#else
		break;
#endif
	case BIO_CTRL_DGRAM_QUERY_MTU:
#if defined(OPENSSL_SYS_LINUX) && defined(IP_MTU)
		addr_len = (socklen_t)sizeof(addr);
		memset((void *)&addr, 0, sizeof(addr));
		if (getsockname(b->num, &addr.sa, &addr_len) < 0) {
			ret = 0;
			break;
		}
		sockopt_len = sizeof(sockopt_val);
		switch (addr.sa.sa_family) {
		case AF_INET:
			if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU,
			    (void *)&sockopt_val, &sockopt_len)) < 0 ||
			    sockopt_val < 0) {
				ret = 0;
			} else {
				/* we assume that the transport protocol is UDP and no
				 * IP options are used.
				 */
				data->mtu = sockopt_val - 8 - 20;
				ret = data->mtu;
			}
			break;
#if defined(IPV6_MTU)
		case AF_INET6:
			if ((ret = getsockopt(b->num, IPPROTO_IPV6, IPV6_MTU,
			    (void *)&sockopt_val, &sockopt_len)) < 0 ||
			    sockopt_val < 0) {
				ret = 0;
			} else {
				/* we assume that the transport protocol is UDP and no
				 * IPV6 options are used.
				 */
				data->mtu = sockopt_val - 8 - 40;
				ret = data->mtu;
			}
			break;
#endif
default:
			ret = 0;
			break;
		}
#else
		ret = 0;
#endif
		break;
	case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
		switch (data->peer.sa.sa_family) {
		case AF_INET:
			ret = 576 - 20 - 8;
			break;
		case AF_INET6:
#ifdef IN6_IS_ADDR_V4MAPPED
			if (IN6_IS_ADDR_V4MAPPED(&data->peer.sa_in6.sin6_addr))
				ret = 576 - 20 - 8;
			else
#endif
				ret = 1280 - 40 - 8;
			break;
		default:
			ret = 576 - 20 - 8;
			break;
		}
		break;
	case BIO_CTRL_DGRAM_GET_MTU:
		return data->mtu;
		break;
	case BIO_CTRL_DGRAM_SET_MTU:
		data->mtu = num;
		ret = num;
		break;
	case BIO_CTRL_DGRAM_SET_CONNECTED:
		to = (struct sockaddr *)ptr;

		if (to != NULL) {
			data->connected = 1;
			switch (to->sa_family) {
			case AF_INET:
				memcpy(&data->peer, to, sizeof(data->peer.sa_in));
				break;
			case AF_INET6:
				memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
				break;
			default:
				memcpy(&data->peer, to, sizeof(data->peer.sa));
				break;
			}
		} else {
			data->connected = 0;
			memset(&(data->peer), 0x00, sizeof(data->peer));
		}
		break;
	case BIO_CTRL_DGRAM_GET_PEER:
		switch (data->peer.sa.sa_family) {
		case AF_INET:
			ret = sizeof(data->peer.sa_in);
			break;
		case AF_INET6:
			ret = sizeof(data->peer.sa_in6);
			break;
		default:
			ret = sizeof(data->peer.sa);
			break;
		}
		if (num == 0 || num > ret)
			num = ret;
		memcpy(ptr, &data->peer, (ret = num));
		break;
	case BIO_CTRL_DGRAM_SET_PEER:
		to = (struct sockaddr *) ptr;
		switch (to->sa_family) {
		case AF_INET:
			memcpy(&data->peer, to, sizeof(data->peer.sa_in));
			break;
		case AF_INET6:
			memcpy(&data->peer, to, sizeof(data->peer.sa_in6));
			break;
		default:
			memcpy(&data->peer, to, sizeof(data->peer.sa));
			break;
		}
		break;
	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
		memcpy(&(data->next_timeout), ptr, sizeof(struct timeval));
		break;
#if defined(SO_RCVTIMEO)
	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
		if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
		    sizeof(struct timeval)) < 0) {
			perror("setsockopt");
			ret = -1;
		}
		break;
	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
		{
			union {
				size_t s;
				int i;
			} sz = {0};
			sz.i = sizeof(struct timeval);
			if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
			    ptr, (void *)&sz) < 0) {
				perror("getsockopt");
				ret = -1;
			} else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0) {
				OPENSSL_assert(sz.s <= sizeof(struct timeval));
				ret = (int)sz.s;
			} else
				ret = sz.i;
		}
		break;
#endif
#if defined(SO_SNDTIMEO)
	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
		if (setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
		    sizeof(struct timeval)) < 0) {
			perror("setsockopt");
			ret = -1;
		}
		break;
	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
		{
			union {
				size_t s;
				int i;
			} sz = {0};
			sz.i = sizeof(struct timeval);
			if (getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO,
			    ptr, (void *)&sz) < 0) {
				perror("getsockopt");
				ret = -1;
			} else if (sizeof(sz.s) != sizeof(sz.i) && sz.i == 0) {
				OPENSSL_assert(sz.s <= sizeof(struct timeval));
				ret = (int)sz.s;
			} else
				ret = sz.i;
		}
		break;
#endif
	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
		/* fall-through */
	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
		if (data->_errno == EAGAIN) {
			ret = 1;
			data->_errno = 0;
		} else
			ret = 0;
		break;
#ifdef EMSGSIZE
	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
		if (data->_errno == EMSGSIZE) {
			ret = 1;
			data->_errno = 0;
		} else
			ret = 0;
		break;
#endif
	default:
		ret = 0;
		break;
	}
	return (ret);
}
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
	     const unsigned char *key, const unsigned char *iv, int enc)
	{
	if (enc == -1)
		enc = ctx->encrypt;
	else
		{
		if (enc)
			enc = 1;
		ctx->encrypt = enc;
		}
#ifdef OPENSSL_NO_FIPS
	if(FIPS_selftest_failed())
		{
		FIPSerr(FIPS_F_EVP_CIPHERINIT_EX,FIPS_R_FIPS_SELFTEST_FAILED);
		ctx->cipher = &bad_cipher;
		return 0;
		}
#endif
#ifndef OPENSSL_NO_ENGINE
	/* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
	 * so this context may already have an ENGINE! Try to avoid releasing
	 * the previous handle, re-querying for an ENGINE, and having a
	 * reinitialisation, when it may all be unecessary. */
	if (ctx->engine && ctx->cipher && (!cipher ||
			(cipher && (cipher->nid == ctx->cipher->nid))))
		goto skip_to_init;
#endif
	if (cipher)
		{
		/* Ensure a context left lying around from last time is cleared
		 * (the previous check attempted to avoid this if the same
		 * ENGINE and EVP_CIPHER could be used). */
		EVP_CIPHER_CTX_cleanup(ctx);

		/* Restore encrypt field: it is zeroed by cleanup */
		ctx->encrypt = enc;
#ifndef OPENSSL_NO_ENGINE
		if (!do_evp_enc_engine(ctx, &cipher, impl))
			return 0;
#endif

		ctx->cipher=cipher;
		if (ctx->cipher->ctx_size)
			{
			ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size);
			if (!ctx->cipher_data)
				{
				EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE);
				return 0;
				}
			}
		else
			{
			ctx->cipher_data = NULL;
			}
		ctx->key_len = cipher->key_len;
		ctx->flags = 0;
		if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT)
			{
			if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL))
				{
				EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
				return 0;
				}
			}
		}
	else if(!ctx->cipher)
		{
		EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
		return 0;
		}
#ifndef OPENSSL_NO_ENGINE
skip_to_init:
#endif
	/* we assume block size is a power of 2 in *cryptUpdate */
	OPENSSL_assert(ctx->cipher->block_size == 1
	    || ctx->cipher->block_size == 8
	    || ctx->cipher->block_size == 16);

	if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
		switch(EVP_CIPHER_CTX_mode(ctx)) {

			case EVP_CIPH_STREAM_CIPHER:
			case EVP_CIPH_ECB_MODE:
			break;

			case EVP_CIPH_CFB_MODE:
			case EVP_CIPH_OFB_MODE:

			ctx->num = 0;

			case EVP_CIPH_CBC_MODE:

			OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <=
					(int)sizeof(ctx->iv));
			if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
			memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
			break;

			default:
			return 0;
			break;
		}
	}

#ifdef OPENSSL_FIPS
	/* After 'key' is set no further parameters changes are permissible.
	 * So only check for non FIPS enabling at this point.
	 */
	if (key && FIPS_mode())
		{
		if (!(ctx->cipher->flags & EVP_CIPH_FLAG_FIPS)
			& !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW))
			{
			EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_DISABLED_FOR_FIPS);
#if 0
			ERR_add_error_data(2, "cipher=",
						EVP_CIPHER_name(ctx->cipher));
#endif
			ctx->cipher = &bad_cipher;
			return 0;
			}
		}
#endif

	if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
		if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
	}
	ctx->buf_len=0;
	ctx->final_used=0;
	ctx->block_mask=ctx->cipher->block_size-1;
	return 1;
	}
Example #5
0
int ssl3_get_finished(SSL *s, int a, int b)
	{
	int al,i,ok;
	long n;
	unsigned char *p;

#ifdef OPENSSL_NO_NEXTPROTONEG
	/* the mac has already been generated when we received the change
	 * cipher spec message and is in s->s3->tmp.peer_finish_md. */
#endif

	n=s->method->ssl_get_message(s,
		a,
		b,
		SSL3_MT_FINISHED,
		64, /* should actually be 36+4 :-) */
		&ok);

	if (!ok) return((int)n);

	/* If this occurs, we have missed a message */
	if (!s->s3->change_cipher_spec)
		{
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_GOT_A_FIN_BEFORE_A_CCS);
		goto f_err;
		}
	s->s3->change_cipher_spec=0;

	p = (unsigned char *)s->init_msg;
	i = s->s3->tmp.peer_finish_md_len;

	if (i != n)
		{
		al=SSL_AD_DECODE_ERROR;
		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_BAD_DIGEST_LENGTH);
		goto f_err;
		}

	if (timingsafe_bcmp(p, s->s3->tmp.peer_finish_md, i) != 0)
		{
		al=SSL_AD_DECRYPT_ERROR;
		SSLerr(SSL_F_SSL3_GET_FINISHED,SSL_R_DIGEST_CHECK_FAILED);
		goto f_err;
		}

        /* Copy the finished so we can use it for
           renegotiation checks */
        if(s->type == SSL_ST_ACCEPT)
                {
                OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
                memcpy(s->s3->previous_client_finished, 
                    s->s3->tmp.peer_finish_md, i);
                s->s3->previous_client_finished_len=i;
                }
        else
                {
                OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
                memcpy(s->s3->previous_server_finished, 
                    s->s3->tmp.peer_finish_md, i);
                s->s3->previous_server_finished_len=i;
                }

	return(1);
f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
	return(0);
	}
Example #6
0
static int asn1_bio_write(BIO *b, const char *in, int inl)
{
    BIO_ASN1_BUF_CTX *ctx;
    int wrmax, wrlen, ret;
    unsigned char *p;
    if (!in || (inl < 0) || (b->next_bio == NULL))
        return 0;
    ctx = (BIO_ASN1_BUF_CTX *)b->ptr;
    if (ctx == NULL)
        return 0;

    wrlen = 0;
    ret = -1;

    for (;;) {
        switch (ctx->state) {

            /* Setup prefix data, call it */
        case ASN1_STATE_START:
            if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
                                   ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
                return 0;
            break;

            /* Copy any pre data first */
        case ASN1_STATE_PRE_COPY:

            ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
                                    ASN1_STATE_HEADER);

            if (ret <= 0)
                goto done;

            break;

        case ASN1_STATE_HEADER:
            ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
            OPENSSL_assert(ctx->buflen <= ctx->bufsize);
            p = ctx->buf;
            ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class);
            ctx->copylen = inl;
            ctx->state = ASN1_STATE_HEADER_COPY;

            break;

        case ASN1_STATE_HEADER_COPY:
            ret = BIO_write(b->next_bio, ctx->buf + ctx->bufpos, ctx->buflen);
            if (ret <= 0)
                goto done;

            ctx->buflen -= ret;
            if (ctx->buflen)
                ctx->bufpos += ret;
            else {
                ctx->bufpos = 0;
                ctx->state = ASN1_STATE_DATA_COPY;
            }

            break;

        case ASN1_STATE_DATA_COPY:

            if (inl > ctx->copylen)
                wrmax = ctx->copylen;
            else
                wrmax = inl;
            ret = BIO_write(b->next_bio, in, wrmax);
            if (ret <= 0)
                break;
            wrlen += ret;
            ctx->copylen -= ret;
            in += ret;
            inl -= ret;

            if (ctx->copylen == 0)
                ctx->state = ASN1_STATE_HEADER;

            if (inl == 0)
                goto done;

            break;

        default:
            BIO_clear_retry_flags(b);
            return 0;

        }

    }

 done:
    BIO_clear_retry_flags(b);
    BIO_copy_next_retry(b);

    return (wrlen > 0) ? wrlen : ret;

}
Example #7
0
void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
					 const unsigned long length, const AES_KEY *key,
					 unsigned char *ivec, const int enc)
	{
	unsigned long n;
	unsigned long len;

	OPENSSL_assert(in && out && key && ivec);
	OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
	OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);

	len = length / AES_BLOCK_SIZE;

	if (AES_ENCRYPT == enc)
		{
		if (in != out &&
		    (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0))
			{
			aes_block_t *ivp = (aes_block_t *)ivec;
			aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);

			while (len)
				{
				aes_block_t *inp = (aes_block_t *)in;
				aes_block_t *outp = (aes_block_t *)out;

				for(n=0 ; n < N_WORDS; ++n)
					outp->data[n] = inp->data[n] ^ ivp->data[n];
				AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key);
				for(n=0 ; n < N_WORDS; ++n)
					outp->data[n] ^= iv2p->data[n];
				ivp = outp;
				iv2p = inp;
				--len;
				in += AES_BLOCK_SIZE;
				out += AES_BLOCK_SIZE;
				}
			memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
			memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
			}
		else
			{
			aes_block_t tmp, tmp2;
			aes_block_t iv;
			aes_block_t iv2;

			load_block(iv, ivec);
			load_block(iv2, ivec + AES_BLOCK_SIZE);

			while (len)
				{
				load_block(tmp, in);
				for(n=0 ; n < N_WORDS; ++n)
					tmp2.data[n] = tmp.data[n] ^ iv.data[n];
				AES_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key);
				for(n=0 ; n < N_WORDS; ++n)
					tmp2.data[n] ^= iv2.data[n];
				store_block(out, tmp2);
				iv = tmp2;
				iv2 = tmp;
				--len;
				in += AES_BLOCK_SIZE;
				out += AES_BLOCK_SIZE;
				}
			memcpy(ivec, iv.data, AES_BLOCK_SIZE);
			memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
			}
		}
	else
		{
		if (in != out &&
		    (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_t)ivec)%sizeof(long)==0))
			{
			aes_block_t *ivp = (aes_block_t *)ivec;
			aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE);

			while (len)
				{
				aes_block_t tmp;
				aes_block_t *inp = (aes_block_t *)in;
				aes_block_t *outp = (aes_block_t *)out;

				for(n=0 ; n < N_WORDS; ++n)
					tmp.data[n] = inp->data[n] ^ iv2p->data[n];
				AES_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key);
				for(n=0 ; n < N_WORDS; ++n)
					outp->data[n] ^= ivp->data[n];
				ivp = inp;
				iv2p = outp;
				--len;
				in += AES_BLOCK_SIZE;
				out += AES_BLOCK_SIZE;
				}
			memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
			memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
			}
		else
			{
			aes_block_t tmp, tmp2;
			aes_block_t iv;
			aes_block_t iv2;

			load_block(iv, ivec);
			load_block(iv2, ivec + AES_BLOCK_SIZE);

			while (len)
				{
				load_block(tmp, in);
				tmp2 = tmp;
				for(n=0 ; n < N_WORDS; ++n)
					tmp.data[n] ^= iv2.data[n];
				AES_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key);
				for(n=0 ; n < N_WORDS; ++n)
					tmp.data[n] ^= iv.data[n];
				store_block(out, tmp);
				iv = tmp2;
				iv2 = tmp;
				--len;
				in += AES_BLOCK_SIZE;
				out += AES_BLOCK_SIZE;
				}
			memcpy(ivec, iv.data, AES_BLOCK_SIZE);
			memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
			}
		}
	}
/* 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;
	}
int tls1_enc(SSL *s, int send)
	{
	SSL3_RECORD *rec;
	EVP_CIPHER_CTX *ds;
	unsigned long l;
	int bs,i,ii,j,k,pad=0;
	const EVP_CIPHER *enc;

	if (send)
		{
		if (EVP_MD_CTX_md(s->write_hash))
			{
			int n=EVP_MD_CTX_size(s->write_hash);
			OPENSSL_assert(n >= 0);
			}
		ds=s->enc_write_ctx;
		rec= &(s->s3->wrec);
		if (s->enc_write_ctx == NULL)
			enc=NULL;
		else
			{
			int ivlen;
			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
			/* For TLSv1.1 and later explicit IV */
			if (s->version >= TLS1_1_VERSION
				&& EVP_CIPHER_mode(enc) == EVP_CIPH_CBC_MODE)
				ivlen = EVP_CIPHER_iv_length(enc);
			else
				ivlen = 0;
			if (ivlen > 1)
				{
				if ( rec->data != rec->input)
					/* we can't write into the input stream:
					 * Can this ever happen?? (steve)
					 */
					fprintf(stderr,
						"%s:%d: rec->data != rec->input\n",
						__FILE__, __LINE__);
				else if (RAND_bytes(rec->input, ivlen) <= 0)
					return -1;
				}
			}
		}
	else
		{
		if (EVP_MD_CTX_md(s->read_hash))
			{
			int n=EVP_MD_CTX_size(s->read_hash);
			OPENSSL_assert(n >= 0);
			}
		ds=s->enc_read_ctx;
		rec= &(s->s3->rrec);
		if (s->enc_read_ctx == NULL)
			enc=NULL;
		else
			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
		}

#ifdef KSSL_DEBUG
	printf("tls1_enc(%d)\n", send);
#endif    /* KSSL_DEBUG */

	if ((s->session == NULL) || (ds == NULL) ||
		(enc == NULL))
		{
		memmove(rec->data,rec->input,rec->length);
		rec->input=rec->data;
		}
	else
		{
		l=rec->length;
		bs=EVP_CIPHER_block_size(ds->cipher);

		if (EVP_CIPHER_flags(ds->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
			{
			unsigned char buf[13],*seq;

			seq = send?s->s3->write_sequence:s->s3->read_sequence;

			if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER)
				{
				unsigned char dtlsseq[9],*p=dtlsseq;

				s2n(send?s->d1->w_epoch:s->d1->r_epoch,p);
				memcpy(p,&seq[2],6);
				memcpy(buf,dtlsseq,8);
				}
			else
				{
				memcpy(buf,seq,8);
				for (i=7; i>=0; i--)	/* increment */
					{
					++seq[i];
					if (seq[i] != 0) break; 
					}
				}

			buf[8]=rec->type;
			buf[9]=(unsigned char)(s->version>>8);
			buf[10]=(unsigned char)(s->version);
			buf[11]=rec->length>>8;
			buf[12]=rec->length&0xff;
			pad=EVP_CIPHER_CTX_ctrl(ds,EVP_CTRL_AEAD_TLS1_AAD,13,buf);
			if (send)
				{
				l+=pad;
				rec->length+=pad;
				}
			}
		else if ((bs != 1) && send)
Example #10
0
/*-
 * BIO_lookup - look up the node and service you want to connect to.
 * @node: the node you want to connect to.
 * @service: the service you want to connect to.
 * @lookup_type: declare intent with the result, client or server.
 * @family: the address family you want to use.  Use AF_UNSPEC for any, or
 *  AF_INET, AF_INET6 or AF_UNIX.
 * @socktype: The socket type you want to use.  Can be SOCK_STREAM, SOCK_DGRAM
 *  or 0 for all.
 * @res: Storage place for the resulting list of returned addresses
 *
 * This will do a lookup of the node and service that you want to connect to.
 * It returns a linked list of different addresses you can try to connect to.
 *
 * When no longer needed you should call BIO_ADDRINFO_free() to free the result.
 *
 * The return value is 1 on success or 0 in case of error.
 */
int BIO_lookup(const char *host, const char *service,
               enum BIO_lookup_type lookup_type,
               int family, int socktype, BIO_ADDRINFO **res)
{
    int ret = 0;                 /* Assume failure */

    switch(family) {
    case AF_INET:
#ifdef AF_INET6
    case AF_INET6:
#endif
#ifdef AF_UNIX
    case AF_UNIX:
#endif
#ifdef AF_UNSPEC
    case AF_UNSPEC:
#endif
        break;
    default:
        BIOerr(BIO_F_BIO_LOOKUP, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
        return 0;
    }

#ifdef AF_UNIX
    if (family == AF_UNIX) {
        if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
            return 1;
        else
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
        return 0;
    }
#endif

    if (BIO_sock_init() != 1)
        return 0;

    if (1) {
        int gai_ret = 0;
#ifdef AI_PASSIVE
        struct addrinfo hints;

        hints.ai_flags = 0;
# ifdef AI_ADDRCONFIG
        hints.ai_flags = AI_ADDRCONFIG;
# endif
        hints.ai_family = family;
        hints.ai_socktype = socktype;
        hints.ai_protocol = 0;
        hints.ai_addrlen = 0;
        hints.ai_addr = NULL;
        hints.ai_canonname = NULL;
        hints.ai_next = NULL;

        if (lookup_type == BIO_LOOKUP_SERVER)
            hints.ai_flags |= AI_PASSIVE;

        /* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
         * macro magic in bio_lcl.h
         */
        switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
# ifdef EAI_SYSTEM
        case EAI_SYSTEM:
            SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
            break;
# endif
        case 0:
            ret = 1;             /* Success */
            break;
        default:
            BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
            ERR_add_error_data(1, gai_strerror(gai_ret));
            break;
        }
    } else {
#endif
        const struct hostent *he;
        /* Windows doesn't seem to have in_addr_t */
#ifdef OPENSSL_SYS_WINDOWS
        static uint32_t he_fallback_address;
        static const uint32_t *he_fallback_addresses[] =
            { &he_fallback_address, NULL };
#else
        static in_addr_t he_fallback_address;
        static const in_addr_t *he_fallback_addresses[] =
            { &he_fallback_address, NULL };
#endif
        static const struct hostent he_fallback =
            { NULL, NULL, AF_INET, sizeof(he_fallback_address),
              (char **)&he_fallback_addresses };
        struct servent *se;
        /* Apprently, on WIN64, s_proto and s_port have traded places... */
#ifdef _WIN64
        struct servent se_fallback = { NULL, NULL, NULL, 0 };
#else
        struct servent se_fallback = { NULL, NULL, 0, NULL };
#endif
        char *proto = NULL;

        CRYPTO_w_lock(CRYPTO_LOCK_GETHOSTBYNAME);
        CRYPTO_w_lock(CRYPTO_LOCK_GETSERVBYNAME);
        he_fallback_address = INADDR_ANY;
        if (host == NULL) {
            he = &he_fallback;
            switch(lookup_type) {
            case BIO_LOOKUP_CLIENT:
                he_fallback_address = INADDR_LOOPBACK;
                break;
            case BIO_LOOKUP_SERVER:
                he_fallback_address = INADDR_ANY;
                break;
            default:
                OPENSSL_assert(("We forgot to handle a lookup type!" == 0));
                break;
            }
        } else {
            he = gethostbyname(host);

            if (he == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
                BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
                ERR_add_error_data(1, hstrerror(h_errno));
#else
                SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
#endif
                ret = 0;
                goto err;
            }
        }

        if (service == NULL) {
            se_fallback.s_port = 0;
            se_fallback.s_proto = proto;
            se = &se_fallback;
        } else {
            char *endp = NULL;
            long portnum = strtol(service, &endp, 10);

            if (endp != service && *endp == '\0'
                    && portnum > 0 && portnum < 65536) {
                se_fallback.s_port = htons(portnum);
                se_fallback.s_proto = proto;
                se = &se_fallback;
            } else if (endp == service) {
                switch (socktype) {
                case SOCK_STREAM:
                    proto = "tcp";
                    break;
                case SOCK_DGRAM:
                    proto = "udp";
                    break;
                }
                se = getservbyname(service, proto);

                if (se == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
                    BIOerr(BIO_F_BIO_LOOKUP, ERR_R_SYS_LIB);
                    ERR_add_error_data(1, hstrerror(h_errno));
#else
                    SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
#endif
                    goto err;
                }
            } else {
                BIOerr(BIO_F_BIO_LOOKUP, BIO_R_MALFORMED_HOST_OR_SERVICE);
                goto err;
            }
        }

        *res = NULL;

        {
            char **addrlistp;
            size_t addresses;
            BIO_ADDRINFO *tmp_bai = NULL;

            /* The easiest way to create a linked list from an
               array is to start from the back */
            for(addrlistp = he->h_addr_list; *addrlistp != NULL;
                addrlistp++)
                ;

            for(addresses = addrlistp - he->h_addr_list;
                addrlistp--, addresses-- > 0; ) {
                if (!addrinfo_wrap(he->h_addrtype, socktype,
                                   *addrlistp, he->h_length,
                                   se->s_port, &tmp_bai))
                    goto addrinfo_malloc_err;
                tmp_bai->bai_next = *res;
                *res = tmp_bai;
                continue;
             addrinfo_malloc_err:
                BIO_ADDRINFO_free(*res);
                *res = NULL;
                BIOerr(BIO_F_BIO_LOOKUP, ERR_R_MALLOC_FAILURE);
                ret = 0;
                goto err;
            }

            ret = 1;
        }
     err:
        CRYPTO_w_unlock(CRYPTO_LOCK_GETSERVBYNAME);
        CRYPTO_w_unlock(CRYPTO_LOCK_GETHOSTBYNAME);
    }

    return ret;
}
static int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
{
  unsigned char *buffer, result[EVP_MAX_MD_SIZE];
  unsigned int length = 0, resultlength;
  ioa_addr peer;

  unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
  calculate_cookie(ssl, cookie_secret, sizeof(cookie_secret));
  
  /* Read peer information */
  (void) BIO_dgram_get_peer(SSL_get_wbio(ssl), &peer);
  
  /* Create buffer with peer's address and port */
  length = 0;
  switch (peer.ss.ss_family) {
  case AF_INET:
    length += sizeof(struct in_addr);
    break;
  case AF_INET6:
    length += sizeof(struct in6_addr);
    break;
  default:
    OPENSSL_assert(0);
    break;
  }
  length += sizeof(in_port_t);
  buffer = (unsigned char*) OPENSSL_malloc(length);
  
  if (buffer == NULL) {
    TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"out of memory\n");
    return 0;
  }
  
  switch (peer.ss.ss_family) {
  case AF_INET:
    memcpy(buffer,
	   &peer.s4.sin_port,
	   sizeof(in_port_t));
    memcpy(buffer + sizeof(peer.s4.sin_port),
	   &peer.s4.sin_addr,
	   sizeof(struct in_addr));
    break;
  case AF_INET6:
    memcpy(buffer,
	   &peer.s6.sin6_port,
	   sizeof(in_port_t));
    memcpy(buffer + sizeof(in_port_t),
	   &peer.s6.sin6_addr,
	   sizeof(struct in6_addr));
    break;
  default:
    OPENSSL_assert(0);
    break;
  }
  
  /* Calculate HMAC of buffer using the secret */
  HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH,
       (const unsigned char*) buffer, length, result, &resultlength);
  OPENSSL_free(buffer);
  
  memcpy(cookie, result, resultlength);
  *cookie_len = resultlength;
  
  return 1;
}
Example #12
0
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
		  const EVP_MD *md, ENGINE *impl)
	{
	int i,j,reset=0;
	unsigned char pad[HMAC_MAX_MD_CBLOCK];

	if (md != NULL)
		{
		reset=1;
		ctx->md=md;
		}
	else
		md=ctx->md;

	if (key != NULL)
		{
		reset=1;
		j=EVP_MD_block_size(md);
		OPENSSL_assert(j <= (int)sizeof(ctx->key));
		if (j < len)
			{
			if (!EVP_DigestInit_ex(&ctx->md_ctx,md, impl))
				goto err;
			if (!EVP_DigestUpdate(&ctx->md_ctx,key,len))
				goto err;
			if (!EVP_DigestFinal_ex(&(ctx->md_ctx),ctx->key,
				&ctx->key_length))
				goto err;
			}
		else
			{
			OPENSSL_assert(len>=0 && len<=(int)sizeof(ctx->key));
			memcpy(ctx->key,key,len);
			ctx->key_length=len;
			}
		if(ctx->key_length != HMAC_MAX_MD_CBLOCK)
			memset(&ctx->key[ctx->key_length], 0,
				HMAC_MAX_MD_CBLOCK - ctx->key_length);
		}

	if (reset)	
		{
		for (i=0; i<HMAC_MAX_MD_CBLOCK; i++)
			pad[i]=0x36^ctx->key[i];
		if (!EVP_DigestInit_ex(&ctx->i_ctx,md, impl))
			goto err;
		if (!EVP_DigestUpdate(&ctx->i_ctx,pad,EVP_MD_block_size(md)))
			goto err;

		for (i=0; i<HMAC_MAX_MD_CBLOCK; i++)
			pad[i]=0x5c^ctx->key[i];
		if (!EVP_DigestInit_ex(&ctx->o_ctx,md, impl))
			goto err;
		if (!EVP_DigestUpdate(&ctx->o_ctx,pad,EVP_MD_block_size(md)))
			goto err;
		}
	if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->i_ctx))
			goto err;
	return 1;
	err:
	return 0;
	}
Example #13
0
static int
dgram_sctp_read(BIO *b, char *out, int outl)
{
	int ret = 0, n = 0, i, optval;
	socklen_t optlen;
	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
	union sctp_notification *snp;
	struct msghdr msg;
	struct iovec iov;
	struct cmsghdr *cmsg;
	char cmsgbuf[512];

	if (out != NULL) {
		errno = 0;

		do {
			memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
			iov.iov_base = out;
			iov.iov_len = outl;
			msg.msg_name = NULL;
			msg.msg_namelen = 0;
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = cmsgbuf;
			msg.msg_controllen = 512;
			msg.msg_flags = 0;
			n = recvmsg(b->num, &msg, 0);

			if (msg.msg_controllen > 0) {
				for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
					if (cmsg->cmsg_level != IPPROTO_SCTP)
						continue;
#ifdef SCTP_RCVINFO
					if (cmsg->cmsg_type == SCTP_RCVINFO) {
						struct sctp_rcvinfo *rcvinfo;

						rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
						data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
						data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
						data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
						data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
						data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
						data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
						data->rcvinfo.rcv_context = rcvinfo->rcv_context;
					}
#endif
#ifdef SCTP_SNDRCV
					if (cmsg->cmsg_type == SCTP_SNDRCV) {
						struct sctp_sndrcvinfo *sndrcvinfo;

						sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
						data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
						data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
						data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
						data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
						data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
						data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
						data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
					}
#endif
				}
			}

			if (n <= 0) {
				if (n < 0)
					ret = n;
				break;
			}

			if (msg.msg_flags & MSG_NOTIFICATION) {
				snp = (union sctp_notification*) out;
				if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT) {
#ifdef SCTP_EVENT
					struct sctp_event event;
#else
					struct sctp_event_subscribe event;
					socklen_t eventsize;
#endif
					/* If a message has been delayed until the socket
					 * is dry, it can be sent now.
					 */
					if (data->saved_message.length > 0) {
						dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
						data->saved_message.length);
						free(data->saved_message.data);
						data->saved_message.length = 0;
					}

					/* disable sender dry event */
#ifdef SCTP_EVENT
					memset(&event, 0, sizeof(struct sctp_event));
					event.se_assoc_id = 0;
					event.se_type = SCTP_SENDER_DRY_EVENT;
					event.se_on = 0;
					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
					OPENSSL_assert(i >= 0);
#else
					eventsize = sizeof(struct sctp_event_subscribe);
					i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
					OPENSSL_assert(i >= 0);

					event.sctp_sender_dry_event = 0;

					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
					OPENSSL_assert(i >= 0);
#endif
				}

#ifdef SCTP_AUTHENTICATION_EVENT
				if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
					dgram_sctp_handle_auth_free_key_event(b, snp);
#endif

				if (data->handle_notifications != NULL)
					data->handle_notifications(b, data->notification_context, (void*) out);

				memset(out, 0, outl);
			} else
				ret += n;
		}
		while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));

		if (ret > 0 && !(msg.msg_flags & MSG_EOR)) {
			/* Partial message read, this should never happen! */

			/* The buffer was too small, this means the peer sent
			 * a message that was larger than allowed. */
			if (ret == outl)
				return -1;

			/* Test if socket buffer can handle max record
			 * size (2^14 + 2048 + 13)
			 */
			optlen = (socklen_t) sizeof(int);
			ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
			OPENSSL_assert(ret >= 0);
			OPENSSL_assert(optval >= 18445);

			/* Test if SCTP doesn't partially deliver below
			 * max record size (2^14 + 2048 + 13)
			 */
			optlen = (socklen_t) sizeof(int);
			ret = getsockopt(b->num, IPPROTO_SCTP,
			    SCTP_PARTIAL_DELIVERY_POINT, &optval, &optlen);
			OPENSSL_assert(ret >= 0);
			OPENSSL_assert(optval >= 18445);

			/* Partially delivered notification??? Probably a bug.... */
			OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));

			/* Everything seems ok till now, so it's most likely
			 * a message dropped by PR-SCTP.
			 */
			memset(out, 0, outl);
			BIO_set_retry_read(b);
			return -1;
		}

		BIO_clear_retry_flags(b);
		if (ret < 0) {
			if (BIO_dgram_should_retry(ret)) {
				BIO_set_retry_read(b);
				data->_errno = errno;
			}
		}

		/* Test if peer uses SCTP-AUTH before continuing */
		if (!data->peer_auth_tested) {
			int ii, auth_data = 0, auth_forward = 0;
			unsigned char *p;
			struct sctp_authchunks *authchunks;

			optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
			authchunks = malloc(optlen);
			memset(authchunks, 0, sizeof(optlen));
			ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
			OPENSSL_assert(ii >= 0);

			for (p = (unsigned char*) authchunks->gauth_chunks;
			    p < (unsigned char*) authchunks + optlen;
			    p += sizeof(uint8_t)) {
				if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
					auth_data = 1;
				if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
					auth_forward = 1;
			}

			free(authchunks);

			if (!auth_data || !auth_forward) {
				BIOerr(BIO_F_DGRAM_SCTP_READ, BIO_R_CONNECT_ERROR);
				return -1;
			}

			data->peer_auth_tested = 1;
		}
	}
	return (ret);
}
/* dtls1_enc encrypts/decrypts the record in |s->wrec| / |s->rrec|, respectively.
 *
 * Returns:
 *   0: (in non-constant time) if the record is publically invalid (i.e. too
 *       short etc).
 *   1: if the record's padding is valid / the encryption was successful.
 *   -1: if the record's padding/AEAD-authenticator is invalid or, if sending,
 *       an internal error occured. */
int dtls1_enc(SSL *s, int send)
	{
	SSL3_RECORD *rec;
	EVP_CIPHER_CTX *ds;
	unsigned long l;
	int bs,i,j,k,mac_size=0;
	const EVP_CIPHER *enc;

	if (send)
		{
		if (EVP_MD_CTX_md(s->write_hash))
			{
			mac_size=EVP_MD_CTX_size(s->write_hash);
			if (mac_size < 0)
				return -1;
			}
		ds=s->enc_write_ctx;
		rec= &(s->s3->wrec);
		if (s->enc_write_ctx == NULL)
			enc=NULL;
		else
			{
			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
			if ( rec->data != rec->input)
				/* we can't write into the input stream */
				fprintf(stderr, "%s:%d: rec->data != rec->input\n",
					__FILE__, __LINE__);
			else if ( EVP_CIPHER_block_size(ds->cipher) > 1)
				{
				if (RAND_bytes(rec->input, EVP_CIPHER_block_size(ds->cipher)) <= 0)
					return -1;
				}
			}
		}
	else
		{
		if (EVP_MD_CTX_md(s->read_hash))
			{
			mac_size=EVP_MD_CTX_size(s->read_hash);
			OPENSSL_assert(mac_size >= 0);
			}
		ds=s->enc_read_ctx;
		rec= &(s->s3->rrec);
		if (s->enc_read_ctx == NULL)
			enc=NULL;
		else
			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
		}

#ifdef KSSL_DEBUG
	printf("dtls1_enc(%d)\n", send);
#endif    /* KSSL_DEBUG */

	if ((s->session == NULL) || (ds == NULL) ||
		(enc == NULL))
		{
		memmove(rec->data,rec->input,rec->length);
		rec->input=rec->data;
		}
	else
		{
		l=rec->length;
		bs=EVP_CIPHER_block_size(ds->cipher);

		if ((bs != 1) && send)
			{
			i=bs-((int)l%bs);

			/* Add weird padding of upto 256 bytes */

			/* we need to add 'i' padding bytes of value j */
			j=i-1;
			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
				{
				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
					j++;
				}
			for (k=(int)l; k<(int)(l+i); k++)
				rec->input[k]=j;
			l+=i;
			rec->length+=i;
			}

#ifdef KSSL_DEBUG
		{
                unsigned long ui;
		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
                        ds,rec->data,rec->input,l);
		printf("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
                        ds->buf_len, ds->cipher->key_len,
                        DES_KEY_SZ, DES_SCHEDULE_SZ,
                        ds->cipher->iv_len);
		printf("\t\tIV: ");
		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
		printf("\n");
		printf("\trec->input=");
		for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
		printf("\n");
		}
#endif	/* KSSL_DEBUG */

		if (!send)
			{
			if (l == 0 || l%bs != 0)
				return 0;
			}
		
		if(EVP_Cipher(ds,rec->data,rec->input,l) < 1)
			return -1;

#ifdef KSSL_DEBUG
		{
                unsigned long i;
                printf("\trec->data=");
		for (i=0; i<l; i++)
                        printf(" %02x", rec->data[i]);  printf("\n");
                }
#endif	/* KSSL_DEBUG */

		if ((bs != 1) && !send)
			return tls1_cbc_remove_padding(s, rec, bs, mac_size);
		}
	return(1);
	}
Example #15
0
static int b64_write(BIO *b, const char *in, int inl)
{
    int ret = 0;
    int n;
    int i;
    BIO_B64_CTX *ctx;

    ctx = (BIO_B64_CTX *)b->ptr;
    BIO_clear_retry_flags(b);

    if (ctx->encode != B64_ENCODE) {
        ctx->encode = B64_ENCODE;
        ctx->buf_len = 0;
        ctx->buf_off = 0;
        ctx->tmp_len = 0;
        EVP_EncodeInit(ctx->base64);
    }

    OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf));
    OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
    OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
    n = ctx->buf_len - ctx->buf_off;
    while (n > 0) {
        i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
        if (i <= 0) {
            BIO_copy_next_retry(b);
            return (i);
        }
        OPENSSL_assert(i <= n);
        ctx->buf_off += i;
        OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        n -= i;
    }
    /* at this point all pending data has been written */
    ctx->buf_off = 0;
    ctx->buf_len = 0;

    if ((in == NULL) || (inl <= 0))
        return (0);

    while (inl > 0) {
        n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl;

        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
            if (ctx->tmp_len > 0) {
                OPENSSL_assert(ctx->tmp_len <= 3);
                n = 3 - ctx->tmp_len;
                /*
                 * There's a theoretical possibility for this
                 */
                if (n > inl)
                    n = inl;
                memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
                ctx->tmp_len += n;
                ret += n;
                if (ctx->tmp_len < 3)
                    break;
                ctx->buf_len =
                    EVP_EncodeBlock((unsigned char *)ctx->buf,
                                    (unsigned char *)ctx->tmp, ctx->tmp_len);
                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
                OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
                /*
                 * Since we're now done using the temporary buffer, the
                 * length should be 0'd
                 */
                ctx->tmp_len = 0;
            } else {
                if (n < 3) {
                    memcpy(ctx->tmp, in, n);
                    ctx->tmp_len = n;
                    ret += n;
                    break;
                }
                n -= n % 3;
                ctx->buf_len =
                    EVP_EncodeBlock((unsigned char *)ctx->buf,
                                    (const unsigned char *)in, n);
                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
                OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
                ret += n;
            }
        } else {
            EVP_EncodeUpdate(ctx->base64,
                             (unsigned char *)ctx->buf, &ctx->buf_len,
                             (unsigned char *)in, n);
            OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf));
            OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
            ret += n;
        }
        inl -= n;
        in += n;

        ctx->buf_off = 0;
        n = ctx->buf_len;
        while (n > 0) {
            i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
            if (i <= 0) {
                BIO_copy_next_retry(b);
                return ((ret == 0) ? i : ret);
            }
            OPENSSL_assert(i <= n);
            n -= i;
            ctx->buf_off += i;
            OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf));
            OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        }
        ctx->buf_len = 0;
        ctx->buf_off = 0;
    }
    return (ret);
}
Example #16
0
static size_t c2i_ibuf(unsigned char *b, int *pneg,
                       const unsigned char *p, size_t plen)
{
    size_t i;
    int neg, pad;
    /* Zero content length is illegal */
    if (plen == 0) {
        ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT);
        return 0;
    }
    neg = p[0] & 0x80;
    if (pneg)
        *pneg = neg;
    /* Handle common case where length is 1 octet separately */
    if (plen == 1) {
        if (b) {
            if (neg)
                b[0] = (p[0] ^ 0xFF) + 1;
            else
                b[0] = p[0];
        }
        return 1;
    }
    if (p[0] == 0 || p[0] == 0xFF)
        pad = 1;
    else
        pad = 0;
    /* reject illegal padding: first two octets MSB can't match */
    if (pad && (neg == (p[1] & 0x80))) {
        ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING);
        return 0;
    }
    /* If positive just copy across */
    if (neg == 0) {
        if (b)
            memcpy(b, p + pad, plen - pad);
        return plen - pad;
    }

    if (neg && pad) {
        /* check is any following octets are non zero */
        for (i = 1; i < plen; i++) {
            if (p[i] != 0)
                break;
        }
        /* if all bytes are zero handle as special case */
        if (i == plen) {
            if (b) {
                b[0] = 1;
                memset(b + 1, 0, plen - 1);
            }
            return plen;
        }
    }

    plen -= pad;
    /* Must be negative: calculate twos complement */
    if (b) {
        const unsigned char *from = p + plen - 1 + pad;
        unsigned char *to = b + plen;
        i = plen;
        while (*from == 0 && i) {
            *--to = 0;
            i--;
            from--;
        }
        *--to = (*from-- ^ 0xff) + 1;
        OPENSSL_assert(i != 0);
        i--;
        for (; i > 0; i--)
            *--to = *from-- ^ 0xff;
    }
    return plen;
}
Example #17
0
static long b64_ctrl(BIO *b, int cmd, long num, void *ptr)
{
    BIO_B64_CTX *ctx;
    long ret = 1;
    int i;

    ctx = (BIO_B64_CTX *)b->ptr;

    switch (cmd) {
    case BIO_CTRL_RESET:
        ctx->cont = 1;
        ctx->start = 1;
        ctx->encode = B64_NONE;
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    case BIO_CTRL_EOF:         /* More to read */
        if (ctx->cont <= 0)
            ret = 1;
        else
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    case BIO_CTRL_WPENDING:    /* More to write in buffer */
        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        ret = ctx->buf_len - ctx->buf_off;
        if ((ret == 0) && (ctx->encode != B64_NONE)
            && (EVP_ENCODE_CTX_num(ctx->base64) != 0))
            ret = 1;
        else if (ret <= 0)
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    case BIO_CTRL_PENDING:     /* More to read in buffer */
        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        ret = ctx->buf_len - ctx->buf_off;
        if (ret <= 0)
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    case BIO_CTRL_FLUSH:
        /* do a final write */
 again:
        while (ctx->buf_len != ctx->buf_off) {
            i = b64_write(b, NULL, 0);
            if (i < 0)
                return i;
        }
        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
            if (ctx->tmp_len != 0) {
                ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf,
                                               (unsigned char *)ctx->tmp,
                                               ctx->tmp_len);
                ctx->buf_off = 0;
                ctx->tmp_len = 0;
                goto again;
            }
        } else if (ctx->encode != B64_NONE
                   && EVP_ENCODE_CTX_num(ctx->base64) != 0) {
            ctx->buf_off = 0;
            EVP_EncodeFinal(ctx->base64,
                            (unsigned char *)ctx->buf, &(ctx->buf_len));
            /* push out the bytes */
            goto again;
        }
        /* Finally flush the underlying BIO */
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;

    case BIO_C_DO_STATE_MACHINE:
        BIO_clear_retry_flags(b);
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        BIO_copy_next_retry(b);
        break;

    case BIO_CTRL_DUP:
        break;
    case BIO_CTRL_INFO:
    case BIO_CTRL_GET:
    case BIO_CTRL_SET:
    default:
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;
    }
    return (ret);
}
Example #18
0
int main(int argc, char **argv)
{
	int r, i;
	KDF_FUNC kdf = NULL;
	EC_GROUP *ec_group = NULL;
	EC_KEY *ec_key = NULL;
	EVP_PKEY *pkey = NULL;
	EVP_PKEY *pub_key = NULL;
	EVP_PKEY *priv_key = NULL;
	X509_ALGOR *map = NULL;
	CPK_MASTER_SECRET *master = NULL;
	CPK_PUBLIC_PARAMS *params = NULL;
	BIO *bio_out = NULL;
	unsigned char *buf = NULL;
	unsigned char *p;
	const unsigned char *cp;
	int len;

	/* init openssl global functions */
	ERR_load_crypto_strings();
	OpenSSL_add_all_algorithms();

	/* prepare cpk setup parameters */
	ec_key = EC_KEY_new_by_curve_name(OBJ_sn2nid("prime192v1"));
	assert(ec_key != NULL);

	EC_GROUP_set_asn1_flag((EC_GROUP *)EC_KEY_get0_group(ec_key), OPENSSL_EC_NAMED_CURVE);
	r = EC_KEY_generate_key(ec_key);
	assert(r == 1);

	pkey = EVP_PKEY_new();
	assert(pkey != NULL);
	r = EVP_PKEY_set1_EC_KEY(pkey, ec_key);
	assert(r == 1);
	map = CPK_MAP_new_default();
	assert(map != NULL);


	//EVP_PKEY_print_fp(pkey, stdout);

	/* generate master_secret and public_params */
	master = CPK_MASTER_SECRET_create("domainid", pkey, map);
	OPENSSL_assert(master);

	bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
	OPENSSL_assert(bio_out);

	r = CPK_MASTER_SECRET_print(bio_out, master, 0, 0);
	assert(r == 1);

	EVP_PKEY_free(pkey);
	pkey = NULL;
	pkey = CPK_MASTER_SECRET_extract_private_key(master, "id");
	assert(pkey != NULL);
	EVP_PKEY_free(pkey);
	//pkey = CPK_MASTER_SECRET_extract_private_key(master, NULL);
	//assert(pkey == NULL);
	pkey = CPK_MASTER_SECRET_extract_private_key(master, id_long);
	assert(pkey != NULL);
	printf("EVP_PKEY of '%s':\n", id_long);
	EVP_PKEY_print_fp(pkey, stdout);
	printf("\n");
	
	params = CPK_MASTER_SECRET_extract_public_params(master);
	assert(params);
	r = CPK_PUBLIC_PARAMS_print(bio_out, params, 0, 0);
	assert(r == 1);
	printf("\n");

	printf("test CPK_PUBLIC_PARAMS_extract_public_key()\n");
	pub_key = CPK_PUBLIC_PARAMS_extract_public_key(params, id_short);
	assert(pub_key != NULL);
	EVP_PKEY_free(pub_key);

	pub_key = CPK_PUBLIC_PARAMS_extract_public_key(params, id_long);
	assert(pub_key != NULL);
	printf("Public Key of '%s':\n", id_long);
	EVP_PKEY_print_fp(pkey, stdout);
	printf("\n");

	
	r = CPK_MASTER_SECRET_validate_public_params(master, params);
	assert(r == 1);
	if (priv_key) EVP_PKEY_free(priv_key);
	priv_key = CPK_MASTER_SECRET_extract_private_key(master, "identity");
	assert(priv_key);
	r = CPK_PUBLIC_PARAMS_validate_private_key(params, "identity", priv_key);
	assert(r == 1);
	r = CPK_PUBLIC_PARAMS_validate_private_key(params, "id", priv_key);
	assert(r == 0);

	/* der encoding and decoding */
	len = i2d_CPK_MASTER_SECRET(master, NULL);
	assert(len > 0);
	if (buf != NULL) OPENSSL_free(buf);
	buf = OPENSSL_malloc(len);
	assert(buf != NULL);
	p = buf;
	len = i2d_CPK_MASTER_SECRET(master, &p);
	assert(len > 0);
	assert(p - buf == len);

	cp = buf;
	if (master) CPK_MASTER_SECRET_free(master);
	master = NULL;
	master = d2i_CPK_MASTER_SECRET(NULL, &cp, len);
	assert(master != NULL);
	r = CPK_MASTER_SECRET_validate_public_params(master, params);
	assert(r == 1);

	kdf = KDF_get_x9_63(EVP_sha1());
	assert(kdf != NULL);


	if (priv_key != NULL) EVP_PKEY_free(priv_key);
	priv_key = CPK_MASTER_SECRET_extract_private_key(master, "Alice");
	assert(priv_key != NULL);

	if (buf != NULL) OPENSSL_free(buf);
	buf = OPENSSL_malloc(1024);
	assert(buf != NULL);
	r = CPK_PUBLIC_PARAMS_compute_share_key(params, buf, 64, "Bob", priv_key, kdf);
	for (i = 0; i < 64; i++) printf("%02x", buf[i]); printf("\n");

	if (priv_key != NULL)
		EVP_PKEY_free(priv_key);
	priv_key = CPK_MASTER_SECRET_extract_private_key(master, "Bob");
	assert(priv_key != NULL);
	r = CPK_PUBLIC_PARAMS_compute_share_key(params, buf, 64, "Alice", priv_key, kdf);
	for (i = 0; i < 64; i++) printf("%02x", buf[i]); printf("\n");


	printf("ok\n");
	
	return 0;
}
Example #19
0
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
						const unsigned long length, const AES_KEY *key,
						const AES_KEY *key2, const unsigned char *ivec,
						const int enc)
	{
	unsigned long n;
	unsigned long len = length;
	unsigned char tmp[AES_BLOCK_SIZE];
	unsigned char tmp2[AES_BLOCK_SIZE];
	unsigned char tmp3[AES_BLOCK_SIZE];
	unsigned char prev[AES_BLOCK_SIZE];
	const unsigned char *iv;
	const unsigned char *iv2;

	OPENSSL_assert(in && out && key && ivec);
	OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc));
	OPENSSL_assert((length%AES_BLOCK_SIZE) == 0);

	if (AES_ENCRYPT == enc)
		{
		/* XXX: Do a separate case for when in != out (strictly should
		   check for overlap, too) */

		/* First the forward pass */ 
		iv = ivec;
		iv2 = ivec + AES_BLOCK_SIZE;
		while (len >= AES_BLOCK_SIZE)
			{
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				out[n] = in[n] ^ iv[n];
			AES_encrypt(out, out, key);
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				out[n] ^= iv2[n];
			iv = out;
			memcpy(prev, in, AES_BLOCK_SIZE);
			iv2 = prev;
			len -= AES_BLOCK_SIZE;
			in += AES_BLOCK_SIZE;
			out += AES_BLOCK_SIZE;
			}

		/* And now backwards */
		iv = ivec + AES_BLOCK_SIZE*2;
		iv2 = ivec + AES_BLOCK_SIZE*3;
		len = length;
		while(len >= AES_BLOCK_SIZE)
			{
			out -= AES_BLOCK_SIZE;
			/* XXX: reduce copies by alternating between buffers */
			memcpy(tmp, out, AES_BLOCK_SIZE);
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				out[n] ^= iv[n];
			/*			hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */
			AES_encrypt(out, out, key);
			/*			hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */
			/*			hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				out[n] ^= iv2[n];
			/*			hexdump(stdout,"out", out, AES_BLOCK_SIZE); */
			iv = out;
			memcpy(prev, tmp, AES_BLOCK_SIZE);
			iv2 = prev;
			len -= AES_BLOCK_SIZE;
			}
		}
	else
		{
		/* First backwards */
		iv = ivec + AES_BLOCK_SIZE*2;
		iv2 = ivec + AES_BLOCK_SIZE*3;
		in += length;
		out += length;
		while (len >= AES_BLOCK_SIZE)
			{
			in -= AES_BLOCK_SIZE;
			out -= AES_BLOCK_SIZE;
			memcpy(tmp, in, AES_BLOCK_SIZE);
			memcpy(tmp2, in, AES_BLOCK_SIZE);
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				tmp[n] ^= iv2[n];
			AES_decrypt(tmp, out, key);
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				out[n] ^= iv[n];
			memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
			iv = tmp3;
			iv2 = out;
			len -= AES_BLOCK_SIZE;
			}

		/* And now forwards */
		iv = ivec;
		iv2 = ivec + AES_BLOCK_SIZE;
		len = length;
		while (len >= AES_BLOCK_SIZE)
			{
			memcpy(tmp, out, AES_BLOCK_SIZE);
			memcpy(tmp2, out, AES_BLOCK_SIZE);
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				tmp[n] ^= iv2[n];
			AES_decrypt(tmp, out, key);
			for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
				out[n] ^= iv[n];
			memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
			iv = tmp3;
			iv2 = out;
			len -= AES_BLOCK_SIZE;
			in += AES_BLOCK_SIZE;
			out += AES_BLOCK_SIZE;
			}
		}
	}
/*
 * Computes gost2001 signature as DSA_SIG structure 
 *
 *
 */ 
DSA_SIG *gost2001_do_sign(const unsigned char *dgst,int dlen, EC_KEY *eckey)
	{
	DSA_SIG *newsig = NULL;
	BIGNUM *md = hashsum2bn(dgst);
	BIGNUM *order = NULL;
	const EC_GROUP *group;
	const BIGNUM *priv_key;
	BIGNUM *r=NULL,*s=NULL,*X=NULL,*tmp=NULL,*tmp2=NULL, *k=NULL,*e=NULL;
	EC_POINT *C=NULL;
	BN_CTX *ctx = BN_CTX_new();	
	BN_CTX_start(ctx);
	OPENSSL_assert(dlen==32);
	newsig=DSA_SIG_new();
	if (!newsig) 
		{
		GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_NO_MEMORY);
		goto err;
		}	
	group = EC_KEY_get0_group(eckey);
	order=BN_CTX_get(ctx);
	EC_GROUP_get_order(group,order,ctx);
	priv_key = EC_KEY_get0_private_key(eckey);
	e = BN_CTX_get(ctx);
	BN_mod(e,md,order,ctx);
#ifdef DEBUG_SIGN
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"digest as bignum=");
	BN_print_fp(OPENSSL_TYPE__FILE_STDERR,md);
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"\ndigest mod q=");
	BN_print_fp(OPENSSL_TYPE__FILE_STDERR,e);
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"\n");
#endif		
	if (BN_is_zero(e))
		{
		BN_one(e);
		}   
	k =BN_CTX_get(ctx);
	C=EC_POINT_new(group);
	do 
		{
		do 
			{
			if (!BN_rand_range(k,order)) 
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
				DSA_SIG_free(newsig);
				newsig = NULL;
				goto err;
				}	
			if (!EC_POINT_mul(group,C,k,NULL,NULL,ctx))
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
				DSA_SIG_free(newsig);
				newsig = NULL;
				goto err;
				}	
			if (!X) X=BN_CTX_get(ctx);
			if (!EC_POINT_get_affine_coordinates_GFp(group,C,X,NULL,ctx))
				{
				GOSTerr(GOST_F_GOST2001_DO_SIGN,ERR_R_EC_LIB);
				DSA_SIG_free(newsig);
				newsig = NULL;
				goto err;
				}	
			if (!r) r=BN_CTX_get(ctx);
			BN_nnmod(r,X,order,ctx);
			}
		while (BN_is_zero(r));
		/* s =  (r*priv_key+k*e) mod order */
		if (!tmp) tmp = BN_CTX_get(ctx);
		BN_mod_mul(tmp,priv_key,r,order,ctx);
		if (!tmp2) tmp2 = BN_CTX_get(ctx);
		BN_mod_mul(tmp2,k,e,order,ctx);
		if (!s) s=BN_CTX_get(ctx);
		BN_mod_add(s,tmp,tmp2,order,ctx);
		}
	while (BN_is_zero(s));	

	newsig->s=BN_dup(s);
	newsig->r=BN_dup(r);
	err:			
	BN_CTX_end(ctx);
	BN_CTX_free(ctx);
	EC_POINT_free(C);
	BN_free(md);
	return newsig;
	}
Example #21
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;
    int rv = 0;
    EVP_MD_CTX_init(&ctx);

    /* 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);

    if (!EVP_DigestInit_ex(&ctx, md, NULL))
        goto err;
    if (!EVP_DigestUpdate(&ctx, pass, passlen))
        goto err;
    if (!EVP_DigestUpdate(&ctx, salt, saltlen))
        goto err;
    PBEPARAM_free(pbe);
    if (!EVP_DigestFinal_ex(&ctx, md_tmp, NULL))
        goto err;
    mdsize = EVP_MD_size(md);
    if (mdsize < 0)
        return 0;
    for (i = 1; i < iter; i++) {
        if (!EVP_DigestInit_ex(&ctx, md, NULL))
            goto err;
        if (!EVP_DigestUpdate(&ctx, md_tmp, mdsize))
            goto err;
        if (!EVP_DigestFinal_ex(&ctx, md_tmp, NULL))
            goto err;
    }
    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));
    if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de))
        goto err;
    OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
    OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
    OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
    rv = 1;
 err:
    EVP_MD_CTX_cleanup(&ctx);
    return rv;
}
Example #22
0
static int generate_cookie(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len)
{
  unsigned char *buffer, result[EVP_MAX_MD_SIZE];
  unsigned int length = 0, resultlength;
  union {
    struct sockaddr_storage ss;
    struct sockaddr_in6 s6;
    struct sockaddr_in s4;
  } peer;

  /* Initialize a random secret */
  if (!cookie_initialized)
    {
      if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH))
	{
	  printf("error setting random cookie secret\n");
	  return 0;
	}
      cookie_initialized = 1;
    }

  /* Read peer information */
  (void) BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);

  /* Create buffer with peer's address and port */
  length = 0;
  switch (peer.ss.ss_family) {
  case AF_INET:
    length += sizeof(struct in_addr);
    break;
  case AF_INET6:
    length += sizeof(struct in6_addr);
    break;
  default:
    OPENSSL_assert(0);
    break;
  }
  length += sizeof(in_port_t);
  buffer = (unsigned char*) OPENSSL_malloc(length);

  if (buffer == NULL)
    {
      printf("out of memory\n");
      return 0;
    }

  switch (peer.ss.ss_family) {
  case AF_INET:
    memcpy(buffer,
	   &peer.s4.sin_port,
	   sizeof(in_port_t));
    memcpy(buffer + sizeof(peer.s4.sin_port),
	   &peer.s4.sin_addr,
	   sizeof(struct in_addr));
    break;
  case AF_INET6:
    memcpy(buffer,
	   &peer.s6.sin6_port,
	   sizeof(in_port_t));
    memcpy(buffer + sizeof(in_port_t),
	   &peer.s6.sin6_addr,
	   sizeof(struct in6_addr));
    break;
  default:
    OPENSSL_assert(0);
    break;
  }

  /* Calculate HMAC of buffer using the secret */
  HMAC(EVP_sha1(), (const void*) cookie_secret, COOKIE_SECRET_LENGTH,
       (const unsigned char*) buffer, length, result, &resultlength);
  OPENSSL_free(buffer);

  memcpy(cookie, result, resultlength);
  *cookie_len = resultlength;

  return 1;
}
Example #23
0
static void dgram_adjust_rcv_timeout(BIO *b)
	{
#if defined(SO_RCVTIMEO)
	bio_dgram_data *data = (bio_dgram_data *)b->ptr;
	union { size_t s; int i; } sz = {0};

	/* Is a timer active? */
	if (data->next_timeout.tv_sec > 0 || data->next_timeout.tv_usec > 0)
		{
		struct timeval timenow, timeleft;

		/* Read current socket timeout */
#ifdef OPENSSL_SYS_WINDOWS
		int timeout;

		sz.i = sizeof(timeout);
		if (getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
					   (void*)&timeout, &sz.i) < 0)
			{ perror("getsockopt"); }
		else
			{
			data->socket_timeout.tv_sec = timeout / 1000;
			data->socket_timeout.tv_usec = (timeout % 1000) * 1000;
			}
#else
		sz.i = sizeof(data->socket_timeout);
		if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
						&(data->socket_timeout), (void *)&sz) < 0)
			{ perror("getsockopt"); }
		else if (sizeof(sz.s)!=sizeof(sz.i) && sz.i==0)
			OPENSSL_assert(sz.s<=sizeof(data->socket_timeout));
#endif

		/* Get current time */
		get_current_time(&timenow);

		/* Calculate time left until timer expires */
		memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval));
		timeleft.tv_sec -= timenow.tv_sec;
		timeleft.tv_usec -= timenow.tv_usec;
		if (timeleft.tv_usec < 0)
			{
			timeleft.tv_sec--;
			timeleft.tv_usec += 1000000;
			}

		if (timeleft.tv_sec < 0)
			{
			timeleft.tv_sec = 0;
			timeleft.tv_usec = 1;
			}

		/* Adjust socket timeout if next handhake message timer
		 * will expire earlier.
		 */
		if ((data->socket_timeout.tv_sec == 0 && data->socket_timeout.tv_usec == 0) ||
			(data->socket_timeout.tv_sec > timeleft.tv_sec) ||
			(data->socket_timeout.tv_sec == timeleft.tv_sec &&
			 data->socket_timeout.tv_usec >= timeleft.tv_usec))
			{
#ifdef OPENSSL_SYS_WINDOWS
			timeout = timeleft.tv_sec * 1000 + timeleft.tv_usec / 1000;
			if (setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO,
						   (void*)&timeout, sizeof(timeout)) < 0)
				{ perror("setsockopt"); }
#else
			if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, &timeleft,
							sizeof(struct timeval)) < 0)
				{ perror("setsockopt"); }
#endif
			}
		}
#endif
	}
Example #24
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;
    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 || 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 = (unsigned char *)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(enc->iv_len <= (int)sizeof(iv));
        if (RAND_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);
        OPENSSL_free(data);
    }
    return (ret);
}
Example #25
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;
    EVP_CIPHER_CTX *dd;
    const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
    COMP_METHOD *comp;
#endif
    const EVP_MD *m;
    int n, i, j, k, cl;
    int reuse_dd = 0;

    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 = EVP_CIPHER_CTX_new()) == NULL)
            goto err;
        else
            /*
             * make sure it's initialised in case we exit later with an error
             */
            EVP_CIPHER_CTX_reset(s->enc_read_ctx);
        dd = s->enc_read_ctx;

        if (ssl_replace_hash(&s->read_hash, m) == NULL) {
            SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
            goto err2;
        }
#ifndef OPENSSL_NO_COMP
        /* COMPRESS */
        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;
            }
        }
#endif
        RECORD_LAYER_reset_read_sequence(&s->rlayer);
        mac_secret = &(s->s3->read_mac_secret[0]);
    } else {
        if (s->enc_write_ctx != NULL)
            reuse_dd = 1;
        else if ((s->enc_write_ctx = EVP_CIPHER_CTX_new()) == NULL)
            goto err;
        else
            /*
             * make sure it's initialised in case we exit later with an error
             */
            EVP_CIPHER_CTX_reset(s->enc_write_ctx);
        dd = s->enc_write_ctx;
        if (ssl_replace_hash(&s->write_hash, m) == NULL) {
            SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
            goto err2;
        }
#ifndef OPENSSL_NO_COMP
        /* COMPRESS */
        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
        RECORD_LAYER_reset_write_sequence(&s->rlayer);
        mac_secret = &(s->s3->write_mac_secret[0]);
    }

    if (reuse_dd)
        EVP_CIPHER_CTX_reset(dd);

    p = s->s3->tmp.key_block;
    i = EVP_MD_size(m);
    if (i < 0)
        goto err2;
    cl = EVP_CIPHER_key_length(c);
    j = cl;
    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;
    } else {
        n = i;
        ms = &(p[n]);
        n += i + j;
        key = &(p[n]);
        n += j + k;
        iv = &(p[n]);
        n += k;
    }

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

    memcpy(mac_secret, ms, i);

    if (!EVP_CipherInit_ex(dd, c, NULL, key, iv, (which & SSL3_CC_WRITE)))
        goto err2;

#ifdef OPENSSL_SSL_TRACE_CRYPTO
    if (s->msg_callback) {

        int wh = which & SSL3_CC_WRITE ?
            TLS1_RT_CRYPTO_WRITE : TLS1_RT_CRYPTO_READ;
        s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC,
                        mac_secret, EVP_MD_size(m), s, s->msg_callback_arg);
        if (c->key_len)
            s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY,
                            key, c->key_len, s, s->msg_callback_arg);
        if (k) {
            s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_IV,
                            iv, k, s, s->msg_callback_arg);
        }
    }
#endif

    OPENSSL_cleanse(exp_key, sizeof(exp_key));
    OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
    return (1);
 err:
    SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
 err2:
    OPENSSL_cleanse(exp_key, sizeof(exp_key));
    OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
    return (0);
}
Example #26
0
/*
 * Whack an ASIdentifierChoice into canonical form.
 */
static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
{
  ASN1_INTEGER *a_max_plus_one = NULL;
  BIGNUM *bn = NULL;
  int i, ret = 0;

  /*
   * Nothing to do for empty element or inheritance.
   */
  if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
    return 1;

  /*
   * If not a list, or if empty list, it's broken.
   */
  if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
      sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
    X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
	      X509V3_R_EXTENSION_VALUE_ERROR);
    return 0;
  }

  /*
   * We have a non-empty list.  Sort it.
   */
  sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);

  /*
   * Now check for errors and suboptimal encoding, rejecting the
   * former and fixing the latter.
   */
  for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
    ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
    ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
    ASN1_INTEGER *a_min, *a_max, *b_min, *b_max;

    extract_min_max(a, &a_min, &a_max);
    extract_min_max(b, &b_min, &b_max);

    /*
     * Make sure we're properly sorted (paranoia).
     */
    OPENSSL_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0);

    /*
     * Punt inverted ranges.
     */
    if (ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
	ASN1_INTEGER_cmp(b_min, b_max) > 0)
      goto done;

    /*
     * Check for overlaps.
     */
    if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
      X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
		X509V3_R_EXTENSION_VALUE_ERROR);
      goto done;
    }

    /*
     * Calculate a_max + 1 to check for adjacency.
     */
    if ((bn == NULL && (bn = BN_new()) == NULL) ||
	ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
	!BN_add_word(bn, 1) ||
	(a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) {
      X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, ERR_R_MALLOC_FAILURE);
      goto done;
    }
    
    /*
     * If a and b are adjacent, merge them.
     */
    if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
      ASRange *r;
      switch (a->type) {
      case ASIdOrRange_id:
	if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) {
	  X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
		    ERR_R_MALLOC_FAILURE);
	  goto done;
	}
	r->min = a_min;
	r->max = b_max;
	a->type = ASIdOrRange_range;
	a->u.range = r;
	break;
      case ASIdOrRange_range:
	ASN1_INTEGER_free(a->u.range->max);
	a->u.range->max = b_max;
	break;
      }
      switch (b->type) {
      case ASIdOrRange_id:
	b->u.id = NULL;
	break;
      case ASIdOrRange_range:
	b->u.range->max = NULL;
	break;
      }
      ASIdOrRange_free(b);
      (void) sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
      i--;
      continue;
    }
  }

  /*
   * Check for final inverted range.
   */
  i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
  {
    ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
    ASN1_INTEGER *a_min, *a_max;
    if (a != NULL && a->type == ASIdOrRange_range) {
      extract_min_max(a, &a_min, &a_max);
      if (ASN1_INTEGER_cmp(a_min, a_max) > 0)
	goto done;
    }
  }

  OPENSSL_assert(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */

  ret = 1;

 done:
  ASN1_INTEGER_free(a_max_plus_one);
  BN_free(bn);
  return ret;
}
Example #27
0
int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
                   const unsigned char *salt, const unsigned char *data,
                   int datal, int count, unsigned char *key,
                   unsigned char *iv)
{
    EVP_MD_CTX c;
    unsigned char md_buf[EVP_MAX_MD_SIZE];
    int niv, nkey, addmd = 0;
    unsigned int mds = 0, i;

    nkey = type->key_len;
    niv = type->iv_len;
    OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH);
    OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH);

    if (data == NULL)
        return (nkey);

    EVP_MD_CTX_init(&c);
    for (;;) {
        if (!EVP_DigestInit_ex(&c, md, NULL))
            return 0;
        if (addmd++)
            EVP_DigestUpdate(&c, &(md_buf[0]), mds);
        EVP_DigestUpdate(&c, data, datal);
        if (salt != NULL)
            EVP_DigestUpdate(&c, salt, PKCS5_SALT_LEN);
        EVP_DigestFinal_ex(&c, &(md_buf[0]), &mds);

        for (i = 1; i < (unsigned int)count; i++) {
            EVP_DigestInit_ex(&c, md, NULL);
            EVP_DigestUpdate(&c, &(md_buf[0]), mds);
            EVP_DigestFinal_ex(&c, &(md_buf[0]), &mds);
        }
        i = 0;
        if (nkey) {
            for (;;) {
                if (nkey == 0)
                    break;
                if (i == mds)
                    break;
                if (key != NULL)
                    *(key++) = md_buf[i];
                nkey--;
                i++;
            }
        }
        if (niv && (i != mds)) {
            for (;;) {
                if (niv == 0)
                    break;
                if (i == mds)
                    break;
                if (iv != NULL)
                    *(iv++) = md_buf[i];
                niv--;
                i++;
            }
        }
        if ((nkey == 0) && (niv == 0))
            break;
    }
    EVP_MD_CTX_cleanup(&c);
    OPENSSL_cleanse(&(md_buf[0]), EVP_MAX_MD_SIZE);
    return (type->key_len);
}
Example #28
0
static int b64_read(BIO *b, char *out, int outl)
{
    int ret = 0, i, ii, j, k, x, n, num, ret_code = 0;
    BIO_B64_CTX *ctx;
    unsigned char *p, *q;

    if (out == NULL)
        return (0);
    ctx = (BIO_B64_CTX *)b->ptr;

    if ((ctx == NULL) || (b->next_bio == NULL))
        return (0);

    BIO_clear_retry_flags(b);

    if (ctx->encode != B64_DECODE) {
        ctx->encode = B64_DECODE;
        ctx->buf_len = 0;
        ctx->buf_off = 0;
        ctx->tmp_len = 0;
        EVP_DecodeInit(ctx->base64);
    }

    /* First check if there are bytes decoded/encoded */
    if (ctx->buf_len > 0) {
        OPENSSL_assert(ctx->buf_len >= ctx->buf_off);
        i = ctx->buf_len - ctx->buf_off;
        if (i > outl)
            i = outl;
        OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf));
        memcpy(out, &(ctx->buf[ctx->buf_off]), i);
        ret = i;
        out += i;
        outl -= i;
        ctx->buf_off += i;
        if (ctx->buf_len == ctx->buf_off) {
            ctx->buf_len = 0;
            ctx->buf_off = 0;
        }
    }

    /*
     * At this point, we have room of outl bytes and an empty buffer, so we
     * should read in some more.
     */

    ret_code = 0;
    while (outl > 0) {
        if (ctx->cont <= 0)
            break;

        i = BIO_read(b->next_bio, &(ctx->tmp[ctx->tmp_len]),
                     B64_BLOCK_SIZE - ctx->tmp_len);

        if (i <= 0) {
            ret_code = i;

            /* Should we continue next time we are called? */
            if (!BIO_should_retry(b->next_bio)) {
                ctx->cont = i;
                /* If buffer empty break */
                if (ctx->tmp_len == 0)
                    break;
                /* Fall through and process what we have */
                else
                    i = 0;
            }
            /* else we retry and add more data to buffer */
            else
                break;
        }
        i += ctx->tmp_len;
        ctx->tmp_len = i;

        /*
         * We need to scan, a line at a time until we have a valid line if we
         * are starting.
         */
        if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) {
            /* ctx->start=1; */
            ctx->tmp_len = 0;
        } else if (ctx->start) {
            q = p = (unsigned char *)ctx->tmp;
            num = 0;
            for (j = 0; j < i; j++) {
                if (*(q++) != '\n')
                    continue;

                /*
                 * due to a previous very long line, we need to keep on
                 * scanning for a '\n' before we even start looking for
                 * base64 encoded stuff.
                 */
                if (ctx->tmp_nl) {
                    p = q;
                    ctx->tmp_nl = 0;
                    continue;
                }

                k = EVP_DecodeUpdate(ctx->base64,
                                     (unsigned char *)ctx->buf,
                                     &num, p, q - p);
                if ((k <= 0) && (num == 0) && (ctx->start))
                    EVP_DecodeInit(ctx->base64);
                else {
                    if (p != (unsigned char *)
                        &(ctx->tmp[0])) {
                        i -= (p - (unsigned char *)
                              &(ctx->tmp[0]));
                        for (x = 0; x < i; x++)
                            ctx->tmp[x] = p[x];
                    }
                    EVP_DecodeInit(ctx->base64);
                    ctx->start = 0;
                    break;
                }
                p = q;
            }

            /* we fell off the end without starting */
            if ((j == i) && (num == 0)) {
                /*
                 * Is this is one long chunk?, if so, keep on reading until a
                 * new line.
                 */
                if (p == (unsigned char *)&(ctx->tmp[0])) {
                    /* Check buffer full */
                    if (i == B64_BLOCK_SIZE) {
                        ctx->tmp_nl = 1;
                        ctx->tmp_len = 0;
                    }
                } else if (p != q) { /* finished on a '\n' */
                    n = q - p;
                    for (ii = 0; ii < n; ii++)
                        ctx->tmp[ii] = p[ii];
                    ctx->tmp_len = n;
                }
                /* else finished on a '\n' */
                continue;
            } else {
                ctx->tmp_len = 0;
            }
        } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) {
            /*
             * If buffer isn't full and we can retry then restart to read in
             * more data.
             */
            continue;
        }

        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) {
            int z, jj;

            jj = i & ~3;        /* process per 4 */
            z = EVP_DecodeBlock((unsigned char *)ctx->buf,
                                (unsigned char *)ctx->tmp, jj);
            if (jj > 2) {
                if (ctx->tmp[jj - 1] == '=') {
                    z--;
                    if (ctx->tmp[jj - 2] == '=')
                        z--;
                }
            }
            /*
             * z is now number of output bytes and jj is the number consumed
             */
            if (jj != i) {
                memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
                ctx->tmp_len = i - jj;
            }
            ctx->buf_len = 0;
            if (z > 0) {
                ctx->buf_len = z;
            }
            i = z;
        } else {
            i = EVP_DecodeUpdate(ctx->base64,
                                 (unsigned char *)ctx->buf, &ctx->buf_len,
                                 (unsigned char *)ctx->tmp, i);
            ctx->tmp_len = 0;
        }
        ctx->buf_off = 0;
        if (i < 0) {
            ret_code = 0;
            ctx->buf_len = 0;
            break;
        }

        if (ctx->buf_len <= outl)
            i = ctx->buf_len;
        else
            i = outl;

        memcpy(out, ctx->buf, i);
        ret += i;
        ctx->buf_off = i;
        if (ctx->buf_off == ctx->buf_len) {
            ctx->buf_len = 0;
            ctx->buf_off = 0;
        }
        outl -= i;
        out += i;
    }
    /* BIO_clear_retry_flags(b); */
    BIO_copy_next_retry(b);
    return ((ret == 0) ? ret_code : ret);
}
Example #29
0
BIO *
BIO_new_dgram_sctp(int fd, int close_flag)
{
	BIO *bio;
	int ret, optval = 20000;
	int auth_data = 0, auth_forward = 0;
	unsigned char *p;
	struct sctp_authchunk auth;
	struct sctp_authchunks *authchunks;
	socklen_t sockopt_len;
#ifdef SCTP_AUTHENTICATION_EVENT
#ifdef SCTP_EVENT
	struct sctp_event event;
#else
	struct sctp_event_subscribe event;
#endif
#endif

	bio = BIO_new(BIO_s_datagram_sctp());
	if (bio == NULL)
		return (NULL);
	BIO_set_fd(bio, fd, close_flag);

	/* Activate SCTP-AUTH for DATA and FORWARD-TSN chunks */
	auth.sauth_chunk = OPENSSL_SCTP_DATA_CHUNK_TYPE;
	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
	OPENSSL_assert(ret >= 0);
	auth.sauth_chunk = OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE;
	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_AUTH_CHUNK, &auth, sizeof(struct sctp_authchunk));
	OPENSSL_assert(ret >= 0);

	/* Test if activation was successful. When using accept(),
	 * SCTP-AUTH has to be activated for the listening socket
	 * already, otherwise the connected socket won't use it. */
	sockopt_len = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
	authchunks = calloc(1, sockopt_len);
	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_LOCAL_AUTH_CHUNKS, authchunks, &sockopt_len);
	OPENSSL_assert(ret >= 0);

	for (p = (unsigned char*) authchunks->gauth_chunks;
	    p < (unsigned char*) authchunks + sockopt_len;
	    p += sizeof(uint8_t)) {
		if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE)
			auth_data = 1;
		if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE)
			auth_forward = 1;
	}

	free(authchunks);

	OPENSSL_assert(auth_data);
	OPENSSL_assert(auth_forward);

#ifdef SCTP_AUTHENTICATION_EVENT
#ifdef SCTP_EVENT
	memset(&event, 0, sizeof(struct sctp_event));
	event.se_assoc_id = 0;
	event.se_type = SCTP_AUTHENTICATION_EVENT;
	event.se_on = 1;
	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
	OPENSSL_assert(ret >= 0);
#else
	sockopt_len = (socklen_t) sizeof(struct sctp_event_subscribe);
	ret = getsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, &sockopt_len);
	OPENSSL_assert(ret >= 0);

	event.sctp_authentication_event = 1;

	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
	OPENSSL_assert(ret >= 0);
#endif
#endif

	/* Disable partial delivery by setting the min size
	 * larger than the max record size of 2^14 + 2048 + 13
	 */
	ret = setsockopt(fd, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT, &optval, sizeof(optval));
	OPENSSL_assert(ret >= 0);

	return (bio);
}
Example #30
0
/* SSL 2.0 imlementation for SSL_read/SSL_peek -
 * This routine will return 0 to len bytes, decrypted etc if required.
 */
static int ssl2_read_internal(SSL *s, void *buf, int len, int peek)
	{
	int n;
	unsigned char mac[MAX_MAC_SIZE];
	unsigned char *p;
	int i;
	int mac_size;

 ssl2_read_again:
	if (SSL_in_init(s) && !s->in_handshake)
		{
		n=s->handshake_func(s);
		if (n < 0) return(n);
		if (n == 0)
			{
			SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_SSL_HANDSHAKE_FAILURE);
			return(-1);
			}
		}

	clear_sys_error();
	s->rwstate=SSL_NOTHING;
	if (len <= 0) return(len);

	if (s->s2->ract_data_length != 0) /* read from buffer */
		{
		if (len > s->s2->ract_data_length)
			n=s->s2->ract_data_length;
		else
			n=len;

		memcpy(buf,s->s2->ract_data,(unsigned int)n);
		if (!peek)
			{
			s->s2->ract_data_length-=n;
			s->s2->ract_data+=n;
			if (s->s2->ract_data_length == 0)
				s->rstate=SSL_ST_READ_HEADER;
			}

		return(n);
		}

	/* s->s2->ract_data_length == 0
	 * 
	 * Fill the buffer, then goto ssl2_read_again.
	 */

	if (s->rstate == SSL_ST_READ_HEADER)
		{
		if (s->first_packet)
			{
			n=read_n(s,5,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
			if (n <= 0) return(n); /* error or non-blocking */
			s->first_packet=0;
			p=s->packet;
			if (!((p[0] & 0x80) && (
				(p[2] == SSL2_MT_CLIENT_HELLO) ||
				(p[2] == SSL2_MT_SERVER_HELLO))))
				{
				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_NON_SSLV2_INITIAL_PACKET);
				return(-1);
				}
			}
		else
			{
			n=read_n(s,2,SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER+2,0);
			if (n <= 0) return(n); /* error or non-blocking */
			}
		/* part read stuff */

		s->rstate=SSL_ST_READ_BODY;
		p=s->packet;
		/* Do header */
		/*s->s2->padding=0;*/
		s->s2->escape=0;
		s->s2->rlength=(((unsigned int)p[0])<<8)|((unsigned int)p[1]);
		if ((p[0] & TWO_BYTE_BIT))		/* Two byte header? */
			{
			s->s2->three_byte_header=0;
			s->s2->rlength&=TWO_BYTE_MASK;	
			}
		else
			{
			s->s2->three_byte_header=1;
			s->s2->rlength&=THREE_BYTE_MASK;

			/* security >s2->escape */
			s->s2->escape=((p[0] & SEC_ESC_BIT))?1:0;
			}
		}

	if (s->rstate == SSL_ST_READ_BODY)
		{
		n=s->s2->rlength+2+s->s2->three_byte_header;
		if (n > (int)s->packet_length)
			{
			n-=s->packet_length;
			i=read_n(s,(unsigned int)n,(unsigned int)n,1);
			if (i <= 0) return(i); /* ERROR */
			}

		p= &(s->packet[2]);
		s->rstate=SSL_ST_READ_HEADER;
		if (s->s2->three_byte_header)
			s->s2->padding= *(p++);
		else	s->s2->padding=0;

		/* Data portion */
		if (s->s2->clear_text)
			{
			mac_size = 0;
			s->s2->mac_data=p;
			s->s2->ract_data=p;
			if (s->s2->padding)
				{
				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING);
				return(-1);
				}
			}
		else
			{
			mac_size=EVP_MD_CTX_size(s->read_hash);
			if (mac_size < 0)
				return -1;
			OPENSSL_assert(mac_size <= MAX_MAC_SIZE);
			s->s2->mac_data=p;
			s->s2->ract_data= &p[mac_size];
			if (s->s2->padding + mac_size > s->s2->rlength)
				{
				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_ILLEGAL_PADDING);
				return(-1);
				}
			}

		s->s2->ract_data_length=s->s2->rlength;
		/* added a check for length > max_size in case
		 * encryption was not turned on yet due to an error */
		if ((!s->s2->clear_text) &&
			(s->s2->rlength >= (unsigned int)mac_size))
			{
			ssl2_enc(s,0);
			s->s2->ract_data_length-=mac_size;
			ssl2_mac(s,mac,0);
			s->s2->ract_data_length-=s->s2->padding;
			if (	(CRYPTO_memcmp(mac,s->s2->mac_data,mac_size) != 0) ||
				(s->s2->rlength%EVP_CIPHER_CTX_block_size(s->enc_read_ctx) != 0))
				{
				SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_MAC_DECODE);
				return(-1);
				}
			}
		INC32(s->s2->read_sequence); /* expect next number */
		/* s->s2->ract_data is now available for processing */

		/* Possibly the packet that we just read had 0 actual data bytes.
		 * (SSLeay/OpenSSL itself never sends such packets; see ssl2_write.)
		 * In this case, returning 0 would be interpreted by the caller
		 * as indicating EOF, so it's not a good idea.  Instead, we just
		 * continue reading; thus ssl2_read_internal may have to process
		 * multiple packets before it can return.
		 *
		 * [Note that using select() for blocking sockets *never* guarantees
		 * that the next SSL_read will not block -- the available
		 * data may contain incomplete packets, and except for SSL 2,
		 * renegotiation can confuse things even more.] */

		goto ssl2_read_again; /* This should really be
		                       * "return ssl2_read(s,buf,len)",
		                       * but that would allow for
		                       * denial-of-service attacks if a
		                       * C compiler is used that does not
		                       * recognize end-recursion. */
		}
	else
		{
		SSLerr(SSL_F_SSL2_READ_INTERNAL,SSL_R_BAD_STATE);
			return(-1);
		}
	}