Example #1
0
int main(int Argc, char *ARGV[])
	{
	ARGS arg;
#define PROG_NAME_SIZE	39
	char pname[PROG_NAME_SIZE+1];
	FUNCTION f,*fp;
	MS_STATIC const char *prompt;
	MS_STATIC char buf[1024];
	char *to_free=NULL;
	int n,i,ret=0;
	int argc;
	char **argv,*p;
	LHASH_OF(FUNCTION) *prog=NULL;
	long errline;

#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
	/* 2011-03-22 SMS.
	 * If we have 32-bit pointers everywhere, then we're safe, and
	 * we bypass this mess, as on non-VMS systems.  (See ARGV,
	 * above.)
	 * Problem 1: Compaq/HP C before V7.3 always used 32-bit
	 * pointers for argv[].
	 * Fix 1: For a 32-bit argv[], when we're using 64-bit pointers
	 * everywhere else, we always allocate and use a 64-bit
	 * duplicate of argv[].
	 * Problem 2: Compaq/HP C V7.3 (Alpha, IA64) before ECO1 failed
	 * to NULL-terminate a 64-bit argv[].  (As this was written, the
	 * compiler ECO was available only on IA64.)
	 * Fix 2: Unless advised not to (VMS_TRUST_ARGV), we test a
	 * 64-bit argv[argc] for NULL, and, if necessary, use a
	 * (properly) NULL-terminated (64-bit) duplicate of argv[].
	 * The same code is used in either case to duplicate argv[].
	 * Some of these decisions could be handled in preprocessing,
	 * but the code tends to get even uglier, and the penalty for
	 * deciding at compile- or run-time is tiny.
	 */
	char **Argv = NULL;
	int free_Argv = 0;

	if ((sizeof( _Argv) < 8)        /* 32-bit argv[]. */
# if !defined( VMS_TRUST_ARGV)
	 || (_Argv[ Argc] != NULL)      /* Untrusted argv[argc] not NULL. */
# endif
		)
		{
		int i;
		Argv = OPENSSL_malloc( (Argc+ 1)* sizeof( char *));
		if (Argv == NULL)
			{ ret = -1; goto end; }
		for(i = 0; i < Argc; i++)
			Argv[i] = _Argv[i];
		Argv[ Argc] = NULL;     /* Certain NULL termination. */
		free_Argv = 1;
		}
	else
		{
		/* Use the known-good 32-bit argv[] (which needs the
		 * type cast to satisfy the compiler), or the trusted or
		 * tested-good 64-bit argv[] as-is. */
		Argv = (char **)_Argv;
		}
#endif /* defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64) */

	arg.data=NULL;
	arg.count=0;

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

	if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) /* if not defined, use compiled-in library defaults */
		{
		if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off")))
			{
			CRYPTO_malloc_debug_init();
			CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
			}
		else
			{
			/* OPENSSL_DEBUG_MEMORY=off */
			CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
			}
		}
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

#if 0
	if (getenv("OPENSSL_DEBUG_LOCKING") != NULL)
#endif
		{
		CRYPTO_set_locking_callback(lock_dbg_cb);
		}

	if(getenv("OPENSSL_FIPS")) {
#ifdef OPENSSL_FIPS
		if (!FIPS_mode_set(1)) {
			ERR_load_crypto_strings();
			ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
			EXIT(1);
		}
#else
		fprintf(stderr, "FIPS mode not supported.\n");
		EXIT(1);
#endif
		}

	apps_startup();

	/* Lets load up our environment a little */
	p=getenv("OPENSSL_CONF");
	if (p == NULL)
		p=getenv("SSLEAY_CONF");
	if (p == NULL)
		p=to_free=make_config_name();

	default_config_file=p;

	config=NCONF_new(NULL);
	i=NCONF_load(config,p,&errline);
	if (i == 0)
		{
		if (ERR_GET_REASON(ERR_peek_last_error())
		    == CONF_R_NO_SUCH_FILE)
			{
			BIO_printf(bio_err,
				   "WARNING: can't open config file: %s\n",p);
			ERR_clear_error();
			NCONF_free(config);
			config = NULL;
			}
		else
			{
			ERR_print_errors(bio_err);
			NCONF_free(config);
			exit(1);
			}
		}

	prog=prog_init();

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

	f.name=pname;
	fp=lh_FUNCTION_retrieve(prog,&f);
	if (fp != NULL)
		{
		Argv[0]=pname;
		ret=fp->func(Argc,Argv);
		goto end;
		}

	/* ok, now check that there are not arguments, if there are,
	 * run with them, shifting the ssleay off the front */
	if (Argc != 1)
		{
		Argc--;
		Argv++;
		ret=do_cmd(prog,Argc,Argv);
		if (ret < 0) ret=0;
		goto end;
		}

	/* ok, lets enter the old 'OpenSSL>' mode */
	
	for (;;)
		{
		ret=0;
		p=buf;
		n=sizeof buf;
		i=0;
		for (;;)
			{
			p[0]='\0';
			if (i++)
				prompt=">";
			else	prompt="OpenSSL> ";
			fputs(prompt,stdout);
			fflush(stdout);
			if (!fgets(p,n,stdin))
				goto end;
			if (p[0] == '\0') goto end;
			i=strlen(p);
			if (i <= 1) break;
			if (p[i-2] != '\\') break;
			i-=2;
			p+=i;
			n-=i;
			}
		if (!chopup_args(&arg,buf,&argc,&argv)) break;

		ret=do_cmd(prog,argc,argv);
		if (ret < 0)
			{
			ret=0;
			goto end;
			}
		if (ret != 0)
			BIO_printf(bio_err,"error in %s\n",argv[0]);
		(void)BIO_flush(bio_err);
		}
	BIO_printf(bio_err,"bad exit\n");
	ret=1;
end:
	if (to_free)
		OPENSSL_free(to_free);
	if (config != NULL)
		{
		NCONF_free(config);
		config=NULL;
		}
	if (prog != NULL) lh_FUNCTION_free(prog);
	if (arg.data != NULL) OPENSSL_free(arg.data);

	apps_shutdown();

	CRYPTO_mem_leaks(bio_err);
	if (bio_err != NULL)
		{
		BIO_free(bio_err);
		bio_err=NULL;
		}
#if defined( OPENSSL_SYS_VMS) && (__INITIAL_POINTER_SIZE == 64)
	/* Free any duplicate Argv[] storage. */
	if (free_Argv)
		{
		OPENSSL_free(Argv);
		}
#endif
	OPENSSL_EXIT(ret);
	}
Example #2
0
void
tlsext_cb(SSL * s, int client_server, int type, unsigned char *data, int len,
    void *arg)
{
	BIO *bio = arg;
	char *extname;

	switch (type) {
	case TLSEXT_TYPE_server_name:
		extname = "server name";
		break;

	case TLSEXT_TYPE_max_fragment_length:
		extname = "max fragment length";
		break;

	case TLSEXT_TYPE_client_certificate_url:
		extname = "client certificate URL";
		break;

	case TLSEXT_TYPE_trusted_ca_keys:
		extname = "trusted CA keys";
		break;

	case TLSEXT_TYPE_truncated_hmac:
		extname = "truncated HMAC";
		break;

	case TLSEXT_TYPE_status_request:
		extname = "status request";
		break;

	case TLSEXT_TYPE_user_mapping:
		extname = "user mapping";
		break;

	case TLSEXT_TYPE_client_authz:
		extname = "client authz";
		break;

	case TLSEXT_TYPE_server_authz:
		extname = "server authz";
		break;

	case TLSEXT_TYPE_cert_type:
		extname = "cert type";
		break;

	case TLSEXT_TYPE_elliptic_curves:
		extname = "elliptic curves";
		break;

	case TLSEXT_TYPE_ec_point_formats:
		extname = "EC point formats";
		break;

	case TLSEXT_TYPE_srp:
		extname = "SRP";
		break;

	case TLSEXT_TYPE_signature_algorithms:
		extname = "signature algorithms";
		break;

	case TLSEXT_TYPE_use_srtp:
		extname = "use SRTP";
		break;

	case TLSEXT_TYPE_heartbeat:
		extname = "heartbeat";
		break;

	case TLSEXT_TYPE_session_ticket:
		extname = "session ticket";
		break;

	case TLSEXT_TYPE_renegotiate:
		extname = "renegotiation info";
		break;

#ifdef TLSEXT_TYPE_next_proto_neg
	case TLSEXT_TYPE_next_proto_neg:
		extname = "next protocol";
		break;
#endif

	default:
		extname = "unknown";
		break;

	}

	BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
	    client_server ? "server" : "client", extname, type, len);
	BIO_dump(bio, (char *) data, len);
	(void) BIO_flush(bio);
}
Example #3
0
/*! @brief est_convert_p7b64_to_pem() converts the base64 encoded
    PKCS7 response from the EST server into PEM format.   
 
    @param certs_p7 Points to a buffer containing the base64 encoded pkcs7 data.
    @param certs_len Indicates the size of the *certs_p7 buffer.
    @param pem Double pointer that will receive the PEM encoded data. 
 
    Several of the EST message return data that contains base64 encoded PKCS7
    certificates.  This function is used to convert the data to PEM format.
    This function will allocate memory pointed to by the **pem argument.
    The caller is responsible for releasing this memory.  The return value
    is the length of the PEM buffer, or -1 on error.
 
    @return int.
 */
int est_convert_p7b64_to_pem (unsigned char *certs_p7, int certs_len, unsigned char **pem)
{
    X509 *x;
    STACK_OF(X509) *certs = NULL;
    BIO *b64, *in, *out;
    unsigned char *cacerts_decoded = NULL;
    int  cacerts_decoded_len = 0;
    BIO *p7bio_in = NULL;
    PKCS7 *p7=NULL;
    int i, nid;
    unsigned char *pem_data;
    int pem_len;

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

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

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

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

    *pem = malloc(pem_len + 1);
    if (!*pem) {
        EST_LOG_ERR("malloc failed");
	PKCS7_free(p7);
	return (-1);
    }
    memcpy_s(*pem, pem_len, pem_data, pem_len);   
    (*pem)[pem_len] = 0;  //Make sure it's null termianted
    BIO_free_all(out);
    PKCS7_free(p7);
    return (pem_len);
}
int ssl23_connect(SSL *s)
	{
	BUF_MEM *buf=NULL;
	unsigned long Time=(unsigned long)time(NULL);
	void (*cb)(const SSL *ssl,int type,int val)=NULL;
	int ret= -1;
	int new_state,state;

	RAND_add(&Time,sizeof(Time),0);
	ERR_clear_error();
	clear_sys_error();

	if (s->info_callback != NULL)
		cb=s->info_callback;
	else if (s->ctx->info_callback != NULL)
		cb=s->ctx->info_callback;
	
	s->in_handshake++;
	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 

	for (;;)
		{
		state=s->state;

		switch(s->state)
			{
		case SSL_ST_BEFORE:
		case SSL_ST_CONNECT:
		case SSL_ST_BEFORE|SSL_ST_CONNECT:
		case SSL_ST_OK|SSL_ST_CONNECT:

			if (s->session != NULL)
				{
				SSLerr(SSL_F_SSL23_CONNECT,SSL_R_SSL23_DOING_SESSION_ID_REUSE);
				ret= -1;
				goto end;
				}
			s->server=0;
			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

			/* s->version=TLS1_VERSION; */
			s->type=SSL_ST_CONNECT;

			if (s->init_buf == NULL)
				{
				if ((buf=BUF_MEM_new()) == NULL)
					{
					ret= -1;
					goto end;
					}
				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
					{
					ret= -1;
					goto end;
					}
				s->init_buf=buf;
				buf=NULL;
				}

			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }

			ssl3_init_finished_mac(s);

			s->state=SSL23_ST_CW_CLNT_HELLO_A;
			s->ctx->stats.sess_connect++;
			s->init_num=0;
			break;

		case SSL23_ST_CW_CLNT_HELLO_A:
		case SSL23_ST_CW_CLNT_HELLO_B:

			s->shutdown=0;
			ret=ssl23_client_hello(s);
			if (ret <= 0) goto end;
			s->state=SSL23_ST_CR_SRVR_HELLO_A;
			s->init_num=0;

			break;

		case SSL23_ST_CR_SRVR_HELLO_A:
		case SSL23_ST_CR_SRVR_HELLO_B:
			ret=ssl23_get_server_hello(s);
			if (ret >= 0) cb=NULL;
			goto end;
			/* break; */

		default:
			SSLerr(SSL_F_SSL23_CONNECT,SSL_R_UNKNOWN_STATE);
			ret= -1;
			goto end;
			/* break; */
			}

		if (s->debug) { (void)BIO_flush(s->wbio); }

		if ((cb != NULL) && (s->state != state))
			{
			new_state=s->state;
			s->state=state;
			cb(s,SSL_CB_CONNECT_LOOP,1);
			s->state=new_state;
			}
		}
end:
	s->in_handshake--;
	if (buf != NULL)
		BUF_MEM_free(buf);
	if (cb != NULL)
		cb(s,SSL_CB_CONNECT_EXIT,ret);
	return(ret);
	}
/* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC) */
int dtls1_do_write(SSL *s, int type)
	{
	int ret;
	int curr_mtu;
	unsigned int len, frag_off;

	/* AHA!  Figure out the MTU, and stick to the right size */
	if ( ! (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU))
        {
		s->d1->mtu = 
			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);

		/* I've seen the kernel return bogus numbers when it doesn't know
		 * (initial write), so just make sure we have a reasonable number */
		if ( s->d1->mtu < dtls1_min_mtu())
			{
			s->d1->mtu = 0;
			s->d1->mtu = dtls1_guess_mtu(s->d1->mtu);
			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SET_MTU, 
				s->d1->mtu, NULL);
			}
		}
#if 0 
	mtu = s->d1->mtu;

	fprintf(stderr, "using MTU = %d\n", mtu);

	mtu -= (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);

	curr_mtu = mtu - BIO_wpending(SSL_get_wbio(s));

	if ( curr_mtu > 0)
		mtu = curr_mtu;
	else if ( ( ret = BIO_flush(SSL_get_wbio(s))) <= 0)
		return ret;
		
	if ( BIO_wpending(SSL_get_wbio(s)) + s->init_num >= mtu)
		{
		ret = BIO_flush(SSL_get_wbio(s));
		if ( ret <= 0)
			return ret;
		mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH);
		}

	OPENSSL_assert(mtu > 0);  /* should have something reasonable now */

#endif

	if ( s->init_off == 0  && type == SSL3_RT_HANDSHAKE)
		OPENSSL_assert(s->init_num == 
			(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);

	frag_off = 0;
	while( s->init_num)
		{
		curr_mtu = s->d1->mtu - BIO_wpending(SSL_get_wbio(s)) - 
			DTLS1_RT_HEADER_LENGTH;

		if ( curr_mtu <= DTLS1_HM_HEADER_LENGTH)
			{
			/* grr.. we could get an error if MTU picked was wrong */
			ret = BIO_flush(SSL_get_wbio(s));
			if ( ret <= 0)
				return ret;
			curr_mtu = s->d1->mtu - DTLS1_RT_HEADER_LENGTH;
			}

		if ( s->init_num > curr_mtu)
			len = curr_mtu;
		else
			len = s->init_num;


		/* XDTLS: this function is too long.  split out the CCS part */
		if ( type == SSL3_RT_HANDSHAKE)
			{
			if ( s->init_off != 0)
				{
				OPENSSL_assert(s->init_off > DTLS1_HM_HEADER_LENGTH);
				s->init_off -= DTLS1_HM_HEADER_LENGTH;
				s->init_num += DTLS1_HM_HEADER_LENGTH;

                /* write atleast DTLS1_HM_HEADER_LENGTH bytes */
				if ( len <= DTLS1_HM_HEADER_LENGTH)  
					len += DTLS1_HM_HEADER_LENGTH;
				}
			
			dtls1_fix_message_header(s, frag_off, 
				len - DTLS1_HM_HEADER_LENGTH);

			dtls1_write_message_header(s, (unsigned char *)&s->init_buf->data[s->init_off]);

			OPENSSL_assert(len >= DTLS1_HM_HEADER_LENGTH);
			}

		ret=dtls1_write_bytes(s,type,&s->init_buf->data[s->init_off],
			len);
		if (ret < 0)
			{
			/* might need to update MTU here, but we don't know
			 * which previous packet caused the failure -- so can't
			 * really retransmit anything.  continue as if everything
			 * is fine and wait for an alert to handle the
			 * retransmit 
			 */
			if ( BIO_ctrl(SSL_get_wbio(s),
				BIO_CTRL_DGRAM_MTU_EXCEEDED, 0, NULL))
				s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
					BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
			else
				return(-1);
			}
		else
			{
			
			/* bad if this assert fails, only part of the handshake
			 * message got sent.  but why would this happen? */
			OPENSSL_assert(len == (unsigned int)ret); 
			
			if (type == SSL3_RT_HANDSHAKE && ! s->d1->retransmitting)
				/* should not be done for 'Hello Request's, but in that case
				 * we'll ignore the result anyway */
				ssl3_finish_mac(s, 
					(unsigned char *)&s->init_buf->data[s->init_off + 
						DTLS1_HM_HEADER_LENGTH], ret - DTLS1_HM_HEADER_LENGTH);
			
			if (ret == s->init_num)
				{
				if (s->msg_callback)
					s->msg_callback(1, s->version, type, s->init_buf->data, 
						(size_t)(s->init_off + s->init_num), s, 
						s->msg_callback_arg);

				s->init_off = 0;  /* done writing this message */
				s->init_num = 0;
				
				return(1);
				}
			s->init_off+=ret;
			s->init_num-=ret;
			frag_off += (ret -= DTLS1_HM_HEADER_LENGTH);
			}
		}
	return(0);
	}
Example #6
0
int OCSP_sendreq_nbio (OCSP_RESPONSE ** presp, OCSP_REQ_CTX * rctx)
{
    int i, n;

    const unsigned char *p;

  next_io:
    if (!(rctx->state & OHS_NOREAD))
    {
        n = BIO_read (rctx->io, rctx->iobuf, rctx->iobuflen);

        if (n <= 0)
        {
            if (BIO_should_retry (rctx->io))
                return -1;
            return 0;
        }

        /* Write data to memory BIO */

        if (BIO_write (rctx->mem, rctx->iobuf, n) != n)
            return 0;
    }

    switch (rctx->state)
    {

        case OHS_ASN1_WRITE:
            n = BIO_get_mem_data (rctx->mem, &p);

            i = BIO_write (rctx->io, p + (n - rctx->asn1_len), rctx->asn1_len);

            if (i <= 0)
            {
                if (BIO_should_retry (rctx->io))
                    return -1;
                rctx->state = OHS_ERROR;
                return 0;
            }

            rctx->asn1_len -= i;

            if (rctx->asn1_len > 0)
                goto next_io;

            rctx->state = OHS_ASN1_FLUSH;

            (void) BIO_reset (rctx->mem);

        case OHS_ASN1_FLUSH:

            i = BIO_flush (rctx->io);

            if (i > 0)
            {
                rctx->state = OHS_FIRSTLINE;
                goto next_io;
            }

            if (BIO_should_retry (rctx->io))
                return -1;

            rctx->state = OHS_ERROR;
            return 0;

        case OHS_ERROR:
            return 0;

        case OHS_FIRSTLINE:
        case OHS_HEADERS:

            /* Attempt to read a line in */

          next_line:
            /* Due to &%^*$" memory BIO behaviour with BIO_gets we
             * have to check there's a complete line in there before
             * calling BIO_gets or we'll just get a partial read.
             */
            n = BIO_get_mem_data (rctx->mem, &p);
            if ((n <= 0) || !memchr (p, '\n', n))
            {
                if (n >= rctx->iobuflen)
                {
                    rctx->state = OHS_ERROR;
                    return 0;
                }
                goto next_io;
            }
            n = BIO_gets (rctx->mem, (char *) rctx->iobuf, rctx->iobuflen);

            if (n <= 0)
            {
                if (BIO_should_retry (rctx->mem))
                    goto next_io;
                rctx->state = OHS_ERROR;
                return 0;
            }

            /* Don't allow excessive lines */
            if (n == rctx->iobuflen)
            {
                rctx->state = OHS_ERROR;
                return 0;
            }

            /* First line */
            if (rctx->state == OHS_FIRSTLINE)
            {
                if (parse_http_line1 ((char *) rctx->iobuf))
                {
                    rctx->state = OHS_HEADERS;
                    goto next_line;
                }
                else
                {
                    rctx->state = OHS_ERROR;
                    return 0;
                }
            }
            else
            {
                /* Look for blank line: end of headers */
                for (p = rctx->iobuf; *p; p++)
                {
                    if ((*p != '\r') && (*p != '\n'))
                        break;
                }
                if (*p)
                    goto next_line;

                rctx->state = OHS_ASN1_HEADER;

            }

            /* Fall thru */


        case OHS_ASN1_HEADER:
            /* Now reading ASN1 header: can read at least 2 bytes which
             * is enough for ASN1 SEQUENCE header and either length field
             * or at least the length of the length field.
             */
            n = BIO_get_mem_data (rctx->mem, &p);
            if (n < 2)
                goto next_io;

            /* Check it is an ASN1 SEQUENCE */
            if (*p++ != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED))
            {
                rctx->state = OHS_ERROR;
                return 0;
            }

            /* Check out length field */
            if (*p & 0x80)
            {
                /* If MSB set on initial length octet we can now
                 * always read 6 octets: make sure we have them.
                 */
                if (n < 6)
                    goto next_io;
                n = *p & 0x7F;
                /* Not NDEF or excessive length */
                if (!n || (n > 4))
                {
                    rctx->state = OHS_ERROR;
                    return 0;
                }
                p++;
                rctx->asn1_len = 0;
                for (i = 0; i < n; i++)
                {
                    rctx->asn1_len <<= 8;
                    rctx->asn1_len |= *p++;
                }

                if (rctx->asn1_len > OCSP_MAX_REQUEST_LENGTH)
                {
                    rctx->state = OHS_ERROR;
                    return 0;
                }

                rctx->asn1_len += n + 2;
            }
            else
                rctx->asn1_len = *p + 2;

            rctx->state = OHS_ASN1_CONTENT;

            /* Fall thru */

        case OHS_ASN1_CONTENT:
            n = BIO_get_mem_data (rctx->mem, &p);
            if (n < (int) rctx->asn1_len)
                goto next_io;


            *presp = d2i_OCSP_RESPONSE (NULL, &p, rctx->asn1_len);
            if (*presp)
            {
                rctx->state = OHS_DONE;
                return 1;
            }

            rctx->state = OHS_ERROR;
            return 0;

            break;

        case OHS_DONE:
            return 1;

    }



    return 0;


}
void* IConnectionHandler::service(void* arg) {

	RequestProp *requestProp = (RequestProp*)arg;
	int fd = requestProp->fd;
	string data = requestProp->data;
	IConnectionHandler* handler = requestProp->handler;

	handler->logger << "start request service";

	if (!ClientInterface::isConnected(fd)) {
		handler->reader->p_mutex.lock();
		handler->reader->fds[fd] = true;
		handler->reader->p_mutex.unlock();
		return NULL;
	}

	Connection *conn = ConnectionPool::getConnection();
	if (!conn->client->isConnected()) {
		handler->reader->p_mutex.lock();
		handler->reader->fds[fd] = true;
		handler->reader->p_mutex.unlock();

		ConnectionPool::release(conn);
		return NULL;
	}

	if(handler->reader->isTextData())
	{
		StringUtil::replaceFirst(data, "Connection: keep-alive", "Connection: close");
		StringUtil::replaceFirst(data, "Connection: Keep-alive", "Connection: close");
		StringUtil::replaceFirst(data, "Connection: Keep-Alive", "Connection: close");
		StringUtil::replaceFirst(data, "Connection: keep-Alive", "Connection: close");
		StringUtil::replaceFirst(data, "{REPLACE_HOST_f2079930-4a8b-11e2-bcfd-0800200c9a66}", conn->host);
	}

	int bytes = conn->client->sendData(data);
	/*handler->logger << "Request START";
	handler->logger << data;
	handler->logger << "Request END";*/

	string call, tot;
	if(!handler->reader->isTextData())
		tot = conn->client->getBinaryData(handler->reader->getHeaderLength(), handler->reader->isHeaderLengthIncluded());
	else
		tot = conn->client->getTextData(handler->reader->getHeaderDelimiter(), handler->reader->getContentLnegthHeader());

	/*handler->logger << "Response START";
	handler->logger << tot;
	handler->logger << "Response END";*/

	int toto = tot.length();

	if(handler->reader->isSSL())
	{
		if(handler->reader->sslConns->find(fd)!=handler->reader->sslConns->end())
		{
			SSLConnection sslConn = handler->reader->sslConns->find(fd)->second;
			int r;
			if((r=BIO_write(sslConn.io, tot.c_str(), tot.length()))<=0)
			{
				handler->logger << "send failed";
			}
			if((r=BIO_flush(sslConn.io))<0)
			{
				handler->logger << "Error flushing BIO";
			}
		}
	}
	else
	{
		while (toto > 0) {
			bytes = send(fd, tot.c_str(), tot.length(), 0);
			if (bytes == 0 || bytes == -1)
				break;
			tot = tot.substr(bytes);
			toto -= bytes;
		}
	}
	if (ConnectionPool::isPersistent()){}
	else
	{
		handler->reader->p_mutex.lock();
		handler->reader->fds[fd] = true;
		handler->reader->p_mutex.unlock();

	}
	ConnectionPool::release(conn);
	delete requestProp;
	handler->logger << "done request service";
	return NULL;
}
Example #8
0
int main(int argc, char **argv)
{

	TSS_HKEY hSrk, hKey;
	TSS_HENCDATA hEncdata;
	TSS_HPOLICY hPolicy;
	int iRc = -1;
	struct option opts[] =
	    { {"infile", required_argument, NULL, 'i'},
	{"outfile", required_argument, NULL, 'o'},
	{"pcr", required_argument, NULL, 'p'},
	{"unicode", no_argument, NULL, 'u'},
	{"well-known", no_argument, NULL, 'z'}
	};
	unsigned char line[EVP_CIPHER_block_size(EVP_aes_256_cbc()) * 16];
	int lineLen;
	unsigned char encData[sizeof(line) + EVP_CIPHER_block_size(EVP_aes_256_cbc())];
	int encDataLen;
	UINT32 encLen, i;
	BYTE *encKey;
	BYTE *randKey = NULL;
	UINT32 sealKeyLen;
	BYTE *sealKey;
	TSS_FLAG keyFlags = TSS_KEY_TYPE_STORAGE | TSS_KEY_SIZE_2048 |
	    TSS_KEY_VOLATILE | TSS_KEY_AUTHORIZATION |
	    TSS_KEY_NOT_MIGRATABLE;
	TSS_HPOLICY hSrkPolicy;
	char *passwd = NULL;
	int pswd_len;
	BYTE wellKnown[TCPA_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;

	BIO *bin = NULL, *bdata=NULL, *b64=NULL;

	initIntlSys();

	if (genericOptHandler(argc, argv, "i:o:p:uz", opts,
			      sizeof(opts) / sizeof(struct option), parse,
			      help) != 0)
		goto out;

	if (contextCreate(&hContext) != TSS_SUCCESS)
		goto out;

	if (contextConnect(hContext) != TSS_SUCCESS)
		goto out_close;

	if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS)
		goto out_close;

	/* Create a BIO for the input file */
	if ((bin = BIO_new(BIO_s_file())) == NULL) {
		logError(_("Unable to open input BIO\n"));
		goto out_close;
	}

	/* Assign the input file to the BIO */
	if (strlen(in_filename) == 0) 
		BIO_set_fp(bin, stdin, BIO_NOCLOSE);
	else if (!BIO_read_filename(bin, in_filename)) {
		logError(_("Unable to open input file: %s\n"),
			 in_filename);
		goto out_close;
	}

	/* Create the PCRs object. If any PCRs above 15 are selected, this will need to be
	 * a 1.2 TSS/TPM */
	if (selectedPcrsLen) {
		TSS_FLAG initFlag = 0;
		UINT32 pcrSize;
		BYTE *pcrValue;

		for (i = 0; i < selectedPcrsLen; i++) {
			if (selectedPcrs[i] > 15) {
#ifdef TSS_LIB_IS_12
				initFlag |= TSS_PCRS_STRUCT_INFO_LONG;
#else
				logError(_("This version of %s was compiled for a v1.1 TSS, which "
					 "can only seal\n data to PCRs 0-15. PCR %u is out of range"
					 "\n"), argv[0], selectedPcrs[i]);
				goto out_close;
#endif
			}
		}

		if (contextCreateObject(hContext, TSS_OBJECT_TYPE_PCRS, initFlag,
					&hPcrs) != TSS_SUCCESS)
			goto out_close;

		for (i = 0; i < selectedPcrsLen; i++) {
			if (tpmPcrRead(hTpm, selectedPcrs[i], &pcrSize, &pcrValue) != TSS_SUCCESS)
				goto out_close;

			if (pcrcompositeSetPcrValue(hPcrs, selectedPcrs[i], pcrSize, pcrValue)
					!= TSS_SUCCESS)
				goto out_close;
		}
#ifdef TSS_LIB_IS_12
		if (initFlag) {
			UINT32 localityValue =
				TPM_LOC_ZERO | TPM_LOC_ONE | TPM_LOC_TWO | TPM_LOC_THREE |
				TPM_LOC_FOUR;

			if (pcrcompositeSetPcrLocality(hPcrs, localityValue) != TSS_SUCCESS)
				goto out_close;
		}
#endif
	}

	/* Retrieve random data to be used as the symmetric key
	   (this key will encrypt the input file contents) */
	if (tpmGetRandom(hTpm, EVP_CIPHER_key_length(EVP_aes_256_cbc()),
			 &randKey) != TSS_SUCCESS)
		goto out_close;

	/* Load the SRK and set the SRK policy (no password) */
	if (keyLoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSrk)
	    != TSS_SUCCESS)
		goto out_close;

	/* Use the context's default policy for the SRK secret */
	if (policyGet(hSrk, &hSrkPolicy) != TSS_SUCCESS)
		goto out_close;

	/* Prompt for SRK password */
	if (!isWellKnown) {
		passwd = _GETPASSWD(_("Enter SRK password: "), (int *)&pswd_len, FALSE,
				    passUnicode);
		if (!passwd) {
			logError(_("Failed to get SRK password\n"));
			goto out_close;
		}
	} else {
		passwd = (char *)wellKnown;
		pswd_len = sizeof(wellKnown);
	}

	if (policySetSecret(hSrkPolicy, (UINT32)pswd_len, (BYTE *)passwd) != TSS_SUCCESS)
		goto out_close;

	if (!isWellKnown)
		shredPasswd(passwd);
	passwd = NULL;

	/* Build an RSA key object that will be created by the TPM
	   (this will encrypt and protect the symmetric key) */
	if (contextCreateObject
	    (hContext, TSS_OBJECT_TYPE_RSAKEY, keyFlags,
	     &hKey) != TSS_SUCCESS)
		goto out_close;

	if (contextCreateObject
	    (hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
	     &hPolicy) != TSS_SUCCESS)
		goto out_close;

	if (policySetSecret(hPolicy, strlen(TPMSEAL_SECRET), (BYTE *)TPMSEAL_SECRET)
	    != TSS_SUCCESS)
		goto out_close;

	if (policyAssign(hPolicy, hKey) != TSS_SUCCESS)
		goto out_close;

	/* Create the RSA key (under the SRK) */
	if (keyCreateKey(hKey, hSrk, NULL_HPCRS) != TSS_SUCCESS)
		goto out_close;

	/* Load the newly created RSA key */
	if (keyLoadKey(hKey, hSrk) != TSS_SUCCESS)
		goto out_close;

	/* Build an encrypted data object that will hold the encrypted
	   version of the symmetric key */
	if (contextCreateObject
	    (hContext, TSS_OBJECT_TYPE_ENCDATA, TSS_ENCDATA_SEAL,
	     &hEncdata) != TSS_SUCCESS)
		goto out_close;

	if (contextCreateObject
	    (hContext, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE,
	     &hPolicy) != TSS_SUCCESS)
		goto out_close;

	if (policySetSecret(hPolicy, strlen(TPMSEAL_SECRET), (BYTE *)TPMSEAL_SECRET)
	    != TSS_SUCCESS)
		goto out_close;

	if (policyAssign(hPolicy, hEncdata) != TSS_SUCCESS)
		goto out_close;

	/* Encrypt and seal the symmetric key */
	if (dataSeal
	    (hEncdata, hKey, EVP_CIPHER_key_length(EVP_aes_256_cbc()),
	     randKey, hPcrs) != TSS_SUCCESS)
		goto out_close;

	if (getAttribData(hEncdata, TSS_TSPATTRIB_ENCDATA_BLOB,
			  TSS_TSPATTRIB_ENCDATABLOB_BLOB, &encLen,
			  &encKey) != TSS_SUCCESS)
		goto out_close;

	if (getAttribData
	    (hKey, TSS_TSPATTRIB_KEY_BLOB, TSS_TSPATTRIB_KEYBLOB_BLOB,
	     &sealKeyLen, &sealKey) != TSS_SUCCESS)
		goto out_close;

	/* Create a BIO to perform base64 encoding */
	if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
		logError(_("Unable to open base64 BIO\n"));
		goto out_close;
	}

	/* Create a BIO for the output file */
	if ((bdata = BIO_new(BIO_s_file())) == NULL) {
		logError(_("Unable to open output BIO\n"));
		goto out_close;
	}

	/* Assign the output file to the BIO */
	if (strlen(out_filename) == 0)
		BIO_set_fp(bdata, stdout, BIO_NOCLOSE);
	else if (BIO_write_filename(bdata, out_filename) <= 0) {
		logError(_("Unable to open output file: %s\n"),
			 out_filename);
		goto out_close;
	}

	/* Output the sealed data header string */
	BIO_puts(bdata, TPMSEAL_HDR_STRING);

	/* Sealing key used on the TPM */
	BIO_puts(bdata, TPMSEAL_TSS_STRING);
	bdata = BIO_push(b64, bdata);
	BIO_write(bdata, sealKey, sealKeyLen);
	if (BIO_flush(bdata) != 1) {
		logError(_("Unable to flush output\n"));
		goto out_close;
	}
	bdata = BIO_pop(b64);

	/* Sealed EVP Symmetric Key */
	BIO_puts(bdata, TPMSEAL_EVP_STRING);
	BIO_puts(bdata, TPMSEAL_KEYTYPE_SYM);
	BIO_puts(bdata, TPMSEAL_CIPHER_AES256CBC);
	bdata = BIO_push(b64, bdata);
	BIO_write(bdata, encKey, encLen);
	if (BIO_flush(bdata) != 1) {
		logError(_("Unable to flush output\n"));
		goto out_close;
	}
	bdata = BIO_pop(b64);

	/* Encrypted Data */
	BIO_puts(bdata, TPMSEAL_ENC_STRING); 
	bdata = BIO_push(b64, bdata);

	EVP_CIPHER_CTX ctx;
	EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), randKey, (unsigned char *)TPMSEAL_IV);

	while ((lineLen = BIO_read(bin, line, sizeof(line))) > 0) {
		EVP_EncryptUpdate(&ctx, encData, &encDataLen,
				  line, lineLen);
		BIO_write(bdata, encData, encDataLen);
	}

	EVP_EncryptFinal(&ctx, encData, &encDataLen);
	BIO_write(bdata, encData, encDataLen);
	if (BIO_flush(bdata) != 1) {
		logError(_("Unable to flush output\n"));
		goto out_close;
	}
	bdata = BIO_pop(b64);

	BIO_puts( bdata, TPMSEAL_FTR_STRING);
	
	iRc = 0;
	logSuccess(argv[0]);

out_close:
	contextClose(hContext);

out:
	if (bin)
		BIO_free(bin);
	if (bdata)
		BIO_free(bdata);
	if (b64)
		BIO_free(b64);
	return iRc;
}
Example #9
0
int
dtls1_connect(SSL *s)
{
	BUF_MEM *buf = NULL;
	void (*cb)(const SSL *ssl, int type, int val) = NULL;
	int ret = -1;
	int new_state, state, skip = 0;
#ifndef OPENSSL_NO_SCTP
	unsigned char sctpauthkey[64];
	char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
#endif

	ERR_clear_error();
	errno = 0;

	if (s->info_callback != NULL)
		cb = s->info_callback;
	else if (s->ctx->info_callback != NULL)
		cb = s->ctx->info_callback;

	s->in_handshake++;
	if (!SSL_in_init(s) || SSL_in_before(s))
		SSL_clear(s);

#ifndef OPENSSL_NO_SCTP
	/* Notify SCTP BIO socket to enter handshake
	 * mode and prevent stream identifier other
	 * than 0. Will be ignored if no SCTP is used.
	 */
	BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
	    s->in_handshake, NULL);
#endif

	for (;;) {
		state = s->state;

		switch (s->state) {
		case SSL_ST_RENEGOTIATE:
			s->renegotiate = 1;
			s->state = SSL_ST_CONNECT;
			s->ctx->stats.sess_connect_renegotiate++;
			/* break */
		case SSL_ST_BEFORE:
		case SSL_ST_CONNECT:
		case SSL_ST_BEFORE|SSL_ST_CONNECT:
		case SSL_ST_OK|SSL_ST_CONNECT:

			s->server = 0;
			if (cb != NULL)
				cb(s, SSL_CB_HANDSHAKE_START, 1);

			if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
			    (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00)) {
				SSLerr(SSL_F_DTLS1_CONNECT,
				    ERR_R_INTERNAL_ERROR);
				ret = -1;
				goto end;
			}

			/* s->version=SSL3_VERSION; */
			s->type = SSL_ST_CONNECT;

			if (s->init_buf == NULL) {
				if ((buf = BUF_MEM_new()) == NULL) {
					ret = -1;
					goto end;
				}
				if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
					ret = -1;
					goto end;
				}
				s->init_buf = buf;
				buf = NULL;
			}

			if (!ssl3_setup_buffers(s)) {
				ret = -1;
				goto end;
			}

			/* setup buffing BIO */
			if (!ssl_init_wbio_buffer(s, 0)) {
				ret = -1;
				goto end;
			}

			/* don't push the buffering BIO quite yet */

			s->state = SSL3_ST_CW_CLNT_HELLO_A;
			s->ctx->stats.sess_connect++;
			s->init_num = 0;
			/* mark client_random uninitialized */
			memset(s->s3->client_random, 0,
			    sizeof(s->s3->client_random));
			s->d1->send_cookie = 0;
			s->hit = 0;
			break;

#ifndef OPENSSL_NO_SCTP
		case DTLS1_SCTP_ST_CR_READ_SOCK:

			if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s))) {
				s->s3->in_read_app_data = 2;
				s->rwstate = SSL_READING;
				BIO_clear_retry_flags(SSL_get_rbio(s));
				BIO_set_retry_read(SSL_get_rbio(s));
				ret = -1;
				goto end;
			}

			s->state = s->s3->tmp.next_state;
			break;

		case DTLS1_SCTP_ST_CW_WRITE_SOCK:
			/* read app data until dry event */

			ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
			if (ret < 0)
				goto end;

			if (ret == 0) {
				s->s3->in_read_app_data = 2;
				s->rwstate = SSL_READING;
				BIO_clear_retry_flags(SSL_get_rbio(s));
				BIO_set_retry_read(SSL_get_rbio(s));
				ret = -1;
				goto end;
			}

			s->state = s->d1->next_state;
			break;
#endif

		case SSL3_ST_CW_CLNT_HELLO_A:
		case SSL3_ST_CW_CLNT_HELLO_B:

			s->shutdown = 0;

			/* every DTLS ClientHello resets Finished MAC */
			ssl3_init_finished_mac(s);

			dtls1_start_timer(s);
			ret = dtls1_client_hello(s);
			if (ret <= 0)
				goto end;

			if (s->d1->send_cookie) {
				s->state = SSL3_ST_CW_FLUSH;
				s->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
			} else
				s->state = SSL3_ST_CR_SRVR_HELLO_A;

			s->init_num = 0;

#ifndef OPENSSL_NO_SCTP
			/* Disable buffering for SCTP */
			if (!BIO_dgram_is_sctp(SSL_get_wbio(s))) {
#endif
				/* turn on buffering for the next lot of output */
				if (s->bbio != s->wbio)
					s->wbio = BIO_push(s->bbio, s->wbio);
#ifndef OPENSSL_NO_SCTP
			}
#endif
			break;

		case SSL3_ST_CR_SRVR_HELLO_A:
		case SSL3_ST_CR_SRVR_HELLO_B:
			ret = ssl3_get_server_hello(s);
			if (ret <= 0)
				goto end;
			else {
				if (s->hit) {
#ifndef OPENSSL_NO_SCTP
					/* Add new shared key for SCTP-Auth,
					 * will be ignored if no SCTP used.
					 */
					snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
					    DTLS1_SCTP_AUTH_LABEL);

					SSL_export_keying_material(s, sctpauthkey,
					    sizeof(sctpauthkey), labelbuffer,
					    sizeof(labelbuffer), NULL, 0, 0);

					BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
					    sizeof(sctpauthkey), sctpauthkey);
#endif

					s->state = SSL3_ST_CR_FINISHED_A;
				} else
					s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
			}
			s->init_num = 0;
			break;

		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:

			ret = dtls1_get_hello_verify(s);
			if (ret <= 0)
				goto end;
			dtls1_stop_timer(s);
			if ( s->d1->send_cookie) /* start again, with a cookie */
				s->state = SSL3_ST_CW_CLNT_HELLO_A;
			else
				s->state = SSL3_ST_CR_CERT_A;
			s->init_num = 0;
			break;

		case SSL3_ST_CR_CERT_A:
		case SSL3_ST_CR_CERT_B:
			ret = ssl3_check_finished(s);
			if (ret <= 0)
				goto end;
			if (ret == 2) {
				s->hit = 1;
				if (s->tlsext_ticket_expected)
					s->state = SSL3_ST_CR_SESSION_TICKET_A;
				else
					s->state = SSL3_ST_CR_FINISHED_A;
				s->init_num = 0;
				break;
			}
			/* Check if it is anon DH. */
			if (!(s->s3->tmp.new_cipher->algorithm_auth &
			    SSL_aNULL)) {
				ret = ssl3_get_server_certificate(s);
				if (ret <= 0)
					goto end;
				if (s->tlsext_status_expected)
					s->state = SSL3_ST_CR_CERT_STATUS_A;
				else
					s->state = SSL3_ST_CR_KEY_EXCH_A;
			} else {
				skip = 1;
				s->state = SSL3_ST_CR_KEY_EXCH_A;
			}
			s->init_num = 0;
			break;

		case SSL3_ST_CR_KEY_EXCH_A:
		case SSL3_ST_CR_KEY_EXCH_B:
			ret = ssl3_get_key_exchange(s);
			if (ret <= 0)
				goto end;
			s->state = SSL3_ST_CR_CERT_REQ_A;
			s->init_num = 0;

			/* at this point we check that we have the
			 * required stuff from the server */
			if (!ssl3_check_cert_and_algorithm(s)) {
				ret = -1;
				goto end;
			}
			break;

		case SSL3_ST_CR_CERT_REQ_A:
		case SSL3_ST_CR_CERT_REQ_B:
			ret = ssl3_get_certificate_request(s);
			if (ret <= 0)
				goto end;
			s->state = SSL3_ST_CR_SRVR_DONE_A;
			s->init_num = 0;
			break;

		case SSL3_ST_CR_SRVR_DONE_A:
		case SSL3_ST_CR_SRVR_DONE_B:
			ret = ssl3_get_server_done(s);
			if (ret <= 0)
				goto end;
			dtls1_stop_timer(s);
			if (s->s3->tmp.cert_req)
				s->s3->tmp.next_state = SSL3_ST_CW_CERT_A;
			else
				s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A;
			s->init_num = 0;

#ifndef OPENSSL_NO_SCTP
			if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
			    state == SSL_ST_RENEGOTIATE)
				s->state = DTLS1_SCTP_ST_CR_READ_SOCK;
			else
#endif
				s->state = s->s3->tmp.next_state;
			break;

		case SSL3_ST_CW_CERT_A:
		case SSL3_ST_CW_CERT_B:
		case SSL3_ST_CW_CERT_C:
		case SSL3_ST_CW_CERT_D:
			dtls1_start_timer(s);
			ret = dtls1_send_client_certificate(s);
			if (ret <= 0)
				goto end;
			s->state = SSL3_ST_CW_KEY_EXCH_A;
			s->init_num = 0;
			break;

		case SSL3_ST_CW_KEY_EXCH_A:
		case SSL3_ST_CW_KEY_EXCH_B:
			dtls1_start_timer(s);
			ret = dtls1_send_client_key_exchange(s);
			if (ret <= 0)
				goto end;

#ifndef OPENSSL_NO_SCTP
			/* Add new shared key for SCTP-Auth,
			 * will be ignored if no SCTP used.
			 */
			snprintf((char*)labelbuffer,
			    sizeof(DTLS1_SCTP_AUTH_LABEL),
			    DTLS1_SCTP_AUTH_LABEL);

			SSL_export_keying_material(s, sctpauthkey,
			    sizeof(sctpauthkey), labelbuffer,
			    sizeof(labelbuffer), NULL, 0, 0);

			BIO_ctrl(SSL_get_wbio(s),
			    BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
			    sizeof(sctpauthkey), sctpauthkey);
#endif

			/* EAY EAY EAY need to check for DH fix cert
			 * sent back */
			/* For TLS, cert_req is set to 2, so a cert chain
			 * of nothing is sent, but no verify packet is sent */
			if (s->s3->tmp.cert_req == 1) {
				s->state = SSL3_ST_CW_CERT_VRFY_A;
			} else {
#ifndef OPENSSL_NO_SCTP
				if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
					s->d1->next_state = SSL3_ST_CW_CHANGE_A;
					s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
				} else
#endif
					s->state = SSL3_ST_CW_CHANGE_A;
				s->s3->change_cipher_spec = 0;
			}

			s->init_num = 0;
			break;

		case SSL3_ST_CW_CERT_VRFY_A:
		case SSL3_ST_CW_CERT_VRFY_B:
			dtls1_start_timer(s);
			ret = dtls1_send_client_verify(s);
			if (ret <= 0)
				goto end;
#ifndef OPENSSL_NO_SCTP
			if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
				s->d1->next_state = SSL3_ST_CW_CHANGE_A;
				s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
			} else
#endif
				s->state = SSL3_ST_CW_CHANGE_A;
			s->init_num = 0;
			s->s3->change_cipher_spec = 0;
			break;

		case SSL3_ST_CW_CHANGE_A:
		case SSL3_ST_CW_CHANGE_B:
			if (!s->hit)
				dtls1_start_timer(s);
			ret = dtls1_send_change_cipher_spec(s,
			    SSL3_ST_CW_CHANGE_A, SSL3_ST_CW_CHANGE_B);
			if (ret <= 0)
				goto end;

			s->state = SSL3_ST_CW_FINISHED_A;
			s->init_num = 0;

			s->session->cipher = s->s3->tmp.new_cipher;
			if (!s->method->ssl3_enc->setup_key_block(s)) {
				ret = -1;
				goto end;
			}

			if (!s->method->ssl3_enc->change_cipher_state(s,
			    SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
				ret = -1;
				goto end;
			}

#ifndef OPENSSL_NO_SCTP
			if (s->hit) {
				/* Change to new shared key of SCTP-Auth,
				 * will be ignored if no SCTP used.
				 */
				BIO_ctrl(SSL_get_wbio(s),
				    BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
			}
#endif

			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
			break;

		case SSL3_ST_CW_FINISHED_A:
		case SSL3_ST_CW_FINISHED_B:
			if (!s->hit)
				dtls1_start_timer(s);
			ret = dtls1_send_finished(s,
			    SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
			    s->method->ssl3_enc->client_finished_label,
			    s->method->ssl3_enc->client_finished_label_len);
			if (ret <= 0)
				goto end;
			s->state = SSL3_ST_CW_FLUSH;

			/* clear flags */
			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
			if (s->hit) {
				s->s3->tmp.next_state = SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
				if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
					s->d1->next_state = s->s3->tmp.next_state;
					s->s3->tmp.next_state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
				}
#endif
				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED) {
					s->state = SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
					if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
						s->d1->next_state = SSL_ST_OK;
						s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
					}
#endif
					s->s3->flags |= SSL3_FLAGS_POP_BUFFER;
					s->s3->delay_buf_pop_ret = 0;
				}
			} else {
#ifndef OPENSSL_NO_SCTP
				/* Change to new shared key of SCTP-Auth,
				 * will be ignored if no SCTP used.
				 */
				BIO_ctrl(SSL_get_wbio(s),
				    BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
#endif

				/* Allow NewSessionTicket if ticket expected */
				if (s->tlsext_ticket_expected)
					s->s3->tmp.next_state =
					    SSL3_ST_CR_SESSION_TICKET_A;
				else
					s->s3->tmp.next_state =
					    SSL3_ST_CR_FINISHED_A;
			}
			s->init_num = 0;
			break;

		case SSL3_ST_CR_SESSION_TICKET_A:
		case SSL3_ST_CR_SESSION_TICKET_B:
			ret = ssl3_get_new_session_ticket(s);
			if (ret <= 0)
				goto end;
			s->state = SSL3_ST_CR_FINISHED_A;
			s->init_num = 0;
			break;

		case SSL3_ST_CR_CERT_STATUS_A:
		case SSL3_ST_CR_CERT_STATUS_B:
			ret = ssl3_get_cert_status(s);
			if (ret <= 0)
				goto end;
			s->state = SSL3_ST_CR_KEY_EXCH_A;
			s->init_num = 0;
			break;

		case SSL3_ST_CR_FINISHED_A:
		case SSL3_ST_CR_FINISHED_B:
			s->d1->change_cipher_spec_ok = 1;
			ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A,
			    SSL3_ST_CR_FINISHED_B);
			if (ret <= 0)
				goto end;
			dtls1_stop_timer(s);

			if (s->hit)
				s->state = SSL3_ST_CW_CHANGE_A;
			else
				s->state = SSL_ST_OK;

#ifndef OPENSSL_NO_SCTP
			if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
			    state == SSL_ST_RENEGOTIATE) {
				s->d1->next_state = s->state;
				s->state = DTLS1_SCTP_ST_CW_WRITE_SOCK;
			}
#endif

			s->init_num = 0;
			break;

		case SSL3_ST_CW_FLUSH:
			s->rwstate = SSL_WRITING;
			if (BIO_flush(s->wbio) <= 0) {
				/* If the write error was fatal, stop trying */
				if (!BIO_should_retry(s->wbio)) {
					s->rwstate = SSL_NOTHING;
					s->state = s->s3->tmp.next_state;
				}

				ret = -1;
				goto end;
			}
			s->rwstate = SSL_NOTHING;
			s->state = s->s3->tmp.next_state;
			break;

		case SSL_ST_OK:
			/* clean a few things up */
			ssl3_cleanup_key_block(s);

			/* If we are not 'joining' the last two packets,
			 * remove the buffering now */
			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
				ssl_free_wbio_buffer(s);
			/* else do it later in ssl3_write */

			s->init_num = 0;
			s->renegotiate = 0;
			s->new_session = 0;

			ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
			if (s->hit)
				s->ctx->stats.sess_hit++;

			ret = 1;
			/* s->server=0; */
			s->handshake_func = dtls1_connect;
			s->ctx->stats.sess_connect_good++;

			if (cb != NULL)
				cb(s, SSL_CB_HANDSHAKE_DONE, 1);

			/* done with handshaking */
			s->d1->handshake_read_seq = 0;
			s->d1->next_handshake_write_seq = 0;
			goto end;
			/* break; */

		default:
			SSLerr(SSL_F_DTLS1_CONNECT, SSL_R_UNKNOWN_STATE);
			ret = -1;
			goto end;
			/* break; */
		}

		/* did we do anything */
		if (!s->s3->tmp.reuse_message && !skip) {
			if (s->debug) {
				if ((ret = BIO_flush(s->wbio)) <= 0)
					goto end;
			}

			if ((cb != NULL) && (s->state != state)) {
				new_state = s->state;
				s->state = state;
				cb(s, SSL_CB_CONNECT_LOOP, 1);
				s->state = new_state;
			}
		}
		skip = 0;
	}
end:
	s->in_handshake--;

#ifndef OPENSSL_NO_SCTP
	/* Notify SCTP BIO socket to leave handshake
	 * mode and allow stream identifier other
	 * than 0. Will be ignored if no SCTP is used.
	 */
	BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
	    s->in_handshake, NULL);
#endif

	if (buf != NULL)
		BUF_MEM_free(buf);
	if (cb != NULL)
		cb(s, SSL_CB_CONNECT_EXIT, ret);
	return (ret);
}
Example #10
0
static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr)
{
    BIO_ZLIB_CTX *ctx;
    int ret, *ip;
    int ibs, obs;
    if (!b->next_bio)
        return 0;
    ctx = (BIO_ZLIB_CTX *) b->ptr;
    switch (cmd) {

    case BIO_CTRL_RESET:
        ctx->ocount = 0;
        ctx->odone = 0;
        ret = 1;
        break;

    case BIO_CTRL_FLUSH:
        ret = bio_zlib_flush(b);
        if (ret > 0)
            ret = BIO_flush(b->next_bio);
        break;

    case BIO_C_SET_BUFF_SIZE:
        ibs = -1;
        obs = -1;
        if (ptr != NULL) {
            ip = ptr;
            if (*ip == 0)
                ibs = (int)num;
            else
                obs = (int)num;
        } else {
            ibs = (int)num;
            obs = ibs;
        }

        if (ibs != -1) {
            if (ctx->ibuf) {
                OPENSSL_free(ctx->ibuf);
                ctx->ibuf = NULL;
            }
            ctx->ibufsize = ibs;
        }

        if (obs != -1) {
            if (ctx->obuf) {
                OPENSSL_free(ctx->obuf);
                ctx->obuf = NULL;
            }
            ctx->obufsize = obs;
        }
        ret = 1;
        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;

    default:
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;

    }

    return ret;
}
int MAIN(int argc, char **argv)
	{
#ifndef OPENSSL_NO_ENGINE
	ENGINE *e = NULL;
#endif
	int i, r, ret = 1;
	int badopt;
	char *outfile = NULL;
	char *inrand = NULL;
	int base64 = 0;
	int hex = 0;
	BIO *out = NULL;
	int num = -1;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif

	apps_startup();

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

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

	badopt = 0;
	i = 0;
	while (!badopt && argv[++i] != NULL)
		{
		if (TINYCLR_SSL_STRCMP(argv[i], "-out") == 0)
			{
			if ((argv[i+1] != NULL) && (outfile == NULL))
				outfile = argv[++i];
			else
				badopt = 1;
			}
#ifndef OPENSSL_NO_ENGINE
		else if (TINYCLR_SSL_STRCMP(argv[i], "-engine") == 0)
			{
			if ((argv[i+1] != NULL) && (engine == NULL))
				engine = argv[++i];
			else
				badopt = 1;
			}
#endif
		else if (TINYCLR_SSL_STRCMP(argv[i], "-rand") == 0)
			{
			if ((argv[i+1] != NULL) && (inrand == NULL))
				inrand = argv[++i];
			else
				badopt = 1;
			}
		else if (TINYCLR_SSL_STRCMP(argv[i], "-base64") == 0)
			{
			if (!base64)
				base64 = 1;
			else
				badopt = 1;
			}
		else if (TINYCLR_SSL_STRCMP(argv[i], "-hex") == 0)
			{
			if (!hex)
				hex = 1;
			else
				badopt = 1;
			}
		else if (isdigit((unsigned char)argv[i][0]))
			{
			if (num < 0)
				{
				r = sscanf(argv[i], "%d", &num);
				if (r == 0 || num < 0)
					badopt = 1;
				}
			else
				badopt = 1;
			}
		else
			badopt = 1;
		}

	if (hex && base64)
		badopt = 1;

	if (num < 0)
		badopt = 1;
	
	if (badopt) 
		{
		BIO_printf(bio_err, "Usage: rand [options] num\n");
		BIO_printf(bio_err, "where options are\n");
		BIO_printf(bio_err, "-out file             - write to file\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err, "-engine e             - use engine e, possibly a hardware device.\n");
#endif
		BIO_printf(bio_err, "-rand file%cfile%c... - seed PRNG from files\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err, "-base64               - base64 encode output\n");
		BIO_printf(bio_err, "-hex                  - hex encode output\n");
		goto err;
		}

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

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

	out = BIO_new(BIO_s_file());
	if (out == NULL)
		goto err;
	if (outfile != NULL)
		r = BIO_write_filename(out, outfile);
	else
		{
		r = BIO_set_fp(out, OPENSSL_TYPE__FILE_STDOUT, BIO_NOCLOSE | BIO_FP_TEXT);
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	if (r <= 0)
		goto err;

	if (base64)
		{
		BIO *b64 = BIO_new(BIO_f_base64());
		if (b64 == NULL)
			goto err;
		out = BIO_push(b64, out);
		}
	
	while (num > 0) 
		{
		unsigned char buf[4096];
		int chunk;

		chunk = num;
		if (chunk > (int)sizeof(buf))
			chunk = sizeof buf;
		r = RAND_bytes(buf, chunk);
		if (r <= 0)
			goto err;
		if (!hex) 
			BIO_write(out, buf, chunk);
		else
			{
			for (i = 0; i < chunk; i++)
				BIO_printf(out, "%02x", buf[i]);
			}
		num -= chunk;
		}
	if (hex)
		BIO_puts(out, "\n");
	(void)BIO_flush(out);

	app_RAND_write_file(NULL, bio_err);
	ret = 0;
	
err:
	ERR_print_errors(bio_err);
	if (out)
		BIO_free_all(out);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Example #12
0
int dtls1_accept(SSL *s)
{
    void (*cb)(const SSL *ssl, int type, int val) = NULL;
    unsigned long alg_k;
    int ret = -1;
    int new_state, state, skip = 0;
    int listen;

    ERR_clear_error();
    errno = 0;

    if (s->info_callback != NULL)
        cb = s->info_callback;
    else if (s->ctx->info_callback != NULL)
        cb = s->ctx->info_callback;

    listen = s->d1->listen;

    /* init things to blank */
    s->in_handshake++;
    if (!SSL_in_init(s) || SSL_in_before(s))
        SSL_clear(s);

    s->d1->listen = listen;

    if (s->cert == NULL) {
        SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_NO_CERTIFICATE_SET);
        return (-1);
    }

    for (;;) {
        state = s->state;

        switch (s->state) {
            case SSL_ST_RENEGOTIATE:
                s->renegotiate = 1;
            /* s->state=SSL_ST_ACCEPT; */

            case SSL_ST_BEFORE:
            case SSL_ST_ACCEPT:
            case SSL_ST_BEFORE | SSL_ST_ACCEPT:
            case SSL_ST_OK | SSL_ST_ACCEPT:

                s->server = 1;
                if (cb != NULL)
                    cb(s, SSL_CB_HANDSHAKE_START, 1);

                if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
                    SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
                    return -1;
                }
                s->type = SSL_ST_ACCEPT;

                if (s->init_buf == NULL) {
                    BUF_MEM *buf;
                    if ((buf = BUF_MEM_new()) == NULL) {
                        ret = -1;
                        s->state = SSL_ST_ERR;
                        goto end;
                    }
                    if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
                        BUF_MEM_free(buf);
                        ret = -1;
                        s->state = SSL_ST_ERR;
                        goto end;
                    }
                    s->init_buf = buf;
                }

                if (!ssl3_setup_buffers(s)) {
                    ret = -1;
                    s->state = SSL_ST_ERR;
                    goto end;
                }

                s->init_num = 0;
                s->d1->change_cipher_spec_ok = 0;
                /* Should have been reset by ssl3_get_finished, too. */
                s->s3->change_cipher_spec = 0;

                if (s->state != SSL_ST_RENEGOTIATE) {
                    /*
                     * Ok, we now need to push on a buffering BIO so that
                     * the output is sent in a way that TCP likes :-)
                     * ...but not with SCTP :-)
                     */
                    if (!ssl_init_wbio_buffer(s, 1)) {
                        ret = -1;
                        s->state = SSL_ST_ERR;
                        goto end;
                    }

                    tls1_init_finished_mac(s);
                    s->state = SSL3_ST_SR_CLNT_HELLO_A;
                    s->ctx->stats.sess_accept++;
                } else if (!s->s3->send_connection_binding) {
                    /*
                     * Server attempting to renegotiate with client that doesn't
                     * support secure renegotiation.
                     */
                    SSLerr(SSL_F_DTLS1_ACCEPT,
                           SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
                    ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
                    ret = -1;
                    s->state = SSL_ST_ERR;
                    goto end;
                } else {
                    /* s->state == SSL_ST_RENEGOTIATE,
                     * we will just send a HelloRequest */
                    s->ctx->stats.sess_accept_renegotiate++;
                    s->state = SSL3_ST_SW_HELLO_REQ_A;
                }

                break;

            case SSL3_ST_SW_HELLO_REQ_A:
            case SSL3_ST_SW_HELLO_REQ_B:

                s->shutdown = 0;
                dtls1_clear_sent_buffer(s);
                dtls1_start_timer(s);
                ret = ssl3_send_hello_request(s);
                if (ret <= 0)
                    goto end;
                s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A;
                s->state = SSL3_ST_SW_FLUSH;
                s->init_num = 0;

                tls1_init_finished_mac(s);
                break;

            case SSL3_ST_SW_HELLO_REQ_C:
                s->state = SSL_ST_OK;
                break;

            case SSL3_ST_SR_CLNT_HELLO_A:
            case SSL3_ST_SR_CLNT_HELLO_B:
            case SSL3_ST_SR_CLNT_HELLO_C:

                s->shutdown = 0;
                ret = ssl3_get_client_hello(s);
                if (ret <= 0)
                    goto end;
                dtls1_stop_timer(s);

                if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
                    s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
                else
                    s->state = SSL3_ST_SW_SRVR_HELLO_A;

                s->init_num = 0;

                /* Reflect ClientHello sequence to remain stateless while listening */
                if (listen) {
                    memcpy(s->s3->write_sequence, s->s3->read_sequence,
                           sizeof(s->s3->write_sequence));
                }

                /* If we're just listening, stop here */
                if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A) {
                    ret = 2;
                    s->d1->listen = 0;
                    /*
                     * Set expected sequence numbers
                     * to continue the handshake.
                     */
                    s->d1->handshake_read_seq = 2;
                    s->d1->handshake_write_seq = 1;
                    s->d1->next_handshake_write_seq = 1;
                    goto end;
                }

                break;

            case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
            case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:

                ret = dtls1_send_hello_verify_request(s);
                if (ret <= 0)
                    goto end;
                s->state = SSL3_ST_SW_FLUSH;
                s->s3->tmp.next_state = SSL3_ST_SR_CLNT_HELLO_A;

                /* HelloVerifyRequest resets Finished MAC */
                tls1_init_finished_mac(s);
                break;


            case SSL3_ST_SW_SRVR_HELLO_A:
            case SSL3_ST_SW_SRVR_HELLO_B:
                s->renegotiate = 2;
                dtls1_start_timer(s);
                ret = ssl3_send_server_hello(s);
                if (ret <= 0)
                    goto end;

                if (s->hit) {
                    if (s->tlsext_ticket_expected)
                        s->state = SSL3_ST_SW_SESSION_TICKET_A;
                    else
                        s->state = SSL3_ST_SW_CHANGE_A;
                } else
                    s->state = SSL3_ST_SW_CERT_A;
                s->init_num = 0;
                break;

            case SSL3_ST_SW_CERT_A:
            case SSL3_ST_SW_CERT_B:
                /* Check if it is anon DH. */
                if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)) {
                    dtls1_start_timer(s);
                    ret = ssl3_send_server_certificate(s);
                    if (ret <= 0)
                        goto end;
                    if (s->tlsext_status_expected)
                        s->state = SSL3_ST_SW_CERT_STATUS_A;
                    else
                        s->state = SSL3_ST_SW_KEY_EXCH_A;
                } else {
                    skip = 1;
                    s->state = SSL3_ST_SW_KEY_EXCH_A;
                }
                s->init_num = 0;
                break;

            case SSL3_ST_SW_KEY_EXCH_A:
            case SSL3_ST_SW_KEY_EXCH_B:
                alg_k = s->s3->tmp.new_cipher->algorithm_mkey;

                /* only send if a DH key exchange */
                if (alg_k & (SSL_kDHE | SSL_kECDHE)) {
                    dtls1_start_timer(s);
                    ret = ssl3_send_server_key_exchange(s);
                    if (ret <= 0)
                        goto end;
                } else
                    skip = 1;

                s->state = SSL3_ST_SW_CERT_REQ_A;
                s->init_num = 0;
                break;

            case SSL3_ST_SW_CERT_REQ_A:
            case SSL3_ST_SW_CERT_REQ_B:
                /*
                 * Determine whether or not we need to request a
                 * certificate.
                 *
                 * Do not request a certificate if:
                 *
                 * - We did not ask for it (SSL_VERIFY_PEER is unset).
                 *
                 * - SSL_VERIFY_CLIENT_ONCE is set and we are
                 *   renegotiating.
                 *
                 * - We are using an anonymous ciphersuites
                 *   (see section "Certificate request" in SSL 3 drafts
                 *   and in RFC 2246) ... except when the application
                 *   insists on verification (against the specs, but
                 *   s3_clnt.c accepts this for SSL 3).
                 */
                if (!(s->verify_mode & SSL_VERIFY_PEER) ||
                    ((s->session->peer != NULL) &&
                    (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
                    ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
                    !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))
                {
                    /* no cert request */
                    skip = 1;
                    s->s3->tmp.cert_request = 0;
                    s->state = SSL3_ST_SW_SRVR_DONE_A;
                } else {
                    s->s3->tmp.cert_request = 1;
                    dtls1_start_timer(s);
                    ret = ssl3_send_certificate_request(s);
                    if (ret <= 0)
                        goto end;
                    s->state = SSL3_ST_SW_SRVR_DONE_A;
                    s->init_num = 0;
                }
                break;

            case SSL3_ST_SW_SRVR_DONE_A:
            case SSL3_ST_SW_SRVR_DONE_B:
                dtls1_start_timer(s);
                ret = ssl3_send_server_done(s);
                if (ret <= 0)
                    goto end;
                s->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
                s->state = SSL3_ST_SW_FLUSH;
                s->init_num = 0;
                break;

            case SSL3_ST_SW_FLUSH:
                s->rwstate = SSL_WRITING;
                if (BIO_flush(s->wbio) <= 0) {
                    /* If the write error was fatal, stop trying */
                    if (!BIO_should_retry(s->wbio)) {
                        s->rwstate = SSL_NOTHING;
                        s->state = s->s3->tmp.next_state;
                    }

                    ret = -1;
                    goto end;
                }
                s->rwstate = SSL_NOTHING;
                s->state = s->s3->tmp.next_state;
                break;

            case SSL3_ST_SR_CERT_A:
            case SSL3_ST_SR_CERT_B:
                if (s->s3->tmp.cert_request) {
                    ret = ssl3_get_client_certificate(s);
                    if (ret <= 0)
                        goto end;
                }
                s->init_num = 0;
                s->state = SSL3_ST_SR_KEY_EXCH_A;
                break;

            case SSL3_ST_SR_KEY_EXCH_A:
            case SSL3_ST_SR_KEY_EXCH_B:
                ret = ssl3_get_client_key_exchange(s);
                if (ret <= 0)
                    goto end;

                s->state = SSL3_ST_SR_CERT_VRFY_A;
                s->init_num = 0;

                if (ret == 2) {
                    /* For the ECDH ciphersuites when
                     * the client sends its ECDH pub key in
                     * a certificate, the CertificateVerify
                     * message is not sent.
                     */
                    s->state = SSL3_ST_SR_FINISHED_A;
                    s->init_num = 0;
                } else if (SSL_USE_SIGALGS(s)) {
                    s->state = SSL3_ST_SR_CERT_VRFY_A;
                    s->init_num = 0;
                    if (!s->session->peer)
                        break;
                    /*
                     * For sigalgs freeze the handshake buffer
                     * at this point and digest cached records.
                     */
                    if (!s->s3->handshake_buffer) {
                        SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
                        s->state = SSL_ST_ERR;
                        return -1;
                    }
                    s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
                    if (!tls1_digest_cached_records(s)) {
                        s->state = SSL_ST_ERR;
                        return -1;
                    }
                } else {
                    s->state = SSL3_ST_SR_CERT_VRFY_A;
                    s->init_num = 0;

                    /* We need to get hashes here so if there is
                     * a client cert, it can be verified */
                    s->method->ssl3_enc->cert_verify_mac(s, NID_md5,
                                                         &(s->s3->tmp.cert_verify_md[0]));
                    s->method->ssl3_enc->cert_verify_mac(
                        s, NID_sha1, &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
                }
                break;

            case SSL3_ST_SR_CERT_VRFY_A:
            case SSL3_ST_SR_CERT_VRFY_B:
                ret = ssl3_get_cert_verify(s);
                if (ret <= 0)
                    goto end;
                s->state = SSL3_ST_SR_FINISHED_A;
                s->init_num = 0;
                break;

            case SSL3_ST_SR_FINISHED_A:
            case SSL3_ST_SR_FINISHED_B:
                /*
                 * Enable CCS. Receiving a CCS clears the flag, so make
                 * sure not to re-enable it to ban duplicates. This *should* be the
                 * first time we have received one - but we check anyway to be
                 * cautious.
                 * s->s3->change_cipher_spec is set when a CCS is
                 * processed in d1_pkt.c, and remains set until
                 * the client's Finished message is read.
                 */
                if (!s->s3->change_cipher_spec)
                    s->d1->change_cipher_spec_ok = 1;
                ret = ssl3_get_finished(s, SSL3_ST_SR_FINISHED_A, SSL3_ST_SR_FINISHED_B);
                if (ret <= 0)
                    goto end;
                dtls1_stop_timer(s);
                if (s->hit)
                    s->state = SSL_ST_OK;
                else if (s->tlsext_ticket_expected)
                    s->state = SSL3_ST_SW_SESSION_TICKET_A;
                else
                    s->state = SSL3_ST_SW_CHANGE_A;
                s->init_num = 0;
                break;

            case SSL3_ST_SW_SESSION_TICKET_A:
            case SSL3_ST_SW_SESSION_TICKET_B:
                ret = ssl3_send_newsession_ticket(s);
                if (ret <= 0)
                    goto end;
                s->state = SSL3_ST_SW_CHANGE_A;
                s->init_num = 0;
                break;

            case SSL3_ST_SW_CERT_STATUS_A:
            case SSL3_ST_SW_CERT_STATUS_B:
                ret = ssl3_send_cert_status(s);
                if (ret <= 0)
                    goto end;
                s->state = SSL3_ST_SW_KEY_EXCH_A;
                s->init_num = 0;
                break;

            case SSL3_ST_SW_CHANGE_A:
            case SSL3_ST_SW_CHANGE_B:

                s->session->cipher = s->s3->tmp.new_cipher;
                if (!s->method->ssl3_enc->setup_key_block(s)) {
                    ret = -1;
                    s->state = SSL_ST_ERR;
                    goto end;
                }

                ret = dtls1_send_change_cipher_spec(s, SSL3_ST_SW_CHANGE_A,
                                                    SSL3_ST_SW_CHANGE_B);

                if (ret <= 0)
                    goto end;


                s->state = SSL3_ST_SW_FINISHED_A;
                s->init_num = 0;

                if (!s->method->ssl3_enc->change_cipher_state(s,
                        SSL3_CHANGE_CIPHER_SERVER_WRITE))
                {
                    ret = -1;
                    s->state = SSL_ST_ERR;
                    goto end;
                }

                dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
                break;

            case SSL3_ST_SW_FINISHED_A:
            case SSL3_ST_SW_FINISHED_B:
                ret = ssl3_send_finished(s, SSL3_ST_SW_FINISHED_A, SSL3_ST_SW_FINISHED_B,
                                         s->method->ssl3_enc->server_finished_label,
                                         s->method->ssl3_enc->server_finished_label_len);
                if (ret <= 0)
                    goto end;
                s->state = SSL3_ST_SW_FLUSH;
                if (s->hit) {
                    s->s3->tmp.next_state = SSL3_ST_SR_FINISHED_A;

                } else {
                    s->s3->tmp.next_state = SSL_ST_OK;
                }
                s->init_num = 0;
                break;

            case SSL_ST_OK:
                /* clean a few things up */
                ssl3_cleanup_key_block(s);

                /* remove buffering on output */
                ssl_free_wbio_buffer(s);

                s->init_num = 0;

                if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
                {
                    s->renegotiate = 0;
                    s->new_session = 0;

                    ssl_update_cache(s, SSL_SESS_CACHE_SERVER);

                    s->ctx->stats.sess_accept_good++;
                    /* s->server=1; */
                    s->handshake_func = dtls1_accept;

                    if (cb != NULL)
                        cb(s, SSL_CB_HANDSHAKE_DONE, 1);
                }

                ret = 1;

                /* done handshaking, next message is client hello */
                s->d1->handshake_read_seq = 0;
                /* next message is server hello */
                s->d1->handshake_write_seq = 0;
                s->d1->next_handshake_write_seq = 0;
                dtls1_clear_received_buffer(s);
                goto end;
            /* break; */

            case SSL_ST_ERR:
            default:
                SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_UNKNOWN_STATE);
                ret = -1;
                goto end;
                /* break; */
        }

        if (!s->s3->tmp.reuse_message && !skip) {
            if (s->debug) {
                if ((ret = BIO_flush(s->wbio)) <= 0)
                    goto end;
            }

            if ((cb != NULL) && (s->state != state)) {
                new_state = s->state;
                s->state = state;
                cb(s, SSL_CB_ACCEPT_LOOP, 1);
                s->state = new_state;
            }
        }
        skip = 0;
    }
end:
    /* BIO_flush(s->wbio); */

    s->in_handshake--;

    if (cb != NULL)
        cb(s, SSL_CB_ACCEPT_EXIT, ret);
    return ret;
}
Example #13
0
void
output_cert_info(X509 *cert, gf_io_t pc)
{
    char    buf[256];
    STORE_S *left,*right;
    gf_io_t spc;
    int len;
        
    left = so_get(CharStar, NULL, EDIT_ACCESS);
    right = so_get(CharStar, NULL, EDIT_ACCESS);
    if(!(left && right))
      return;

    gf_set_so_writec(&spc, left);

    if(!cert->cert_info){
    	gf_puts("Couldn't find certificate info.", spc);
	gf_puts(NEWLINE, spc);
    }
    else{
	gf_puts_uline("Subject (whose certificate it is)", spc);
	gf_puts(NEWLINE, spc);

	output_X509_NAME(cert->cert_info->subject, spc);
	gf_puts(NEWLINE, spc);

	gf_puts_uline("Serial Number", spc);
	gf_puts(NEWLINE, spc);

	snprintf(buf, sizeof(buf), "%ld", ASN1_INTEGER_get(cert->cert_info->serialNumber));
	gf_puts(buf, spc);
	gf_puts(NEWLINE, spc);
	gf_puts(NEWLINE, spc);

	gf_puts_uline("Validity", spc);
	gf_puts(NEWLINE, spc);
    	{
    	    BIO *mb = BIO_new(BIO_s_mem());
	    char iobuf[4096];
	    
	    gf_puts("Not Before: ", spc);

	    (void) BIO_reset(mb);
	    ASN1_UTCTIME_print(mb, cert->cert_info->validity->notBefore);
	    (void) BIO_flush(mb);
	    while((len = BIO_read(mb, iobuf, sizeof(iobuf))) > 0)
	      gf_nputs(iobuf, len, spc);

	    gf_puts(NEWLINE, spc);

	    gf_puts("Not After:  ", spc);

	    (void) BIO_reset(mb);
	    ASN1_UTCTIME_print(mb, cert->cert_info->validity->notAfter);
	    (void) BIO_flush(mb);
	    while((len = BIO_read(mb, iobuf, sizeof(iobuf))) > 0)
	      gf_nputs(iobuf, len, spc);
    	    
	    gf_puts(NEWLINE, spc);
	    gf_puts(NEWLINE, spc);
	    	    
	    BIO_free(mb);
	}
    }

    gf_clear_so_writec(left);

    gf_set_so_writec(&spc, right);

    if(!cert->cert_info){
    	gf_puts(_("Couldn't find certificate info."), spc);
	gf_puts(NEWLINE, spc);
    }
    else{
	gf_puts_uline("Issuer", spc);
	gf_puts(NEWLINE, spc);

	output_X509_NAME(cert->cert_info->issuer, spc);
	gf_puts(NEWLINE, spc);
    }
    
    gf_clear_so_writec(right);
    
    side_by_side(left, right, pc);

    gf_puts_uline("SHA1 Fingerprint", pc);
    gf_puts(NEWLINE, pc);
    get_fingerprint(cert, EVP_sha1(), buf, sizeof(buf));
    gf_puts(buf, pc);
    gf_puts(NEWLINE, pc);

    gf_puts_uline("MD5 Fingerprint", pc);
    gf_puts(NEWLINE, pc);
    get_fingerprint(cert, EVP_md5(), buf, sizeof(buf));
    gf_puts(buf, pc);
    gf_puts(NEWLINE, pc);
    
    so_give(&left);
    so_give(&right);
}
Example #14
0
int dane_verify(SSL *con, char *s_host, short s_port) {
	struct ub_result *dns_result;
	struct ub_ctx* ctx;
	char dns_name[256];
	int retval;
	
	if (b_err == NULL)
		b_err=BIO_new_fp(stderr,BIO_NOCLOSE);
	BIO_printf(b_err, "DANE:%s:%d\n", s_host, s_port);
	
	int peerfd;
	peerfd = SSL_get_fd(con);
	socklen_t len;
	struct sockaddr_storage addr;
	char ipstr[INET6_ADDRSTRLEN];
	char node[NI_MAXHOST];
	int port;

	len = sizeof addr;
	getpeername(peerfd, (struct sockaddr*)&addr, &len);

	// deal with both IPv4 and IPv6:
	if (addr.ss_family == AF_INET) {
	    struct sockaddr_in *s = (struct sockaddr_in *)&addr;
	    port = ntohs(s->sin_port);
	    inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
		struct sockaddr_in sa;
		sa.sin_family = AF_INET;
		inet_pton(AF_INET, ipstr, &sa.sin_addr);
		int res = getnameinfo((struct sockaddr*)&sa, sizeof(sa), node, sizeof(node), NULL, 0, 0);
	} else { // AF_INET6
		struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
	    port = ntohs(s->sin6_port);
	    inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
	}

	BIO_printf(b_err, "Peer IP address: %s\n", ipstr);
	BIO_printf(b_err, "Peer port      : %d\n", port);
	BIO_printf(b_err, "Peer hostname  : %s\n", node);
	
	ctx = ub_ctx_create();
	if(!ctx) {
		printf("error: could not create unbound context\n");
		return -1;
	}
	if( (retval=ub_ctx_resolvconf(ctx, "/etc/resolv.conf")) != 0) {
		printf("error reading resolv.conf: %s. errno says: %s\n", 
			ub_strerror(retval), strerror(errno));
		return -1;
	}
	if( (retval=ub_ctx_hosts(ctx, "/etc/hosts")) != 0) {
		printf("error reading hosts: %s. errno says: %s\n", 
			ub_strerror(retval), strerror(errno));
		return -1;
	}
	
	retval = sprintf(dns_name, "_%d._tcp.%s", s_port, s_host );
	if(retval < 0) {
		printf("failure to create dns name\n");
		return -1;
	}
	BIO_printf(b_err,"DANE:dns name: %s\n", dns_name);
	retval = ub_resolve(ctx, dns_name, 65534, 1, &dns_result);
	if(retval != 0) {
		printf("resolve error: %s\n", ub_strerror(retval));
		return -1;
	}
	
	if(dns_result->havedata) {
		int i;
		for (i = 0; dns_result->data[i] != NULL; i++) {
			unsigned char usage, selector, matching_type;
			unsigned char *tlsa_bytes;
			
			if (dns_result->len[i] < 35) {
				// must have at least 1+1+1+32 bytes for the SHA-256 case
				BIO_printf(b_err, "DANE: Not enough data: %d available\n",
					dns_result->len[i]);
				return -1;
			}
			unsigned char *rdata = (unsigned char *)dns_result->data[i];
			usage = (char) *rdata++;
			selector = (char) *rdata++;
			matching_type = (char) *rdata++;
			tlsa_bytes = (unsigned char *)rdata;
			X509 *tlsa_cert;
			tlsa_cert = d2i_X509(NULL, &tlsa_bytes, dns_result->len[i]-3);
			
			BIO_printf(b_err, "DANE: Usage %d Selector %d Matching Type %d\n",
				usage, selector, matching_type);
			
			if (selector != 0)
				continue;
			if (matching_type != 0)
				continue;
			
			if (usage == 0 || usage == 2) {
				int retval;
				retval = ca_constraint(con, tlsa_cert, usage);
				return retval;
			}
			if (usage == 1) {
				X509 *cert = NULL;
				cert = SSL_get_peer_certificate(con);
				int retval;
				retval = service_cert_constraint(cert, tlsa_cert);
				if (retval == 0)
					BIO_printf(b_err, "DANE: Passed validation for usage 1\n");
				else
					BIO_printf(b_err, "DANE: Failed validation for usage 1\n");
				return retval;
			}
		}
	} else
		return 0;

	(void)BIO_flush(b_err);
	return 0;
}
Example #15
0
File: tlsIO.c Project: fahkri/tls
static int
TlsOutputProc(ClientData instanceData,	/* Socket state. */
              CONST char *buf,		/* The data buffer. */
              int toWrite,		/* How many bytes to write? */
              int *errorCodePtr)	/* Where to store error code. */
{
    State *statePtr = (State *) instanceData;
    int written, err;

    *errorCodePtr = 0;

    dprintf(stderr,"\nBIO_write(0x%x, %d)", (unsigned int) statePtr, toWrite);

    if (statePtr->flags & TLS_TCL_CALLBACK) {
       /* don't process any bytes while verify callback is running */
       written = -1;
       *errorCodePtr = EAGAIN;
       goto output;
    }

    if (!SSL_is_init_finished(statePtr->ssl)) {
	written = Tls_WaitForConnect(statePtr, errorCodePtr);
	if (written <= 0) {
	    goto output;
	}
    }
    if (statePtr->flags & TLS_TCL_INIT) {
	statePtr->flags &= ~(TLS_TCL_INIT);
    }
    if (toWrite == 0) {
	dprintf(stderr, "zero-write\n");
	BIO_flush(statePtr->bio);
	written = 0;
	goto output;
    } else {
	/*
	 * We need to clear the SSL error stack now because we sometimes reach
	 * this function with leftover errors in the stack.  If BIO_write
	 * returns -1 and intends EAGAIN, there is a leftover error, it will be
	 * misconstrued as an error, not EAGAIN.
	 *
	 * Alternatively, we may want to handle the <0 return codes from
	 * BIO_write specially (as advised in the RSA docs).  TLS's lower level
	 * BIO functions play with the retry flags though, and this seems to
	 * work correctly.  Similar fix in TlsInputProc. - hobbs
	 */
	ERR_clear_error();
	written = BIO_write(statePtr->bio, buf, toWrite);
	dprintf(stderr,"\nBIO_write(0x%x, %d) -> [%d]",
		(unsigned int) statePtr, toWrite, written);
    }
    if (written <= 0) {
	switch ((err = SSL_get_error(statePtr->ssl, written))) {
	    case SSL_ERROR_NONE:
		if (written < 0) {
		    written = 0;
		}
		break;
	    case SSL_ERROR_WANT_WRITE:
		dprintf(stderr," write W BLOCK");
		break;
	    case SSL_ERROR_WANT_READ:
		dprintf(stderr," write R BLOCK");
		break;
	    case SSL_ERROR_WANT_X509_LOOKUP:
		dprintf(stderr," write X BLOCK");
		break;
	    case SSL_ERROR_ZERO_RETURN:
		dprintf(stderr," closed\n");
		written = 0;
		break;
	    case SSL_ERROR_SYSCALL:
		*errorCodePtr = Tcl_GetErrno();
		dprintf(stderr," [%d] syscall errr: %d",
			written, *errorCodePtr);
		written = -1;
		break;
	    case SSL_ERROR_SSL:
		Tls_Error(statePtr, SSL_ERROR(statePtr->ssl, written));
		*errorCodePtr = ECONNABORTED;
		written = -1;
		break;
	    default:
		dprintf(stderr," unknown err: %d\n", err);
		break;
	}
    }
    output:
    dprintf(stderr, "\nOutput(%d) -> %d", toWrite, written);
    return written;
}
Example #16
0
int main(int Argc, char *Argv[])
{
    ARGS arg;
#define PROG_NAME_SIZE  39
    char pname[PROG_NAME_SIZE + 1];
    FUNCTION f, *fp;
    MS_STATIC const char *prompt;
    MS_STATIC char buf[1024];
    char *to_free = NULL;
    int n, i, ret = 0;
    int argc;
    char **argv, *p;
    LHASH *prog = NULL;
    long errline;

    arg.data = NULL;
    arg.count = 0;

    in_FIPS_mode = 0;

    if (getenv("OPENSSL_FIPS")) {
#ifdef OPENSSL_FIPS
        if (!FIPS_mode_set(1)) {
            ERR_load_crypto_strings();
            ERR_print_errors(BIO_new_fp(stderr, BIO_NOCLOSE));
            EXIT(1);
        }
        in_FIPS_mode = 1;
#else
        fprintf(stderr, "FIPS mode not supported.\n");
        EXIT(1);
#endif
    }

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

    if (getenv("OPENSSL_DEBUG_MEMORY") != NULL) { /* if not defined, use
                                                   * compiled-in library
                                                   * defaults */
        if (!(0 == strcmp(getenv("OPENSSL_DEBUG_MEMORY"), "off"))) {
            CRYPTO_malloc_debug_init();
            CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
        } else {
            /* OPENSSL_DEBUG_MEMORY=off */
            CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
        }
    }
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

#if 0
    if (getenv("OPENSSL_DEBUG_LOCKING") != NULL)
#endif
    {
        CRYPTO_set_locking_callback(lock_dbg_cb);
    }

    apps_startup();

    /* Lets load up our environment a little */
    p = getenv("OPENSSL_CONF");
    if (p == NULL)
        p = getenv("SSLEAY_CONF");
    if (p == NULL)
        p = to_free = make_config_name();

    default_config_file = p;

    config = NCONF_new(NULL);
    i = NCONF_load(config, p, &errline);
    if (i == 0) {
        NCONF_free(config);
        config = NULL;
        ERR_clear_error();
    }

    prog = prog_init();

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

    f.name = pname;
    fp = (FUNCTION *) lh_retrieve(prog, &f);
    if (fp != NULL) {
        Argv[0] = pname;
        ret = fp->func(Argc, Argv);
        goto end;
    }

    /*
     * ok, now check that there are not arguments, if there are, run with
     * them, shifting the ssleay off the front
     */
    if (Argc != 1) {
        Argc--;
        Argv++;
        ret = do_cmd(prog, Argc, Argv);
        if (ret < 0)
            ret = 0;
        goto end;
    }

    /* ok, lets enter the old 'OpenSSL>' mode */

    for (;;) {
        ret = 0;
        p = buf;
        n = sizeof buf;
        i = 0;
        for (;;) {
            p[0] = '\0';
            if (i++)
                prompt = ">";
            else
                prompt = "OpenSSL> ";
            fputs(prompt, stdout);
            fflush(stdout);
            if (!fgets(p, n, stdin))
                goto end;
            if (p[0] == '\0')
                goto end;
            i = strlen(p);
            if (i <= 1)
                break;
            if (p[i - 2] != '\\')
                break;
            i -= 2;
            p += i;
            n -= i;
        }
        if (!chopup_args(&arg, buf, &argc, &argv))
            break;

        ret = do_cmd(prog, argc, argv);
        if (ret < 0) {
            ret = 0;
            goto end;
        }
        if (ret != 0)
            BIO_printf(bio_err, "error in %s\n", argv[0]);
        (void)BIO_flush(bio_err);
    }
    BIO_printf(bio_err, "bad exit\n");
    ret = 1;
 end:
    if (to_free)
        OPENSSL_free(to_free);
    if (config != NULL) {
        NCONF_free(config);
        config = NULL;
    }
    if (prog != NULL)
        lh_free(prog);
    if (arg.data != NULL)
        OPENSSL_free(arg.data);

    apps_shutdown();

    CRYPTO_mem_leaks(bio_err);
    if (bio_err != NULL) {
        BIO_free(bio_err);
        bio_err = NULL;
    }
    OPENSSL_EXIT(ret);
}
Example #17
0
int MAIN(int argc, char **argv)
	{
	static const char magic[]="Salted__";
	char mbuf[sizeof magic-1];
	char *strbuf=NULL;
	unsigned char *buff=NULL,*bufsize=NULL;
	int bsize=BSIZE,verbose=0;
	int ret=1,inl;
	int nopad = 0;
	unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
	unsigned char salt[PKCS5_SALT_LEN];
	char *str=NULL, *passarg = NULL, *pass = NULL;
	char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
	char *md=NULL;
	int enc=1,printkey=0,i,base64=0;
#ifdef ZLIB
	int do_zlib=0;
	BIO *bzl = NULL;
#endif
	int debug=0,olb64=0,nosalt=0;
	const EVP_CIPHER *cipher=NULL,*c;
	EVP_CIPHER_CTX *ctx = NULL;
	char *inf=NULL,*outf=NULL;
	BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL;
#define PROG_NAME_SIZE  39
	char pname[PROG_NAME_SIZE+1];
#ifndef OPENSSL_NO_ENGINE
	char *engine = NULL;
#endif
	const EVP_MD *dgst=NULL;
	int non_fips_allow = 0;

	apps_startup();

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

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

	/* first check the program name */
	program_name(argv[1],pname,sizeof pname);
	if (strcmp(pname,"base64") == 0)
		base64=1;
#ifdef ZLIB
	if (strcmp(pname,"zlib") == 0)
		do_zlib=1;
#endif

	cipher=EVP_get_cipherbyname(pname);
#ifdef ZLIB
	if (!do_zlib && !base64 && (cipher == NULL)
				&& (strcmp(pname,"enc") != 0))
#else
	if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0))
#endif
		{
		BIO_printf(bio_err,"%s is an unknown cipher\n",pname);
		goto bad;
		}

	argc -= 2;
	argv += 2;
	while (argc >= 1)
		{
		if	(strcmp(*argv,"-e") == 0)
			enc=1;
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			inf= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outf= *(++argv);
			}
		else if (strcmp(*argv,"-pass") == 0)
			{
			if (--argc < 1) goto bad;
			passarg= *(++argv);
			}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
#endif
		else if	(strcmp(*argv,"-d") == 0)
			enc=0;
		else if	(strcmp(*argv,"-p") == 0)
			printkey=1;
		else if	(strcmp(*argv,"-v") == 0)
			verbose=1;
		else if	(strcmp(*argv,"-nopad") == 0)
			nopad=1;
		else if	(strcmp(*argv,"-salt") == 0)
			nosalt=0;
		else if	(strcmp(*argv,"-nosalt") == 0)
			nosalt=1;
		else if	(strcmp(*argv,"-debug") == 0)
			debug=1;
		else if	(strcmp(*argv,"-P") == 0)
			printkey=2;
		else if	(strcmp(*argv,"-A") == 0)
			olb64=1;
		else if	(strcmp(*argv,"-a") == 0)
			base64=1;
		else if	(strcmp(*argv,"-base64") == 0)
			base64=1;
#ifdef ZLIB
		else if	(strcmp(*argv,"-z") == 0)
			do_zlib=1;
#endif
		else if (strcmp(*argv,"-bufsize") == 0)
			{
			if (--argc < 1) goto bad;
			bufsize=(unsigned char *)*(++argv);
			}
		else if (strcmp(*argv,"-k") == 0)
			{
			if (--argc < 1) goto bad;
			str= *(++argv);
			}
		else if (strcmp(*argv,"-kfile") == 0)
			{
			static char buf[128];
			FILE *infile;
			char *file;

			if (--argc < 1) goto bad;
			file= *(++argv);
			infile=fopen(file,"r");
			if (infile == NULL)
				{
				BIO_printf(bio_err,"unable to read key from '%s'\n",
					file);
				goto bad;
				}
			buf[0]='\0';
			if (!fgets(buf,sizeof buf,infile))
				{
				BIO_printf(bio_err,"unable to read key from '%s'\n",
					file);
				goto bad;
				}
			fclose(infile);
			i=strlen(buf);
			if ((i > 0) &&
				((buf[i-1] == '\n') || (buf[i-1] == '\r')))
				buf[--i]='\0';
			if ((i > 0) &&
				((buf[i-1] == '\n') || (buf[i-1] == '\r')))
				buf[--i]='\0';
			if (i < 1)
				{
				BIO_printf(bio_err,"zero length password\n");
				goto bad;
				}
			str=buf;
			}
		else if (strcmp(*argv,"-K") == 0)
			{
			if (--argc < 1) goto bad;
			hkey= *(++argv);
			}
		else if (strcmp(*argv,"-S") == 0)
			{
			if (--argc < 1) goto bad;
			hsalt= *(++argv);
			}
		else if (strcmp(*argv,"-iv") == 0)
			{
			if (--argc < 1) goto bad;
			hiv= *(++argv);
			}
		else if (strcmp(*argv,"-md") == 0)
			{
			if (--argc < 1) goto bad;
			md= *(++argv);
			}
		else if (strcmp(*argv,"-non-fips-allow") == 0)
			non_fips_allow = 1;
		else if	((argv[0][0] == '-') &&
			((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL))
			{
			cipher=c;
			}
		else if (strcmp(*argv,"-none") == 0)
			cipher=NULL;
		else
			{
			BIO_printf(bio_err,"unknown option '%s'\n",*argv);
bad:
			BIO_printf(bio_err,"options are\n");
			BIO_printf(bio_err,"%-14s input file\n","-in <file>");
			BIO_printf(bio_err,"%-14s output file\n","-out <file>");
			BIO_printf(bio_err,"%-14s pass phrase source\n","-pass <arg>");
			BIO_printf(bio_err,"%-14s encrypt\n","-e");
			BIO_printf(bio_err,"%-14s decrypt\n","-d");
			BIO_printf(bio_err,"%-14s base64 encode/decode, depending on encryption flag\n","-a/-base64");
			BIO_printf(bio_err,"%-14s passphrase is the next argument\n","-k");
			BIO_printf(bio_err,"%-14s passphrase is the first line of the file argument\n","-kfile");
			BIO_printf(bio_err,"%-14s the next argument is the md to use to create a key\n","-md");
			BIO_printf(bio_err,"%-14s   from a passphrase.  One of md2, md5, sha or sha1\n","");
			BIO_printf(bio_err,"%-14s salt in hex is the next argument\n","-S");
			BIO_printf(bio_err,"%-14s key/iv in hex is the next argument\n","-K/-iv");
			BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]");
			BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>");
			BIO_printf(bio_err,"%-14s disable standard block padding\n","-nopad");
#ifndef OPENSSL_NO_ENGINE
			BIO_printf(bio_err,"%-14s use engine e, possibly a hardware device.\n","-engine e");
#endif

			BIO_printf(bio_err,"Cipher Types\n");
			OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
					       show_ciphers,
					       bio_err);
			BIO_printf(bio_err,"\n");

			goto end;
			}
		argc--;
		argv++;
		}

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

	if (md && (dgst=EVP_get_digestbyname(md)) == NULL)
		{
		BIO_printf(bio_err,"%s is an unsupported message digest type\n",md);
		goto end;
		}

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

	if (bufsize != NULL)
		{
		unsigned long n;

		for (n=0; *bufsize; bufsize++)
			{
			i= *bufsize;
			if ((i <= '9') && (i >= '0'))
				n=n*10+i-'0';
			else if (i == 'k')
				{
				n*=1024;
				bufsize++;
				break;
				}
			}
		if (*bufsize != '\0')
			{
			BIO_printf(bio_err,"invalid 'bufsize' specified.\n");
			goto end;
			}

		/* It must be large enough for a base64 encoded line */
		if (base64 && n < 80) n=80;

		bsize=(int)n;
		if (verbose) BIO_printf(bio_err,"bufsize=%d\n",bsize);
		}

	strbuf=OPENSSL_malloc(SIZE);
	buff=(unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize));
	if ((buff == NULL) || (strbuf == NULL))
		{
		BIO_printf(bio_err,"OPENSSL_malloc failure %ld\n",(long)EVP_ENCODE_LENGTH(bsize));
		goto end;
		}

	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		{
		ERR_print_errors(bio_err);
		goto end;
		}
	if (debug)
		{
		BIO_set_callback(in,BIO_debug_callback);
		BIO_set_callback(out,BIO_debug_callback);
		BIO_set_callback_arg(in,(char *)bio_err);
		BIO_set_callback_arg(out,(char *)bio_err);
		}

	if (inf == NULL)
	        {
#ifndef OPENSSL_NO_SETVBUF_IONBF
		if (bufsize != NULL)
			setvbuf(stdin, (char *)NULL, _IONBF, 0);
#endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
		BIO_set_fp(in,stdin,BIO_NOCLOSE);
	        }
	else
		{
		if (BIO_read_filename(in,inf) <= 0)
			{
			perror(inf);
			goto end;
			}
		}

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

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

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


	if (outf == NULL)
		{
		BIO_set_fp(out,stdout,BIO_NOCLOSE);
#ifndef OPENSSL_NO_SETVBUF_IONBF
		if (bufsize != NULL)
			setvbuf(stdout, (char *)NULL, _IONBF, 0);
#endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outf) <= 0)
			{
			perror(outf);
			goto end;
			}
		}

	rbio=in;
	wbio=out;

#ifdef ZLIB

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

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

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

				sptr = salt;
			}

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

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

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

		BIO_get_cipher_ctx(benc, &ctx);

		if (non_fips_allow)
			EVP_CIPHER_CTX_set_flags(ctx,
				EVP_CIPH_FLAG_NON_FIPS_ALLOW);

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

		if (nopad)
			EVP_CIPHER_CTX_set_padding(ctx, 0);

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

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

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

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

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

	ret=0;
	if (verbose)
		{
		BIO_printf(bio_err,"bytes read   :%8ld\n",BIO_number_read(in));
		BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out));
		}
end:
	ERR_print_errors(bio_err);
	if (strbuf != NULL) OPENSSL_free(strbuf);
	if (buff != NULL) OPENSSL_free(buff);
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	if (benc != NULL) BIO_free(benc);
	if (b64 != NULL) BIO_free(b64);
#ifdef ZLIB
	if (bzl != NULL) BIO_free(bzl);
#endif
	if(pass) OPENSSL_free(pass);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Example #18
0
static int test_ecdh_curve(int nid, BN_CTX *ctx, BIO *out)
{
    EC_KEY *a = NULL;
    EC_KEY *b = NULL;
    BIGNUM *x_a = NULL, *y_a = NULL, *x_b = NULL, *y_b = NULL;
    char buf[12];
    unsigned char *abuf = NULL, *bbuf = NULL;
    int i, alen, blen, aout, bout, ret = 0;
    const EC_GROUP *group;

    a = EC_KEY_new_by_curve_name(nid);
    b = EC_KEY_new_by_curve_name(nid);
    if (a == NULL || b == NULL)
        goto err;

    group = EC_KEY_get0_group(a);

    if ((x_a = BN_new()) == NULL)
        goto err;
    if ((y_a = BN_new()) == NULL)
        goto err;
    if ((x_b = BN_new()) == NULL)
        goto err;
    if ((y_b = BN_new()) == NULL)
        goto err;

    BIO_puts(out, "Testing key generation with ");
    BIO_puts(out, OBJ_nid2sn(nid));
# ifdef NOISY
    BIO_puts(out, "\n");
# else
    (void)BIO_flush(out);
# endif

    if (!EC_KEY_generate_key(a))
        goto err;

    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
        NID_X9_62_prime_field) {
        if (!EC_POINT_get_affine_coordinates_GFp
            (group, EC_KEY_get0_public_key(a), x_a, y_a, ctx))
            goto err;
    }
# ifndef OPENSSL_NO_EC2M
    else {
        if (!EC_POINT_get_affine_coordinates_GF2m(group,
                                                  EC_KEY_get0_public_key(a),
                                                  x_a, y_a, ctx))
            goto err;
    }
# endif
# ifdef NOISY
    BIO_puts(out, "  pri 1=");
    BN_print(out, a->priv_key);
    BIO_puts(out, "\n  pub 1=");
    BN_print(out, x_a);
    BIO_puts(out, ",");
    BN_print(out, y_a);
    BIO_puts(out, "\n");
# else
    BIO_printf(out, " .");
    (void)BIO_flush(out);
# endif

    if (!EC_KEY_generate_key(b))
        goto err;

    if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) ==
        NID_X9_62_prime_field) {
        if (!EC_POINT_get_affine_coordinates_GFp
            (group, EC_KEY_get0_public_key(b), x_b, y_b, ctx))
            goto err;
    }
# ifndef OPENSSL_NO_EC2M
    else {
        if (!EC_POINT_get_affine_coordinates_GF2m(group,
                                                  EC_KEY_get0_public_key(b),
                                                  x_b, y_b, ctx))
            goto err;
    }
# endif

# ifdef NOISY
    BIO_puts(out, "  pri 2=");
    BN_print(out, b->priv_key);
    BIO_puts(out, "\n  pub 2=");
    BN_print(out, x_b);
    BIO_puts(out, ",");
    BN_print(out, y_b);
    BIO_puts(out, "\n");
# else
    BIO_printf(out, ".");
    (void)BIO_flush(out);
# endif

    alen = KDF1_SHA1_len;
    abuf = OPENSSL_malloc(alen);
    aout =
        ECDH_compute_key(abuf, alen, EC_KEY_get0_public_key(b), a, KDF1_SHA1);

# ifdef NOISY
    BIO_puts(out, "  key1 =");
    for (i = 0; i < aout; i++) {
        sprintf(buf, "%02X", abuf[i]);
        BIO_puts(out, buf);
    }
    BIO_puts(out, "\n");
# else
    BIO_printf(out, ".");
    (void)BIO_flush(out);
# endif

    blen = KDF1_SHA1_len;
    bbuf = OPENSSL_malloc(blen);
    bout =
        ECDH_compute_key(bbuf, blen, EC_KEY_get0_public_key(a), b, KDF1_SHA1);

# ifdef NOISY
    BIO_puts(out, "  key2 =");
    for (i = 0; i < bout; i++) {
        sprintf(buf, "%02X", bbuf[i]);
        BIO_puts(out, buf);
    }
    BIO_puts(out, "\n");
# else
    BIO_printf(out, ".");
    (void)BIO_flush(out);
# endif

    if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
# ifndef NOISY
        BIO_printf(out, " failed\n\n");
        BIO_printf(out, "key a:\n");
        BIO_printf(out, "private key: ");
        BN_print(out, EC_KEY_get0_private_key(a));
        BIO_printf(out, "\n");
        BIO_printf(out, "public key (x,y): ");
        BN_print(out, x_a);
        BIO_printf(out, ",");
        BN_print(out, y_a);
        BIO_printf(out, "\nkey b:\n");
        BIO_printf(out, "private key: ");
        BN_print(out, EC_KEY_get0_private_key(b));
        BIO_printf(out, "\n");
        BIO_printf(out, "public key (x,y): ");
        BN_print(out, x_b);
        BIO_printf(out, ",");
        BN_print(out, y_b);
        BIO_printf(out, "\n");
        BIO_printf(out, "generated key a: ");
        for (i = 0; i < bout; i++) {
            sprintf(buf, "%02X", bbuf[i]);
            BIO_puts(out, buf);
        }
        BIO_printf(out, "\n");
        BIO_printf(out, "generated key b: ");
        for (i = 0; i < aout; i++) {
            sprintf(buf, "%02X", abuf[i]);
            BIO_puts(out, buf);
        }
        BIO_printf(out, "\n");
# endif
        fprintf(stderr, "Error in ECDH routines\n");
        ret = 0;
    } else {
# ifndef NOISY
        BIO_printf(out, " ok\n");
# endif
        ret = 1;
    }
 err:
    ERR_print_errors_fp(stderr);

    OPENSSL_free(abuf);
    OPENSSL_free(bbuf);
    BN_free(x_a);
    BN_free(y_a);
    BN_free(x_b);
    BN_free(y_b);
    EC_KEY_free(b);
    EC_KEY_free(a);
    return (ret);
}
Example #19
0
int dtls1_accept(SSL *s)
  {
  BUF_MEM *buf;
  unsigned long l,Time=time(NULL);
  void (*cb)(const SSL *ssl,int type,int val)=NULL;
  long num1;
  int ret= -1;
  int new_state,state,skip=0;

  RAND_add(&Time,sizeof(Time),0);
  ERR_clear_error();
  clear_sys_error();

  if (s->info_callback != NULL)
    cb=s->info_callback;
  else if (s->ctx->info_callback != NULL)
    cb=s->ctx->info_callback;

  /* init things to blank */
  s->in_handshake++;
  if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);

  if (s->cert == NULL)
    {
    SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
    return(-1);
    }

  for (;;)
    {
    state=s->state;

    switch (s->state)
      {
    case SSL_ST_RENEGOTIATE:
      s->new_session=1;
      /* s->state=SSL_ST_ACCEPT; */

    case SSL_ST_BEFORE:
    case SSL_ST_ACCEPT:
    case SSL_ST_BEFORE|SSL_ST_ACCEPT:
    case SSL_ST_OK|SSL_ST_ACCEPT:

      s->server=1;
      if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

      if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00))
        {
        SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
        return -1;
        }
      s->type=SSL_ST_ACCEPT;

      if (s->init_buf == NULL)
        {
        if ((buf=BUF_MEM_new()) == NULL)
          {
          ret= -1;
          goto end;
          }
        if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
          {
          ret= -1;
          goto end;
          }
        s->init_buf=buf;
        }

      if (!ssl3_setup_buffers(s))
        {
        ret= -1;
        goto end;
        }

      s->init_num=0;

      if (s->state != SSL_ST_RENEGOTIATE)
        {
        /* Ok, we now need to push on a buffering BIO so that
         * the output is sent in a way that TCP likes :-)
         */
        if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }

        ssl3_init_finished_mac(s);
        s->state=SSL3_ST_SR_CLNT_HELLO_A;
        s->ctx->stats.sess_accept++;
        }
      else
        {
        /* s->state == SSL_ST_RENEGOTIATE,
         * we will just send a HelloRequest */
        s->ctx->stats.sess_accept_renegotiate++;
        s->state=SSL3_ST_SW_HELLO_REQ_A;
        }

            if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
                s->d1->send_cookie = 1;
            else
                s->d1->send_cookie = 0;

      break;

    case SSL3_ST_SW_HELLO_REQ_A:
    case SSL3_ST_SW_HELLO_REQ_B:

      s->shutdown=0;
      ret=dtls1_send_hello_request(s);
      if (ret <= 0) goto end;
      s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
      s->state=SSL3_ST_SW_FLUSH;
      s->init_num=0;

      ssl3_init_finished_mac(s);
      break;

    case SSL3_ST_SW_HELLO_REQ_C:
      s->state=SSL_ST_OK;
      break;

    case SSL3_ST_SR_CLNT_HELLO_A:
    case SSL3_ST_SR_CLNT_HELLO_B:
    case SSL3_ST_SR_CLNT_HELLO_C:

      s->shutdown=0;
      ret=ssl3_get_client_hello(s);
      if (ret <= 0) goto end;
      s->new_session = 2;

      if ( s->d1->send_cookie)
        s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
      else
        s->state = SSL3_ST_SW_SRVR_HELLO_A;

      s->init_num=0;
      break;
      
    case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
    case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:

      ret = dtls1_send_hello_verify_request(s);
      if ( ret <= 0) goto end;
      s->d1->send_cookie = 0;
      s->state=SSL3_ST_SW_FLUSH;
      s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;
      break;
      
    case SSL3_ST_SW_SRVR_HELLO_A:
    case SSL3_ST_SW_SRVR_HELLO_B:
      ret=dtls1_send_server_hello(s);
      if (ret <= 0) goto end;

      if (s->hit)
        s->state=SSL3_ST_SW_CHANGE_A;
      else
        s->state=SSL3_ST_SW_CERT_A;
      s->init_num=0;
      break;

    case SSL3_ST_SW_CERT_A:
    case SSL3_ST_SW_CERT_B:
      /* Check if it is anon DH */
      if (!(s->s3->tmp.new_cipher->algorithms & SSL_aNULL))
        {
        ret=dtls1_send_server_certificate(s);
        if (ret <= 0) goto end;
        }
      else
        skip=1;
      s->state=SSL3_ST_SW_KEY_EXCH_A;
      s->init_num=0;
      break;

    case SSL3_ST_SW_KEY_EXCH_A:
    case SSL3_ST_SW_KEY_EXCH_B:
      l=s->s3->tmp.new_cipher->algorithms;

      /* clear this, it may get reset by
       * send_server_key_exchange */
      if ((s->options & SSL_OP_EPHEMERAL_RSA)
#ifndef OPENSSL_NO_KRB5
        && !(l & SSL_KRB5)
#endif /* OPENSSL_NO_KRB5 */
        )
        /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
         * even when forbidden by protocol specs
         * (handshake may fail as clients are not required to
         * be able to handle this) */
        s->s3->tmp.use_rsa_tmp=1;
      else
        s->s3->tmp.use_rsa_tmp=0;

      /* only send if a DH key exchange, fortezza or
       * RSA but we have a sign only certificate */
      if (s->s3->tmp.use_rsa_tmp
          || (l & (SSL_DH|SSL_kFZA))
          || ((l & SSL_kRSA)
        && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
            || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
          && EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
          )
            )
        )
          )
        {
        ret=dtls1_send_server_key_exchange(s);
        if (ret <= 0) goto end;
        }
      else
        skip=1;

      s->state=SSL3_ST_SW_CERT_REQ_A;
      s->init_num=0;
      break;

    case SSL3_ST_SW_CERT_REQ_A:
    case SSL3_ST_SW_CERT_REQ_B:
      if (/* don't request cert unless asked for it: */
        !(s->verify_mode & SSL_VERIFY_PEER) ||
        /* if SSL_VERIFY_CLIENT_ONCE is set,
         * don't request cert during re-negotiation: */
        ((s->session->peer != NULL) &&
         (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
        /* never request cert in anonymous ciphersuites
         * (see section "Certificate request" in SSL 3 drafts
         * and in RFC 2246): */
        ((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) &&
         /* ... except when the application insists on verification
          * (against the specs, but s3_clnt.c accepts this for SSL 3) */
         !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
                                 /* never request cert in Kerberos ciphersuites */
                                (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
        {
        /* no cert request */
        skip=1;
        s->s3->tmp.cert_request=0;
        s->state=SSL3_ST_SW_SRVR_DONE_A;
        }
      else
        {
        s->s3->tmp.cert_request=1;
        ret=dtls1_send_certificate_request(s);
        if (ret <= 0) goto end;
#ifndef NETSCAPE_HANG_BUG
        s->state=SSL3_ST_SW_SRVR_DONE_A;
#else
        s->state=SSL3_ST_SW_FLUSH;
        s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
#endif
        s->init_num=0;
        }
      break;

    case SSL3_ST_SW_SRVR_DONE_A:
    case SSL3_ST_SW_SRVR_DONE_B:
      ret=dtls1_send_server_done(s);
      if (ret <= 0) goto end;
      s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
      s->state=SSL3_ST_SW_FLUSH;
      s->init_num=0;
      break;
    
    case SSL3_ST_SW_FLUSH:
      /* number of bytes to be flushed */
      num1=BIO_ctrl(s->wbio,BIO_CTRL_INFO,0,NULL);
      if (num1 > 0)
        {
        s->rwstate=SSL_WRITING;
        num1=BIO_flush(s->wbio);
        if (num1 <= 0) { ret= -1; goto end; }
        s->rwstate=SSL_NOTHING;
        }

      s->state=s->s3->tmp.next_state;
      break;

    case SSL3_ST_SR_CERT_A:
    case SSL3_ST_SR_CERT_B:
      /* Check for second client hello (MS SGC) */
      ret = ssl3_check_client_hello(s);
      if (ret <= 0)
        goto end;
      if (ret == 2)
        s->state = SSL3_ST_SR_CLNT_HELLO_C;
      else {
        /* could be sent for a DH cert, even if we
         * have not asked for it :-) */
        ret=ssl3_get_client_certificate(s);
        if (ret <= 0) goto end;
        s->init_num=0;
        s->state=SSL3_ST_SR_KEY_EXCH_A;
      }
      break;

    case SSL3_ST_SR_KEY_EXCH_A:
    case SSL3_ST_SR_KEY_EXCH_B:
      ret=ssl3_get_client_key_exchange(s);
      if (ret <= 0) goto end;
      s->state=SSL3_ST_SR_CERT_VRFY_A;
      s->init_num=0;

      /* We need to get hashes here so if there is
       * a client cert, it can be verified */ 
      s->method->ssl3_enc->cert_verify_mac(s,
        &(s->s3->finish_dgst1),
        &(s->s3->tmp.cert_verify_md[0]));
      s->method->ssl3_enc->cert_verify_mac(s,
        &(s->s3->finish_dgst2),
        &(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));

      break;

    case SSL3_ST_SR_CERT_VRFY_A:
    case SSL3_ST_SR_CERT_VRFY_B:

      /* we should decide if we expected this one */
      ret=ssl3_get_cert_verify(s);
      if (ret <= 0) goto end;

      s->state=SSL3_ST_SR_FINISHED_A;
      s->init_num=0;
      break;

    case SSL3_ST_SR_FINISHED_A:
    case SSL3_ST_SR_FINISHED_B:
      ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
        SSL3_ST_SR_FINISHED_B);
      if (ret <= 0) goto end;
      if (s->hit)
        s->state=SSL_ST_OK;
      else
        s->state=SSL3_ST_SW_CHANGE_A;
      s->init_num=0;
      break;

    case SSL3_ST_SW_CHANGE_A:
    case SSL3_ST_SW_CHANGE_B:

      s->session->cipher=s->s3->tmp.new_cipher;
      if (!s->method->ssl3_enc->setup_key_block(s))
        { ret= -1; goto end; }

      ret=dtls1_send_change_cipher_spec(s,
        SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);

      if (ret <= 0) goto end;
      s->state=SSL3_ST_SW_FINISHED_A;
      s->init_num=0;

      if (!s->method->ssl3_enc->change_cipher_state(s,
        SSL3_CHANGE_CIPHER_SERVER_WRITE))
        {
        ret= -1;
        goto end;
        }

      dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
      break;

    case SSL3_ST_SW_FINISHED_A:
    case SSL3_ST_SW_FINISHED_B:
      ret=dtls1_send_finished(s,
        SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
        s->method->ssl3_enc->server_finished_label,
        s->method->ssl3_enc->server_finished_label_len);
      if (ret <= 0) goto end;
      s->state=SSL3_ST_SW_FLUSH;
      if (s->hit)
        s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
      else
        s->s3->tmp.next_state=SSL_ST_OK;
      s->init_num=0;
      break;

    case SSL_ST_OK:
      /* clean a few things up */
      ssl3_cleanup_key_block(s);

#if 0
      BUF_MEM_free(s->init_buf);
      s->init_buf=NULL;
#endif

      /* remove buffering on output */
      ssl_free_wbio_buffer(s);

      s->init_num=0;

      if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
        {
        /* actually not necessarily a 'new' session unless
         * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
        
        s->new_session=0;
        
        ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
        
        s->ctx->stats.sess_accept_good++;
        /* s->server=1; */
        s->handshake_func=dtls1_accept;

        if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
        }
      
      ret = 1;

      /* done handshaking, next message is client hello */
      s->d1->handshake_read_seq = 0;
      /* next message is server hello */
      s->d1->handshake_write_seq = 0;
      goto end;
      /* break; */

    default:
      SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE);
      ret= -1;
      goto end;
      /* break; */
      }
    
    if (!s->s3->tmp.reuse_message && !skip)
      {
      if (s->debug)
        {
        if ((ret=BIO_flush(s->wbio)) <= 0)
          goto end;
        }


      if ((cb != NULL) && (s->state != state))
        {
        new_state=s->state;
        s->state=state;
        cb(s,SSL_CB_ACCEPT_LOOP,1);
        s->state=new_state;
        }
      }
    skip=0;
    }
end:
  /* BIO_flush(s->wbio); */

  s->in_handshake--;
  if (cb != NULL)
    cb(s,SSL_CB_ACCEPT_EXIT,ret);
  return(ret);
  }
Example #20
0
int main(int argc, char *argv[])
{
    BN_GENCB *_cb = NULL;
    DH *a = NULL;
    DH *b = NULL;
    BIGNUM *ap = NULL, *ag = NULL, *bp = NULL, *bg = NULL, *apub_key = NULL;
    BIGNUM *bpub_key = NULL, *priv_key = NULL;
    char buf[12] = {0};
    unsigned char *abuf = NULL;
    unsigned char *bbuf = NULL;
    int i, alen, blen, aout, bout;
    int ret = 1;
    BIO *out = NULL;

    CRYPTO_set_mem_debug(1);
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

    RAND_seed(rnd_seed, sizeof rnd_seed);

    out = BIO_new(BIO_s_file());
    if (out == NULL)
        EXIT(1);
    BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);

    _cb = BN_GENCB_new();
    if (_cb == NULL)
        goto err;
    BN_GENCB_set(_cb, &cb, out);
    if (((a = DH_new()) == NULL)
        || (!DH_generate_parameters_ex(a, 64, DH_GENERATOR_5, _cb)))
        goto err;

    if (!DH_check(a, &i))
        goto err;
    if (i & DH_CHECK_P_NOT_PRIME)
        BIO_puts(out, "p value is not prime\n");
    if (i & DH_CHECK_P_NOT_SAFE_PRIME)
        BIO_puts(out, "p value is not a safe prime\n");
    if (i & DH_UNABLE_TO_CHECK_GENERATOR)
        BIO_puts(out, "unable to check the generator value\n");
    if (i & DH_NOT_SUITABLE_GENERATOR)
        BIO_puts(out, "the g value is not a generator\n");

    DH_get0_pqg(a, &ap, NULL, &ag);
    BIO_puts(out, "\np    =");
    BN_print(out, ap);
    BIO_puts(out, "\ng    =");
    BN_print(out, ag);
    BIO_puts(out, "\n");

    b = DH_new();
    if (b == NULL)
        goto err;

    bp = BN_dup(ap);
    bg = BN_dup(ag);
    if ((bp == NULL) || (bg == NULL) || !DH_set0_pqg(b, bp, NULL, bg))
        goto err;
    bp = bg = NULL;

    /* Set a to run with normal modexp and b to use constant time */
    DH_clear_flags(a, DH_FLAG_NO_EXP_CONSTTIME);
    DH_set_flags(b, DH_FLAG_NO_EXP_CONSTTIME);

    if (!DH_generate_key(a))
        goto err;
    DH_get0_key(a, &apub_key, &priv_key);
    BIO_puts(out, "pri 1=");
    BN_print(out, priv_key);
    BIO_puts(out, "\npub 1=");
    BN_print(out, apub_key);
    BIO_puts(out, "\n");

    if (!DH_generate_key(b))
        goto err;
    DH_get0_key(b, &bpub_key, &priv_key);
    BIO_puts(out, "pri 2=");
    BN_print(out, priv_key);
    BIO_puts(out, "\npub 2=");
    BN_print(out, bpub_key);
    BIO_puts(out, "\n");

    alen = DH_size(a);
    abuf = OPENSSL_malloc(alen);
    if (abuf == NULL)
        goto err;

    aout = DH_compute_key(abuf, bpub_key, a);

    BIO_puts(out, "key1 =");
    for (i = 0; i < aout; i++) {
        sprintf(buf, "%02X", abuf[i]);
        BIO_puts(out, buf);
    }
    BIO_puts(out, "\n");

    blen = DH_size(b);
    bbuf = OPENSSL_malloc(blen);
    if (bbuf == NULL)
        goto err;

    bout = DH_compute_key(bbuf, apub_key, b);

    BIO_puts(out, "key2 =");
    for (i = 0; i < bout; i++) {
        sprintf(buf, "%02X", bbuf[i]);
        BIO_puts(out, buf);
    }
    BIO_puts(out, "\n");
    if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
        fprintf(stderr, "Error in DH routines\n");
        ret = 1;
    } else
        ret = 0;
    if (!run_rfc5114_tests())
        ret = 1;
 err:
    (void)BIO_flush(out);
    ERR_print_errors_fp(stderr);

    OPENSSL_free(abuf);
    OPENSSL_free(bbuf);
    DH_free(b);
    DH_free(a);
    BN_free(bp);
    BN_free(bg);
    BN_GENCB_free(_cb);
    BIO_free(out);

#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    if (CRYPTO_mem_leaks_fp(stderr) <= 0)
        ret = 1;
#endif

    EXIT(ret);
}
Example #21
0
int DTLSv1_listen(SSL *s, BIO_ADDR *client)
{
    int next, n, ret = 0, clearpkt = 0;
    unsigned char cookie[DTLS1_COOKIE_LENGTH];
    unsigned char seq[SEQ_NUM_SIZE];
    const unsigned char *data;
    unsigned char *buf;
    unsigned long fragoff, fraglen, msglen;
    unsigned int rectype, versmajor, msgseq, msgtype, clientvers, cookielen;
    BIO *rbio, *wbio;
    BUF_MEM *bufm;
    BIO_ADDR *tmpclient = NULL;
    PACKET pkt, msgpkt, msgpayload, session, cookiepkt;

    /* Ensure there is no state left over from a previous invocation */
    if (!SSL_clear(s))
        return -1;

    ERR_clear_error();

    rbio = SSL_get_rbio(s);
    wbio = SSL_get_wbio(s);

    if (!rbio || !wbio) {
        SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BIO_NOT_SET);
        return -1;
    }

    /*
     * We only peek at incoming ClientHello's until we're sure we are going to
     * to respond with a HelloVerifyRequest. If its a ClientHello with a valid
     * cookie then we leave it in the BIO for accept to handle.
     */
    BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);

    /*
     * Note: This check deliberately excludes DTLS1_BAD_VER because that version
     * requires the MAC to be calculated *including* the first ClientHello
     * (without the cookie). Since DTLSv1_listen is stateless that cannot be
     * supported. DTLS1_BAD_VER must use cookies in a stateful manner (e.g. via
     * SSL_accept)
     */
    if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00)) {
        SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNSUPPORTED_SSL_VERSION);
        return -1;
    }

    if (s->init_buf == NULL) {
        if ((bufm = BUF_MEM_new()) == NULL) {
            SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
            return -1;
        }

        if (!BUF_MEM_grow(bufm, SSL3_RT_MAX_PLAIN_LENGTH)) {
            BUF_MEM_free(bufm);
            SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
            return -1;
        }
        s->init_buf = bufm;
    }
    buf = (unsigned char *)s->init_buf->data;

    do {
        /* Get a packet */

        clear_sys_error();
        /*
         * Technically a ClientHello could be SSL3_RT_MAX_PLAIN_LENGTH
         * + DTLS1_RT_HEADER_LENGTH bytes long. Normally init_buf does not store
         * the record header as well, but we do here. We've set up init_buf to
         * be the standard size for simplicity. In practice we shouldn't ever
         * receive a ClientHello as long as this. If we do it will get dropped
         * in the record length check below.
         */
        n = BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);

        if (n <= 0) {
            if (BIO_should_retry(rbio)) {
                /* Non-blocking IO */
                goto end;
            }
            return -1;
        }

        /* If we hit any problems we need to clear this packet from the BIO */
        clearpkt = 1;

        if (!PACKET_buf_init(&pkt, buf, n)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
            return -1;
        }

        /*
         * Parse the received record. If there are any problems with it we just
         * dump it - with no alert. RFC6347 says this "Unlike TLS, DTLS is
         * resilient in the face of invalid records (e.g., invalid formatting,
         * length, MAC, etc.).  In general, invalid records SHOULD be silently
         * discarded, thus preserving the association; however, an error MAY be
         * logged for diagnostic purposes."
         */

        /* this packet contained a partial record, dump it */
        if (n < DTLS1_RT_HEADER_LENGTH) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_RECORD_TOO_SMALL);
            goto end;
        }

        if (s->msg_callback)
            s->msg_callback(0, 0, SSL3_RT_HEADER, buf,
                            DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);

        /* Get the record header */
        if (!PACKET_get_1(&pkt, &rectype)
            || !PACKET_get_1(&pkt, &versmajor)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        if (rectype != SSL3_RT_HANDSHAKE) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
            goto end;
        }

        /*
         * Check record version number. We only check that the major version is
         * the same.
         */
        if (versmajor != DTLS1_VERSION_MAJOR) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
            goto end;
        }

        if (!PACKET_forward(&pkt, 1)
            /* Save the sequence number: 64 bits, with top 2 bytes = epoch */
            || !PACKET_copy_bytes(&pkt, seq, SEQ_NUM_SIZE)
            || !PACKET_get_length_prefixed_2(&pkt, &msgpkt)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }
        /*
         * We allow data remaining at the end of the packet because there could
         * be a second record (but we ignore it)
         */

        /* This is an initial ClientHello so the epoch has to be 0 */
        if (seq[0] != 0 || seq[1] != 0) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
            goto end;
        }

        /* Get a pointer to the raw message for the later callback */
        data = PACKET_data(&msgpkt);

        /* Finished processing the record header, now process the message */
        if (!PACKET_get_1(&msgpkt, &msgtype)
            || !PACKET_get_net_3(&msgpkt, &msglen)
            || !PACKET_get_net_2(&msgpkt, &msgseq)
            || !PACKET_get_net_3(&msgpkt, &fragoff)
            || !PACKET_get_net_3(&msgpkt, &fraglen)
            || !PACKET_get_sub_packet(&msgpkt, &msgpayload, fraglen)
            || PACKET_remaining(&msgpkt) != 0) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        if (msgtype != SSL3_MT_CLIENT_HELLO) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_UNEXPECTED_MESSAGE);
            goto end;
        }

        /* Message sequence number can only be 0 or 1 */
        if (msgseq > 2) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_INVALID_SEQUENCE_NUMBER);
            goto end;
        }

        /*
         * We don't support fragment reassembly for ClientHellos whilst
         * listening because that would require server side state (which is
         * against the whole point of the ClientHello/HelloVerifyRequest
         * mechanism). Instead we only look at the first ClientHello fragment
         * and require that the cookie must be contained within it.
         */
        if (fragoff != 0 || fraglen > msglen) {
            /* Non initial ClientHello fragment (or bad fragment) */
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_FRAGMENTED_CLIENT_HELLO);
            goto end;
        }

        if (s->msg_callback)
            s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, data,
                            fraglen + DTLS1_HM_HEADER_LENGTH, s,
                            s->msg_callback_arg);

        if (!PACKET_get_net_2(&msgpayload, &clientvers)) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        /*
         * Verify client version is supported
         */
        if (DTLS_VERSION_LT(clientvers, (unsigned int)s->method->version) &&
            s->method->version != DTLS_ANY_VERSION) {
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_WRONG_VERSION_NUMBER);
            goto end;
        }

        if (!PACKET_forward(&msgpayload, SSL3_RANDOM_SIZE)
            || !PACKET_get_length_prefixed_1(&msgpayload, &session)
            || !PACKET_get_length_prefixed_1(&msgpayload, &cookiepkt)) {
            /*
             * Could be malformed or the cookie does not fit within the initial
             * ClientHello fragment. Either way we can't handle it.
             */
            SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_LENGTH_MISMATCH);
            goto end;
        }

        /*
         * Check if we have a cookie or not. If not we need to send a
         * HelloVerifyRequest.
         */
        if (PACKET_remaining(&cookiepkt) == 0) {
            next = LISTEN_SEND_VERIFY_REQUEST;
        } else {
            /*
             * We have a cookie, so lets check it.
             */
            if (s->ctx->app_verify_cookie_cb == NULL) {
                SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_NO_VERIFY_COOKIE_CALLBACK);
                /* This is fatal */
                return -1;
            }
            if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookiepkt),
                                             PACKET_remaining(&cookiepkt)) ==
                0) {
                /*
                 * We treat invalid cookies in the same was as no cookie as
                 * per RFC6347
                 */
                next = LISTEN_SEND_VERIFY_REQUEST;
            } else {
                /* Cookie verification succeeded */
                next = LISTEN_SUCCESS;
            }
        }

        if (next == LISTEN_SEND_VERIFY_REQUEST) {
            WPACKET wpkt;
            unsigned int version;
            size_t wreclen;

            /*
             * There was no cookie in the ClientHello so we need to send a
             * HelloVerifyRequest. If this fails we do not worry about trying
             * to resend, we just drop it.
             */

            /*
             * Dump the read packet, we don't need it any more. Ignore return
             * value
             */
            BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
            BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
            BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 1, NULL);

            /* Generate the cookie */
            if (s->ctx->app_gen_cookie_cb == NULL ||
                s->ctx->app_gen_cookie_cb(s, cookie, &cookielen) == 0 ||
                cookielen > 255) {
                SSLerr(SSL_F_DTLSV1_LISTEN, SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
                /* This is fatal */
                return -1;
            }

            /*
             * Special case: for hello verify request, client version 1.0 and we
             * haven't decided which version to use yet send back using version
             * 1.0 header: otherwise some clients will ignore it.
             */
            version = (s->method->version == DTLS_ANY_VERSION) ? DTLS1_VERSION
                                                               : s->version;

            /* Construct the record and message headers */
            if (!WPACKET_init(&wpkt, s->init_buf)
                    || !WPACKET_put_bytes_u8(&wpkt, SSL3_RT_HANDSHAKE)
                    || !WPACKET_put_bytes_u16(&wpkt, version)
                       /*
                        * Record sequence number is always the same as in the
                        * received ClientHello
                        */
                    || !WPACKET_memcpy(&wpkt, seq, SEQ_NUM_SIZE)
                       /* End of record, start sub packet for message */
                    || !WPACKET_start_sub_packet_u16(&wpkt)
                       /* Message type */
                    || !WPACKET_put_bytes_u8(&wpkt,
                                             DTLS1_MT_HELLO_VERIFY_REQUEST)
                       /*
                        * Message length - doesn't follow normal TLS convention:
                        * the length isn't the last thing in the message header.
                        * We'll need to fill this in later when we know the
                        * length. Set it to zero for now
                        */
                    || !WPACKET_put_bytes_u24(&wpkt, 0)
                       /*
                        * Message sequence number is always 0 for a
                        * HelloVerifyRequest
                        */
                    || !WPACKET_put_bytes_u16(&wpkt, 0)
                       /*
                        * We never fragment a HelloVerifyRequest, so fragment
                        * offset is 0
                        */
                    || !WPACKET_put_bytes_u24(&wpkt, 0)
                       /*
                        * Fragment length is the same as message length, but
                        * this *is* the last thing in the message header so we
                        * can just start a sub-packet. No need to come back
                        * later for this one.
                        */
                    || !WPACKET_start_sub_packet_u24(&wpkt)
                       /* Create the actual HelloVerifyRequest body */
                    || !dtls_raw_hello_verify_request(&wpkt, cookie, cookielen)
                       /* Close message body */
                    || !WPACKET_close(&wpkt)
                       /* Close record body */
                    || !WPACKET_close(&wpkt)
                    || !WPACKET_get_total_written(&wpkt, &wreclen)
                    || !WPACKET_finish(&wpkt)) {
                SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_INTERNAL_ERROR);
                WPACKET_cleanup(&wpkt);
                /* This is fatal */
                return -1;
            }

            /*
             * Fix up the message len in the message header. Its the same as the
             * fragment len which has been filled in by WPACKET, so just copy
             * that. Destination for the message len is after the record header
             * plus one byte for the message content type. The source is the
             * last 3 bytes of the message header
             */
            memcpy(&buf[DTLS1_RT_HEADER_LENGTH + 1],
                   &buf[DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH - 3],
                   3);

            if (s->msg_callback)
                s->msg_callback(1, 0, SSL3_RT_HEADER, buf,
                                DTLS1_RT_HEADER_LENGTH, s, s->msg_callback_arg);

            if ((tmpclient = BIO_ADDR_new()) == NULL) {
                SSLerr(SSL_F_DTLSV1_LISTEN, ERR_R_MALLOC_FAILURE);
                goto end;
            }

            /*
             * This is unnecessary if rbio and wbio are one and the same - but
             * maybe they're not. We ignore errors here - some BIOs do not
             * support this.
             */
            if (BIO_dgram_get_peer(rbio, tmpclient) > 0) {
                (void)BIO_dgram_set_peer(wbio, tmpclient);
            }
            BIO_ADDR_free(tmpclient);
            tmpclient = NULL;

            if (BIO_write(wbio, buf, wreclen) < (int)wreclen) {
                if (BIO_should_retry(wbio)) {
                    /*
                     * Non-blocking IO...but we're stateless, so we're just
                     * going to drop this packet.
                     */
                    goto end;
                }
                return -1;
            }

            if (BIO_flush(wbio) <= 0) {
                if (BIO_should_retry(wbio)) {
                    /*
                     * Non-blocking IO...but we're stateless, so we're just
                     * going to drop this packet.
                     */
                    goto end;
                }
                return -1;
            }
        }
    } while (next != LISTEN_SUCCESS);

    /*
     * Set expected sequence numbers to continue the handshake.
     */
    s->d1->handshake_read_seq = 1;
    s->d1->handshake_write_seq = 1;
    s->d1->next_handshake_write_seq = 1;
    DTLS_RECORD_LAYER_set_write_sequence(&s->rlayer, seq);

    /*
     * We are doing cookie exchange, so make sure we set that option in the
     * SSL object
     */
    SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);

    /*
     * Tell the state machine that we've done the initial hello verify
     * exchange
     */
    ossl_statem_set_hello_verify_done(s);

    /*
     * Some BIOs may not support this. If we fail we clear the client address
     */
    if (BIO_dgram_get_peer(rbio, client) <= 0)
        BIO_ADDR_clear(client);

    ret = 1;
    clearpkt = 0;
 end:
    BIO_ADDR_free(tmpclient);
    BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_PEEK_MODE, 0, NULL);
    if (clearpkt) {
        /* Dump this packet. Ignore return value */
        BIO_read(rbio, buf, SSL3_RT_MAX_PLAIN_LENGTH);
    }
    return ret;
}
Example #22
0
int dtls1_connect(SSL *s)
	{
	BUF_MEM *buf=NULL;
	unsigned long Time=(unsigned long)time(NULL);
	void (*cb)(const SSL *ssl,int type,int val)=NULL;
	int ret= -1;
	int new_state,state,skip=0;;

	RAND_add(&Time,sizeof(Time),0);
	ERR_clear_error();
	clear_sys_error();

	if (s->info_callback != NULL)
		cb=s->info_callback;
	else if (s->ctx->info_callback != NULL)
		cb=s->ctx->info_callback;
	
	s->in_handshake++;
	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s); 

	for (;;)
		{
		state=s->state;

		switch(s->state)
			{
		case SSL_ST_RENEGOTIATE:
			s->new_session=1;
			s->state=SSL_ST_CONNECT;
			s->ctx->stats.sess_connect_renegotiate++;
			/* break */
		case SSL_ST_BEFORE:
		case SSL_ST_CONNECT:
		case SSL_ST_BEFORE|SSL_ST_CONNECT:
		case SSL_ST_OK|SSL_ST_CONNECT:

			s->server=0;
			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

			if ((s->version & 0xff00 ) != (DTLS1_VERSION & 0xff00) &&
			    (s->version & 0xff00 ) != (DTLS1_BAD_VER & 0xff00))
				{
				SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
				ret = -1;
				goto end;
				}
				
			/* s->version=SSL3_VERSION; */
			s->type=SSL_ST_CONNECT;

			if (s->init_buf == NULL)
				{
				if ((buf=BUF_MEM_new()) == NULL)
					{
					ret= -1;
					goto end;
					}
				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
					{
					ret= -1;
					goto end;
					}
				s->init_buf=buf;
				buf=NULL;
				}

			if (!ssl3_setup_buffers(s)) { ret= -1; goto end; }

			/* setup buffing BIO */
			if (!ssl_init_wbio_buffer(s,0)) { ret= -1; goto end; }

			/* don't push the buffering BIO quite yet */

			s->state=SSL3_ST_CW_CLNT_HELLO_A;
			s->ctx->stats.sess_connect++;
			s->init_num=0;
			/* mark client_random uninitialized */
			memset(s->s3->client_random,0,sizeof(s->s3->client_random));
			s->d1->send_cookie = 0;
			s->hit = 0;
			break;

		case SSL3_ST_CW_CLNT_HELLO_A:
		case SSL3_ST_CW_CLNT_HELLO_B:

			s->shutdown=0;

			/* every DTLS ClientHello resets Finished MAC */
			ssl3_init_finished_mac(s);

			dtls1_start_timer(s);
			ret=dtls1_client_hello(s);
			if (ret <= 0) goto end;

			if ( s->d1->send_cookie)
				{
				s->state=SSL3_ST_CW_FLUSH;
				s->s3->tmp.next_state=SSL3_ST_CR_SRVR_HELLO_A;
				}
			else
				s->state=SSL3_ST_CR_SRVR_HELLO_A;

			s->init_num=0;

			/* turn on buffering for the next lot of output */
			if (s->bbio != s->wbio)
				s->wbio=BIO_push(s->bbio,s->wbio);

			break;

		case SSL3_ST_CR_SRVR_HELLO_A:
		case SSL3_ST_CR_SRVR_HELLO_B:
			ret=ssl3_get_server_hello(s);
			if (ret <= 0) goto end;
			else
				{
				dtls1_stop_timer(s);
				if (s->hit)
					s->state=SSL3_ST_CR_FINISHED_A;
				else
					s->state=DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
				}
			s->init_num=0;
			break;

		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
		case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:

			ret = dtls1_get_hello_verify(s);
			if ( ret <= 0)
				goto end;
			dtls1_stop_timer(s);
			if ( s->d1->send_cookie) /* start again, with a cookie */
				s->state=SSL3_ST_CW_CLNT_HELLO_A;
			else
				s->state = SSL3_ST_CR_CERT_A;
			s->init_num = 0;
			break;

		case SSL3_ST_CR_CERT_A:
		case SSL3_ST_CR_CERT_B:
#ifndef OPENSSL_NO_TLSEXT
			ret=ssl3_check_finished(s);
			if (ret <= 0) goto end;
			if (ret == 2)
				{
				s->hit = 1;
				if (s->tlsext_ticket_expected)
					s->state=SSL3_ST_CR_SESSION_TICKET_A;
				else
					s->state=SSL3_ST_CR_FINISHED_A;
				s->init_num=0;
				break;
				}
#endif
			/* Check if it is anon DH or PSK */
			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
			    !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
				{
				ret=ssl3_get_server_certificate(s);
				if (ret <= 0) goto end;
#ifndef OPENSSL_NO_TLSEXT
				if (s->tlsext_status_expected)
					s->state=SSL3_ST_CR_CERT_STATUS_A;
				else
					s->state=SSL3_ST_CR_KEY_EXCH_A;
				}
			else
				{
				skip = 1;
				s->state=SSL3_ST_CR_KEY_EXCH_A;
				}
#else
				}
			else
				skip=1;

			s->state=SSL3_ST_CR_KEY_EXCH_A;
#endif
			s->init_num=0;
			break;

		case SSL3_ST_CR_KEY_EXCH_A:
		case SSL3_ST_CR_KEY_EXCH_B:
			ret=ssl3_get_key_exchange(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CR_CERT_REQ_A;
			s->init_num=0;

			/* at this point we check that we have the
			 * required stuff from the server */
			if (!ssl3_check_cert_and_algorithm(s))
				{
				ret= -1;
				goto end;
				}
			break;

		case SSL3_ST_CR_CERT_REQ_A:
		case SSL3_ST_CR_CERT_REQ_B:
			ret=ssl3_get_certificate_request(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CR_SRVR_DONE_A;
			s->init_num=0;
			break;

		case SSL3_ST_CR_SRVR_DONE_A:
		case SSL3_ST_CR_SRVR_DONE_B:
			ret=ssl3_get_server_done(s);
			if (ret <= 0) goto end;
			if (s->s3->tmp.cert_req)
				s->state=SSL3_ST_CW_CERT_A;
			else
				s->state=SSL3_ST_CW_KEY_EXCH_A;
			s->init_num=0;

			break;

		case SSL3_ST_CW_CERT_A:
		case SSL3_ST_CW_CERT_B:
		case SSL3_ST_CW_CERT_C:
		case SSL3_ST_CW_CERT_D:
			dtls1_start_timer(s);
			ret=dtls1_send_client_certificate(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CW_KEY_EXCH_A;
			s->init_num=0;
			break;

		case SSL3_ST_CW_KEY_EXCH_A:
		case SSL3_ST_CW_KEY_EXCH_B:
			dtls1_start_timer(s);
			ret=dtls1_send_client_key_exchange(s);
			if (ret <= 0) goto end;
			/* EAY EAY EAY need to check for DH fix cert
			 * sent back */
			/* For TLS, cert_req is set to 2, so a cert chain
			 * of nothing is sent, but no verify packet is sent */
			if (s->s3->tmp.cert_req == 1)
				{
				s->state=SSL3_ST_CW_CERT_VRFY_A;
				}
			else
				{
				s->state=SSL3_ST_CW_CHANGE_A;
				s->s3->change_cipher_spec=0;
				}

			s->init_num=0;
			break;

		case SSL3_ST_CW_CERT_VRFY_A:
		case SSL3_ST_CW_CERT_VRFY_B:
			dtls1_start_timer(s);
			ret=dtls1_send_client_verify(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CW_CHANGE_A;
			s->init_num=0;
			s->s3->change_cipher_spec=0;
			break;

		case SSL3_ST_CW_CHANGE_A:
		case SSL3_ST_CW_CHANGE_B:
			dtls1_start_timer(s);
			ret=dtls1_send_change_cipher_spec(s,
				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CW_FINISHED_A;
			s->init_num=0;

			s->session->cipher=s->s3->tmp.new_cipher;
#ifdef OPENSSL_NO_COMP
			s->session->compress_meth=0;
#else
			if (s->s3->tmp.new_compression == NULL)
				s->session->compress_meth=0;
			else
				s->session->compress_meth=
					s->s3->tmp.new_compression->id;
#endif
			if (!s->method->ssl3_enc->setup_key_block(s))
				{
				ret= -1;
				goto end;
				}

			if (!s->method->ssl3_enc->change_cipher_state(s,
				SSL3_CHANGE_CIPHER_CLIENT_WRITE))
				{
				ret= -1;
				goto end;
				}
			
			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
			break;

		case SSL3_ST_CW_FINISHED_A:
		case SSL3_ST_CW_FINISHED_B:
			dtls1_start_timer(s);
			ret=dtls1_send_finished(s,
				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
				s->method->ssl3_enc->client_finished_label,
				s->method->ssl3_enc->client_finished_label_len);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CW_FLUSH;

			/* clear flags */
			s->s3->flags&= ~SSL3_FLAGS_POP_BUFFER;
			if (s->hit)
				{
				s->s3->tmp.next_state=SSL_ST_OK;
				if (s->s3->flags & SSL3_FLAGS_DELAY_CLIENT_FINISHED)
					{
					s->state=SSL_ST_OK;
					s->s3->flags|=SSL3_FLAGS_POP_BUFFER;
					s->s3->delay_buf_pop_ret=0;
					}
				}
			else
				{
#ifndef OPENSSL_NO_TLSEXT
				/* Allow NewSessionTicket if ticket expected */
				if (s->tlsext_ticket_expected)
					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
				else
#endif
				
				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
				}
			s->init_num=0;
			break;

#ifndef OPENSSL_NO_TLSEXT
		case SSL3_ST_CR_SESSION_TICKET_A:
		case SSL3_ST_CR_SESSION_TICKET_B:
			ret=ssl3_get_new_session_ticket(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CR_FINISHED_A;
			s->init_num=0;
		break;

		case SSL3_ST_CR_CERT_STATUS_A:
		case SSL3_ST_CR_CERT_STATUS_B:
			ret=ssl3_get_cert_status(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CR_KEY_EXCH_A;
			s->init_num=0;
		break;
#endif

		case SSL3_ST_CR_FINISHED_A:
		case SSL3_ST_CR_FINISHED_B:
			s->d1->change_cipher_spec_ok = 1;
			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
				SSL3_ST_CR_FINISHED_B);
			if (ret <= 0) goto end;
			dtls1_stop_timer(s);

			if (s->hit)
				s->state=SSL3_ST_CW_CHANGE_A;
			else
				s->state=SSL_ST_OK;
			s->init_num=0;
			break;

		case SSL3_ST_CW_FLUSH:
			s->rwstate=SSL_WRITING;
			if (BIO_flush(s->wbio) <= 0)
				{
				ret= -1;
				goto end;
				}
			s->rwstate=SSL_NOTHING;
			s->state=s->s3->tmp.next_state;
			break;

		case SSL_ST_OK:
			/* clean a few things up */
			ssl3_cleanup_key_block(s);

#if 0
			if (s->init_buf != NULL)
				{
				BUF_MEM_free(s->init_buf);
				s->init_buf=NULL;
				}
#endif

			/* If we are not 'joining' the last two packets,
			 * remove the buffering now */
			if (!(s->s3->flags & SSL3_FLAGS_POP_BUFFER))
				ssl_free_wbio_buffer(s);
			/* else do it later in ssl3_write */

			s->init_num=0;
			s->new_session=0;

			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
			if (s->hit) s->ctx->stats.sess_hit++;

			ret=1;
			/* s->server=0; */
			s->handshake_func=dtls1_connect;
			s->ctx->stats.sess_connect_good++;

			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);

			/* done with handshaking */
			s->d1->handshake_read_seq  = 0;
			s->d1->next_handshake_write_seq = 0;
			goto end;
			/* break; */
			
		default:
			SSLerr(SSL_F_DTLS1_CONNECT,SSL_R_UNKNOWN_STATE);
			ret= -1;
			goto end;
			/* break; */
			}
Example #23
0
int dtls1_connect(SSL *s) {
  BUF_MEM *buf = NULL;
  void (*cb)(const SSL *ssl, int type, int val) = NULL;
  int ret = -1;
  int new_state, state, skip = 0;

  assert(s->handshake_func == dtls1_connect);
  assert(!s->server);
  assert(SSL_IS_DTLS(s));

  ERR_clear_error();
  ERR_clear_system_error();

  if (s->info_callback != NULL) {
    cb = s->info_callback;
  } else if (s->ctx->info_callback != NULL) {
    cb = s->ctx->info_callback;
  }

  s->in_handshake++;

  for (;;) {
    state = s->state;

    switch (s->state) {
      case SSL_ST_RENEGOTIATE:
        s->renegotiate = 1;
        s->state = SSL_ST_CONNECT;
      /* break */
      case SSL_ST_CONNECT:
      case SSL_ST_BEFORE | SSL_ST_CONNECT:
        if (cb != NULL) {
          cb(s, SSL_CB_HANDSHAKE_START, 1);
        }

        if (s->init_buf == NULL) {
          buf = BUF_MEM_new();
          if (buf == NULL ||
              !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
            ret = -1;
            goto end;
          }
          s->init_buf = buf;
          buf = NULL;
        }

        if (!ssl3_setup_buffers(s) ||
            !ssl_init_wbio_buffer(s, 0)) {
          ret = -1;
          goto end;
        }

        /* don't push the buffering BIO quite yet */

        s->state = SSL3_ST_CW_CLNT_HELLO_A;
        s->init_num = 0;
        s->d1->send_cookie = 0;
        s->hit = 0;
        break;

      case SSL3_ST_CW_CLNT_HELLO_A:
      case SSL3_ST_CW_CLNT_HELLO_B:
        s->shutdown = 0;

        /* every DTLS ClientHello resets Finished MAC */
        if (!ssl3_init_finished_mac(s)) {
          OPENSSL_PUT_ERROR(SSL, dtls1_connect, ERR_R_INTERNAL_ERROR);
          ret = -1;
          goto end;
        }

        dtls1_start_timer(s);
        ret = ssl3_send_client_hello(s);
        if (ret <= 0) {
          goto end;
        }

        if (s->d1->send_cookie) {
          s->state = SSL3_ST_CW_FLUSH;
          s->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
        } else {
          s->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
        }

        s->init_num = 0;
        /* turn on buffering for the next lot of output */
        if (s->bbio != s->wbio) {
          s->wbio = BIO_push(s->bbio, s->wbio);
        }

        break;

      case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
      case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
        ret = dtls1_get_hello_verify(s);
        if (ret <= 0) {
          goto end;
        }
        if (s->d1->send_cookie) {
          /* start again, with a cookie */
          dtls1_stop_timer(s);
          s->state = SSL3_ST_CW_CLNT_HELLO_A;
        } else {
          s->state = SSL3_ST_CR_SRVR_HELLO_A;
        }
        s->init_num = 0;
        break;

      case SSL3_ST_CR_SRVR_HELLO_A:
      case SSL3_ST_CR_SRVR_HELLO_B:
        ret = ssl3_get_server_hello(s);
        if (ret <= 0) {
          goto end;
        }

        if (s->hit) {
          s->state = SSL3_ST_CR_FINISHED_A;
          if (s->tlsext_ticket_expected) {
            /* receive renewed session ticket */
            s->state = SSL3_ST_CR_SESSION_TICKET_A;
          }
        } else {
          s->state = SSL3_ST_CR_CERT_A;
        }
        s->init_num = 0;
        break;

      case SSL3_ST_CR_CERT_A:
      case SSL3_ST_CR_CERT_B:
        if (ssl_cipher_has_server_public_key(s->s3->tmp.new_cipher)) {
          ret = ssl3_get_server_certificate(s);
          if (ret <= 0) {
            goto end;
          }
          if (s->s3->tmp.certificate_status_expected) {
            s->state = SSL3_ST_CR_CERT_STATUS_A;
          } else {
            s->state = SSL3_ST_CR_KEY_EXCH_A;
          }
        } else {
          skip = 1;
          s->state = SSL3_ST_CR_KEY_EXCH_A;
        }
        s->init_num = 0;
        break;

      case SSL3_ST_CR_KEY_EXCH_A:
      case SSL3_ST_CR_KEY_EXCH_B:
        ret = ssl3_get_server_key_exchange(s);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CR_CERT_REQ_A;
        s->init_num = 0;

        /* at this point we check that we have the
         * required stuff from the server */
        if (!ssl3_check_cert_and_algorithm(s)) {
          ret = -1;
          goto end;
        }
        break;

      case SSL3_ST_CR_CERT_REQ_A:
      case SSL3_ST_CR_CERT_REQ_B:
        ret = ssl3_get_certificate_request(s);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CR_SRVR_DONE_A;
        s->init_num = 0;
        break;

      case SSL3_ST_CR_SRVR_DONE_A:
      case SSL3_ST_CR_SRVR_DONE_B:
        ret = ssl3_get_server_done(s);
        if (ret <= 0) {
          goto end;
        }
        dtls1_stop_timer(s);
        if (s->s3->tmp.cert_req) {
          s->s3->tmp.next_state = SSL3_ST_CW_CERT_A;
        } else {
          s->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A;
        }
        s->init_num = 0;
        s->state = s->s3->tmp.next_state;
        break;

      case SSL3_ST_CW_CERT_A:
      case SSL3_ST_CW_CERT_B:
      case SSL3_ST_CW_CERT_C:
      case SSL3_ST_CW_CERT_D:
        dtls1_start_timer(s);
        ret = ssl3_send_client_certificate(s);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CW_KEY_EXCH_A;
        s->init_num = 0;
        break;

      case SSL3_ST_CW_KEY_EXCH_A:
      case SSL3_ST_CW_KEY_EXCH_B:
        dtls1_start_timer(s);
        ret = ssl3_send_client_key_exchange(s);
        if (ret <= 0) {
          goto end;
        }
        /* For TLS, cert_req is set to 2, so a cert chain
         * of nothing is sent, but no verify packet is sent */
        if (s->s3->tmp.cert_req == 1) {
          s->state = SSL3_ST_CW_CERT_VRFY_A;
        } else {
          s->state = SSL3_ST_CW_CHANGE_A;
          s->s3->change_cipher_spec = 0;
        }

        s->init_num = 0;
        break;

      case SSL3_ST_CW_CERT_VRFY_A:
      case SSL3_ST_CW_CERT_VRFY_B:
        dtls1_start_timer(s);
        ret = ssl3_send_cert_verify(s);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CW_CHANGE_A;
        s->init_num = 0;
        s->s3->change_cipher_spec = 0;
        break;

      case SSL3_ST_CW_CHANGE_A:
      case SSL3_ST_CW_CHANGE_B:
        if (!s->hit) {
          dtls1_start_timer(s);
        }
        ret = dtls1_send_change_cipher_spec(s, SSL3_ST_CW_CHANGE_A,
                                            SSL3_ST_CW_CHANGE_B);
        if (ret <= 0) {
          goto end;
        }

        s->state = SSL3_ST_CW_FINISHED_A;
        s->init_num = 0;

        s->session->cipher = s->s3->tmp.new_cipher;
        if (!s->enc_method->setup_key_block(s) ||
            !s->enc_method->change_cipher_state(
                s, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
          ret = -1;
          goto end;
        }

        dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
        break;

      case SSL3_ST_CW_FINISHED_A:
      case SSL3_ST_CW_FINISHED_B:
        if (!s->hit) {
          dtls1_start_timer(s);
        }

        ret =
            ssl3_send_finished(s, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
                               s->enc_method->client_finished_label,
                               s->enc_method->client_finished_label_len);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CW_FLUSH;

        if (s->hit) {
          s->s3->tmp.next_state = SSL_ST_OK;
        } else {
          /* Allow NewSessionTicket if ticket expected */
          if (s->tlsext_ticket_expected) {
            s->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
          } else {
            s->s3->tmp.next_state = SSL3_ST_CR_FINISHED_A;
          }
        }
        s->init_num = 0;
        break;

      case SSL3_ST_CR_SESSION_TICKET_A:
      case SSL3_ST_CR_SESSION_TICKET_B:
        ret = ssl3_get_new_session_ticket(s);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CR_FINISHED_A;
        s->init_num = 0;
        break;

      case SSL3_ST_CR_CERT_STATUS_A:
      case SSL3_ST_CR_CERT_STATUS_B:
        ret = ssl3_get_cert_status(s);
        if (ret <= 0) {
          goto end;
        }
        s->state = SSL3_ST_CR_KEY_EXCH_A;
        s->init_num = 0;
        break;

      case SSL3_ST_CR_FINISHED_A:
      case SSL3_ST_CR_FINISHED_B:
        s->d1->change_cipher_spec_ok = 1;
        ret =
            ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B);
        if (ret <= 0) {
          goto end;
        }
        dtls1_stop_timer(s);

        if (s->hit) {
          s->state = SSL3_ST_CW_CHANGE_A;
        } else {
          s->state = SSL_ST_OK;
        }

        s->init_num = 0;
        break;

      case SSL3_ST_CW_FLUSH:
        s->rwstate = SSL_WRITING;
        if (BIO_flush(s->wbio) <= 0) {
          ret = -1;
          goto end;
        }
        s->rwstate = SSL_NOTHING;
        s->state = s->s3->tmp.next_state;
        break;

      case SSL_ST_OK:
        /* clean a few things up */
        ssl3_cleanup_key_block(s);

        /* Remove write buffering now. */
        ssl_free_wbio_buffer(s);

        s->init_num = 0;
        s->renegotiate = 0;
        s->new_session = 0;

        ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);

        ret = 1;

        if (cb != NULL) {
          cb(s, SSL_CB_HANDSHAKE_DONE, 1);
        }

        /* done with handshaking */
        s->d1->handshake_read_seq = 0;
        s->d1->next_handshake_write_seq = 0;
        goto end;

      default:
        OPENSSL_PUT_ERROR(SSL, dtls1_connect, SSL_R_UNKNOWN_STATE);
        ret = -1;
        goto end;
    }

    /* did we do anything? */
    if (!s->s3->tmp.reuse_message && !skip) {
      if ((cb != NULL) && (s->state != state)) {
        new_state = s->state;
        s->state = state;
        cb(s, SSL_CB_CONNECT_LOOP, 1);
        s->state = new_state;
      }
    }
    skip = 0;
  }

end:
  s->in_handshake--;

  if (buf != NULL) {
    BUF_MEM_free(buf);
  }
  if (cb != NULL) {
    cb(s, SSL_CB_CONNECT_EXIT, ret);
  }
  return ret;
}
Example #24
0
static void print_stuff(BIO *bio, SSL *s, int full)
{
    X509 *peer=NULL;
    char *p;
    static const char *space="                ";
    char buf[BUFSIZ];
    STACK_OF(X509) *sk;
    STACK_OF(X509_NAME) *sk2;
    SSL_CIPHER *c;
    X509_NAME *xn;
    int j,i;
#ifndef OPENSSL_NO_COMP
    const COMP_METHOD *comp, *expansion;
#endif

    if (full)
    {
        int got_a_chain = 0;

        sk=SSL_get_peer_cert_chain(s);
        if (sk != NULL)
        {
            got_a_chain = 1; /* we don't have it for SSL2 (yet) */

            BIO_printf(bio,"---\nCertificate chain\n");
            for (i=0; i<sk_X509_num(sk); i++)
            {
                X509_NAME_oneline(X509_get_subject_name(
                                      sk_X509_value(sk,i)),buf,sizeof buf);
                BIO_printf(bio,"%2d s:%s\n",i,buf);
                X509_NAME_oneline(X509_get_issuer_name(
                                      sk_X509_value(sk,i)),buf,sizeof buf);
                BIO_printf(bio,"   i:%s\n",buf);
                if (c_showcerts)
                    PEM_write_bio_X509(bio,sk_X509_value(sk,i));
            }
        }

        BIO_printf(bio,"---\n");
        peer=SSL_get_peer_certificate(s);
        if (peer != NULL)
        {
            BIO_printf(bio,"Server certificate\n");
            if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */
                PEM_write_bio_X509(bio,peer);
            X509_NAME_oneline(X509_get_subject_name(peer),
                              buf,sizeof buf);
            BIO_printf(bio,"subject=%s\n",buf);
            X509_NAME_oneline(X509_get_issuer_name(peer),
                              buf,sizeof buf);
            BIO_printf(bio,"issuer=%s\n",buf);
        }
        else
            BIO_printf(bio,"no peer certificate available\n");

        sk2=SSL_get_client_CA_list(s);
        if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0))
        {
            BIO_printf(bio,"---\nAcceptable client certificate CA names\n");
            for (i=0; i<sk_X509_NAME_num(sk2); i++)
            {
                xn=sk_X509_NAME_value(sk2,i);
                X509_NAME_oneline(xn,buf,sizeof(buf));
                BIO_write(bio,buf,strlen(buf));
                BIO_write(bio,"\n",1);
            }
        }
        else
        {
            BIO_printf(bio,"---\nNo client certificate CA names sent\n");
        }
        p=SSL_get_shared_ciphers(s,buf,sizeof buf);
        if (p != NULL)
        {
            /* This works only for SSL 2.  In later protocol
             * versions, the client does not know what other
             * ciphers (in addition to the one to be used
             * in the current connection) the server supports. */

            BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n");
            j=i=0;
            while (*p)
            {
                if (*p == ':')
                {
                    BIO_write(bio,space,15-j%25);
                    i++;
                    j=0;
                    BIO_write(bio,((i%3)?" ":"\n"),1);
                }
                else
                {
                    BIO_write(bio,p,1);
                    j++;
                }
                p++;
            }
            BIO_write(bio,"\n",1);
        }

        BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
                   BIO_number_read(SSL_get_rbio(s)),
                   BIO_number_written(SSL_get_wbio(s)));
    }
    BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));
    c=SSL_get_current_cipher(s);
    BIO_printf(bio,"%s, Cipher is %s\n",
               SSL_CIPHER_get_version(c),
               SSL_CIPHER_get_name(c));
    if (peer != NULL) {
        EVP_PKEY *pktmp;
        pktmp = X509_get_pubkey(peer);
        BIO_printf(bio,"Server public key is %d bit\n",
                   EVP_PKEY_bits(pktmp));
        EVP_PKEY_free(pktmp);
    }
#ifndef OPENSSL_NO_COMP
    comp=SSL_get_current_compression(s);
    expansion=SSL_get_current_expansion(s);
    BIO_printf(bio,"Compression: %s\n",
               comp ? SSL_COMP_get_name(comp) : "NONE");
    BIO_printf(bio,"Expansion: %s\n",
               expansion ? SSL_COMP_get_name(expansion) : "NONE");
#endif
    SSL_SESSION_print(bio,SSL_get_session(s));
    BIO_printf(bio,"---\n");
    if (peer != NULL)
        X509_free(peer);
    /* flush, or debugging output gets mixed with http response */
    BIO_flush(bio);
}
Example #25
0
void
msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL * ssl, void *arg)
{
	BIO *bio = arg;
	const char *str_write_p, *str_version, *str_content_type = "",
	    *str_details1 = "", *str_details2 = "";

	str_write_p = write_p ? ">>>" : "<<<";

	switch (version) {
	case SSL2_VERSION:
		str_version = "SSL 2.0";
		break;
	case SSL3_VERSION:
		str_version = "SSL 3.0 ";
		break;
	case TLS1_VERSION:
		str_version = "TLS 1.0 ";
		break;
	case TLS1_1_VERSION:
		str_version = "TLS 1.1 ";
		break;
	case TLS1_2_VERSION:
		str_version = "TLS 1.2 ";
		break;
	case DTLS1_VERSION:
		str_version = "DTLS 1.0 ";
		break;
	default:
		str_version = "???";
	}

	if (version == SSL2_VERSION) {
		str_details1 = "???";

		if (len > 0) {
			switch (((const unsigned char *) buf)[0]) {
			case 0:
				str_details1 = ", ERROR:";
				str_details2 = " ???";
				if (len >= 3) {
					unsigned err = (((const unsigned char *) buf)[1] << 8) + ((const unsigned char *) buf)[2];

					switch (err) {
					case 0x0001:
						str_details2 = " NO-CIPHER-ERROR";
						break;
					case 0x0002:
						str_details2 = " NO-CERTIFICATE-ERROR";
						break;
					case 0x0004:
						str_details2 = " BAD-CERTIFICATE-ERROR";
						break;
					case 0x0006:
						str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR";
						break;
					}
				}
				break;
			case 1:
				str_details1 = ", CLIENT-HELLO";
				break;
			case 2:
				str_details1 = ", CLIENT-MASTER-KEY";
				break;
			case 3:
				str_details1 = ", CLIENT-FINISHED";
				break;
			case 4:
				str_details1 = ", SERVER-HELLO";
				break;
			case 5:
				str_details1 = ", SERVER-VERIFY";
				break;
			case 6:
				str_details1 = ", SERVER-FINISHED";
				break;
			case 7:
				str_details1 = ", REQUEST-CERTIFICATE";
				break;
			case 8:
				str_details1 = ", CLIENT-CERTIFICATE";
				break;
			}
		}
	}
	if (version == SSL3_VERSION || version == TLS1_VERSION ||
	    version == TLS1_1_VERSION || version == TLS1_2_VERSION ||
	    version == DTLS1_VERSION) {
		switch (content_type) {
		case 20:
			str_content_type = "ChangeCipherSpec";
			break;
		case 21:
			str_content_type = "Alert";
			break;
		case 22:
			str_content_type = "Handshake";
			break;
		}

		if (content_type == 21) {	/* Alert */
			str_details1 = ", ???";

			if (len == 2) {
				switch (((const unsigned char *) buf)[0]) {
				case 1:
					str_details1 = ", warning";
					break;
				case 2:
					str_details1 = ", fatal";
					break;
				}

				str_details2 = " ???";
				switch (((const unsigned char *) buf)[1]) {
				case 0:
					str_details2 = " close_notify";
					break;
				case 10:
					str_details2 = " unexpected_message";
					break;
				case 20:
					str_details2 = " bad_record_mac";
					break;
				case 21:
					str_details2 = " decryption_failed";
					break;
				case 22:
					str_details2 = " record_overflow";
					break;
				case 30:
					str_details2 = " decompression_failure";
					break;
				case 40:
					str_details2 = " handshake_failure";
					break;
				case 42:
					str_details2 = " bad_certificate";
					break;
				case 43:
					str_details2 = " unsupported_certificate";
					break;
				case 44:
					str_details2 = " certificate_revoked";
					break;
				case 45:
					str_details2 = " certificate_expired";
					break;
				case 46:
					str_details2 = " certificate_unknown";
					break;
				case 47:
					str_details2 = " illegal_parameter";
					break;
				case 48:
					str_details2 = " unknown_ca";
					break;
				case 49:
					str_details2 = " access_denied";
					break;
				case 50:
					str_details2 = " decode_error";
					break;
				case 51:
					str_details2 = " decrypt_error";
					break;
				case 60:
					str_details2 = " export_restriction";
					break;
				case 70:
					str_details2 = " protocol_version";
					break;
				case 71:
					str_details2 = " insufficient_security";
					break;
				case 80:
					str_details2 = " internal_error";
					break;
				case 90:
					str_details2 = " user_canceled";
					break;
				case 100:
					str_details2 = " no_renegotiation";
					break;
				case 110:
					str_details2 = " unsupported_extension";
					break;
				case 111:
					str_details2 = " certificate_unobtainable";
					break;
				case 112:
					str_details2 = " unrecognized_name";
					break;
				case 113:
					str_details2 = " bad_certificate_status_response";
					break;
				case 114:
					str_details2 = " bad_certificate_hash_value";
					break;
				case 115:
					str_details2 = " unknown_psk_identity";
					break;
				}
			}
		}
		if (content_type == 22) {	/* Handshake */
			str_details1 = "???";

			if (len > 0) {
				switch (((const unsigned char *) buf)[0]) {
				case 0:
					str_details1 = ", HelloRequest";
					break;
				case 1:
					str_details1 = ", ClientHello";
					break;
				case 2:
					str_details1 = ", ServerHello";
					break;
				case 3:
					str_details1 = ", HelloVerifyRequest";
					break;
				case 11:
					str_details1 = ", Certificate";
					break;
				case 12:
					str_details1 = ", ServerKeyExchange";
					break;
				case 13:
					str_details1 = ", CertificateRequest";
					break;
				case 14:
					str_details1 = ", ServerHelloDone";
					break;
				case 15:
					str_details1 = ", CertificateVerify";
					break;
				case 16:
					str_details1 = ", ClientKeyExchange";
					break;
				case 20:
					str_details1 = ", Finished";
					break;
				}
			}
		}
	}
	BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p,
	    str_version, str_content_type, (unsigned long) len,
	    str_details1, str_details2);

	if (len > 0) {
		size_t num, i;

		BIO_printf(bio, "   ");
		num = len;

		for (i = 0; i < num; i++) {
			if (i % 16 == 0 && i > 0)
				BIO_printf(bio, "\n   ");
			BIO_printf(bio, " %02x",
			    ((const unsigned char *) buf)[i]);
		}
		if (i < len)
			BIO_printf(bio, " ...");
		BIO_printf(bio, "\n");
	}
	(void) BIO_flush(bio);
}
Example #26
0
int main(int argc, char *argv[])
{
    FUNCTION f, *fp;
    LHASH_OF(FUNCTION) *prog = NULL;
    char **copied_argv = NULL;
    char *p, *pname;
    char buf[1024];
    const char *prompt;
    ARGS arg;
    int first, n, i, ret = 0;

    arg.argv = NULL;
    arg.size = 0;

    /* Set up some of the environment. */
    default_config_file = make_config_name();
    bio_in = dup_bio_in(FORMAT_TEXT);
    bio_out = dup_bio_out(FORMAT_TEXT);
    bio_err = dup_bio_err(FORMAT_TEXT);

#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
    copied_argv = argv = copy_argv(&argc, argv);
#endif

    p = getenv("OPENSSL_DEBUG_MEMORY");
    if (p != NULL && strcmp(p, "on") == 0)
        CRYPTO_set_mem_debug(1);
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

    if (getenv("OPENSSL_FIPS")) {
#ifdef OPENSSL_FIPS
        if (!FIPS_mode_set(1)) {
            ERR_print_errors(bio_err);
            return 1;
        }
#else
        BIO_printf(bio_err, "FIPS mode not supported.\n");
        return 1;
#endif
    }

    if (!apps_startup())
        goto end;

    prog = prog_init();
    pname = opt_progname(argv[0]);

    /* first check the program name */
    f.name = pname;
    fp = lh_FUNCTION_retrieve(prog, &f);
    if (fp != NULL) {
        argv[0] = pname;
        ret = fp->func(argc, argv);
        goto end;
    }

    /* If there is stuff on the command line, run with that. */
    if (argc != 1) {
        argc--;
        argv++;
        ret = do_cmd(prog, argc, argv);
        if (ret < 0)
            ret = 0;
        goto end;
    }

    /* ok, lets enter interactive mode */
    for (;;) {
        ret = 0;
        /* Read a line, continue reading if line ends with \ */
        for (p = buf, n = sizeof buf, i = 0, first = 1; n > 0; first = 0) {
            prompt = first ? "OpenSSL> " : "> ";
            p[0] = '\0';
#ifndef READLINE
            fputs(prompt, stdout);
            fflush(stdout);
            if (!fgets(p, n, stdin))
                goto end;
            if (p[0] == '\0')
                goto end;
            i = strlen(p);
            if (i <= 1)
                break;
            if (p[i - 2] != '\\')
                break;
            i -= 2;
            p += i;
            n -= i;
#else
            {
                extern char *readline(const char *);
                extern void add_history(const char *cp);
                char *text;

                char *text = readline(prompt);
                if (text == NULL)
                    goto end;
                i = strlen(text);
                if (i == 0 || i > n)
                    break;
                if (text[i - 1] != '\\') {
                    p += strlen(strcpy(p, text));
                    free(text);
                    add_history(buf);
                    break;
                }

                text[i - 1] = '\0';
                p += strlen(strcpy(p, text));
                free(text);
                n -= i;
            }
#endif
        }

        if (!chopup_args(&arg, buf)) {
            BIO_printf(bio_err, "Can't parse (no memory?)\n");
            break;
        }

        ret = do_cmd(prog, arg.argc, arg.argv);
        if (ret == EXIT_THE_PROGRAM) {
            ret = 0;
            goto end;
        }
        if (ret != 0)
            BIO_printf(bio_err, "error in %s\n", arg.argv[0]);
        (void)BIO_flush(bio_out);
        (void)BIO_flush(bio_err);
    }
    ret = 1;
 end:
    OPENSSL_free(copied_argv);
    OPENSSL_free(default_config_file);
    NCONF_free(config);
    config = NULL;
    lh_FUNCTION_free(prog);
    OPENSSL_free(arg.argv);

    BIO_free(bio_in);
    BIO_free_all(bio_out);
    apps_shutdown();
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    if (CRYPTO_mem_leaks(bio_err) <= 0)
        ret = 1;
#endif
    BIO_free(bio_err);
    EXIT(ret);
}
Example #27
0
int rand_main(int argc, char **argv)
{
    BIO *out = NULL;
    char *inrand = NULL, *outfile = NULL, *prog;
    OPTION_CHOICE o;
    int format = FORMAT_BINARY, i, num = -1, r, ret = 1;

    prog = opt_init(argc, argv, rand_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(rand_options);
            ret = 0;
            goto end;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENGINE:
            (void)setup_engine(opt_arg(), 0);
            break;
        case OPT_RAND:
            inrand = opt_arg();
            break;
        case OPT_BASE64:
            format = FORMAT_BASE64;
            break;
        case OPT_HEX:
            format = FORMAT_TEXT;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (argc != 1 || !opt_int(argv[0], &num) || num < 0)
        goto opthelp;

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

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

    if (format == FORMAT_BASE64) {
        BIO *b64 = BIO_new(BIO_f_base64());
        if (b64 == NULL)
            goto end;
        out = BIO_push(b64, out);
    }

    while (num > 0) {
        unsigned char buf[4096];
        int chunk;

        chunk = num;
        if (chunk > (int)sizeof(buf))
            chunk = sizeof buf;
        r = RAND_bytes(buf, chunk);
        if (r <= 0)
            goto end;
        if (format != FORMAT_TEXT) /* hex */
            BIO_write(out, buf, chunk);
        else {
            for (i = 0; i < chunk; i++)
                BIO_printf(out, "%02x", buf[i]);
        }
        num -= chunk;
    }
    if (format == FORMAT_TEXT)
        BIO_puts(out, "\n");
    (void)BIO_flush(out);

    app_RAND_write_file(NULL);
    ret = 0;

 end:
    BIO_free_all(out);
    return (ret);
}
Example #28
0
int
__bro_openssl_write(BroConn *bc, uchar *buf, uint buf_size)
{
  int n;
  void *old_sig;
  
  D_ENTER;
  
#ifdef BRO_DEBUG
  if (bro_debug_messages)
    {
      unsigned int i = 0;
      int last_hex = 0;

      D(("Sending %u bytes: ", buf_size));
 
      for (i = 0; i < buf_size; i++)
	{
	  if (buf[i] >= 32 && buf[i] <= 126)
	    {
	      printf("%s%c", last_hex ? " " : "", buf[i]);
	      last_hex = 0;
	    }
	  else
	    {
	      printf(" 0x%.2x", buf[i]);
	      last_hex = 1;
	    }
	}
      printf("\n");
    }
#endif

  /* We may get a SIGPIPE if we write to a connection whose peer
   * died. Since we don't know the application context in which
   * we're running, we temporarily set the SIGPIPE handler to our
   * own and then set it back to the old one after we wrote.
   */
  old_sig = signal(SIGPIPE, SIG_IGN);
  
  n = BIO_write(bc->bio, buf, buf_size);
  
  if (n <= 0)
    {
      if (BIO_should_retry(bc->bio))
	{
	  n = 0;
	  goto error_return;
	}

      print_errors();
      __bro_openssl_shutdown(bc);
      D(("Connection closed.\n"));
      n = -1;
    }
  
  BIO_flush(bc->bio);

 error_return:
  
  if (old_sig != SIG_ERR)
    signal(SIGPIPE, old_sig);
  
  D_RETURN_(n);
}
Example #29
0
int dtls1_accept(SSL *s)
	{
	BUF_MEM *buf;
	unsigned long Time=(unsigned long)time(NULL);
	void (*cb)(const SSL *ssl,int type,int val)=NULL;
	unsigned long alg_k;
	int ret= -1;
	int new_state,state,skip=0;
	int listen;
#ifndef OPENSSL_NO_SCTP
	unsigned char sctpauthkey[64];
	char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
#endif

	RAND_add(&Time,sizeof(Time),0);
	ERR_clear_error();
	clear_sys_error();

	if (s->info_callback != NULL)
		cb=s->info_callback;
	else if (s->ctx->info_callback != NULL)
		cb=s->ctx->info_callback;
	
	listen = s->d1->listen;

	/* init things to blank */
	s->in_handshake++;
	if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);

	s->d1->listen = listen;
#ifndef OPENSSL_NO_SCTP
	/* Notify SCTP BIO socket to enter handshake
	 * mode and prevent stream identifier other
	 * than 0. Will be ignored if no SCTP is used.
	 */
	BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE, s->in_handshake, NULL);
#endif

	if (s->cert == NULL)
		{
		SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_NO_CERTIFICATE_SET);
		return(-1);
		}

#ifndef OPENSSL_NO_HEARTBEATS
	/* If we're awaiting a HeartbeatResponse, pretend we
	 * already got and don't await it anymore, because
	 * Heartbeats don't make sense during handshakes anyway.
	 */
	if (s->tlsext_hb_pending)
		{
		dtls1_stop_timer(s);
		s->tlsext_hb_pending = 0;
		s->tlsext_hb_seq++;
		}
#endif

	for (;;)
		{
		state=s->state;

		switch (s->state)
			{
		case SSL_ST_RENEGOTIATE:
			s->renegotiate=1;
			/* s->state=SSL_ST_ACCEPT; */

		case SSL_ST_BEFORE:
		case SSL_ST_ACCEPT:
		case SSL_ST_BEFORE|SSL_ST_ACCEPT:
		case SSL_ST_OK|SSL_ST_ACCEPT:

			s->server=1;
			if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);

			if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00))
				{
				SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
				return -1;
				}
			s->type=SSL_ST_ACCEPT;

			if (s->init_buf == NULL)
				{
				if ((buf=BUF_MEM_new()) == NULL)
					{
					ret= -1;
					goto end;
					}
				if (!BUF_MEM_grow(buf,SSL3_RT_MAX_PLAIN_LENGTH))
					{
					ret= -1;
					goto end;
					}
				s->init_buf=buf;
				}

			if (!ssl3_setup_buffers(s))
				{
				ret= -1;
				goto end;
				}

			s->init_num=0;

			if (s->state != SSL_ST_RENEGOTIATE)
				{
				/* Ok, we now need to push on a buffering BIO so that
				 * the output is sent in a way that TCP likes :-)
				 * ...but not with SCTP :-)
				 */
#ifndef OPENSSL_NO_SCTP
				if (!BIO_dgram_is_sctp(SSL_get_wbio(s)))
#endif
					if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }

				ssl3_init_finished_mac(s);
				s->state=SSL3_ST_SR_CLNT_HELLO_A;
				s->ctx->stats.sess_accept++;
				}
			else
				{
				/* s->state == SSL_ST_RENEGOTIATE,
				 * we will just send a HelloRequest */
				s->ctx->stats.sess_accept_renegotiate++;
				s->state=SSL3_ST_SW_HELLO_REQ_A;
				}

			break;

		case SSL3_ST_SW_HELLO_REQ_A:
		case SSL3_ST_SW_HELLO_REQ_B:

			s->shutdown=0;
			dtls1_start_timer(s);
			ret=dtls1_send_hello_request(s);
			if (ret <= 0) goto end;
			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
			s->state=SSL3_ST_SW_FLUSH;
			s->init_num=0;

			ssl3_init_finished_mac(s);
			break;

		case SSL3_ST_SW_HELLO_REQ_C:
			s->state=SSL_ST_OK;
			break;

		case SSL3_ST_SR_CLNT_HELLO_A:
		case SSL3_ST_SR_CLNT_HELLO_B:
		case SSL3_ST_SR_CLNT_HELLO_C:

			s->shutdown=0;
			ret=ssl3_get_client_hello(s);
			if (ret <= 0) goto end;
			dtls1_stop_timer(s);

			if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
				s->state = DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A;
			else
				s->state = SSL3_ST_SW_SRVR_HELLO_A;

			s->init_num=0;

			/* Reflect ClientHello sequence to remain stateless while listening */
			if (listen)
				{
				memcpy(s->s3->write_sequence, s->s3->read_sequence, sizeof(s->s3->write_sequence));
				}

			/* If we're just listening, stop here */
			if (listen && s->state == SSL3_ST_SW_SRVR_HELLO_A)
				{
				ret = 2;
				s->d1->listen = 0;
				/* Set expected sequence numbers
				 * to continue the handshake.
				 */
				s->d1->handshake_read_seq = 2;
				s->d1->handshake_write_seq = 1;
				s->d1->next_handshake_write_seq = 1;
				goto end;
				}
			
			break;
			
		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:

			ret = dtls1_send_hello_verify_request(s);
			if ( ret <= 0) goto end;
			s->state=SSL3_ST_SW_FLUSH;
			s->s3->tmp.next_state=SSL3_ST_SR_CLNT_HELLO_A;

			/* HelloVerifyRequest resets Finished MAC */
			if (s->version != DTLS1_BAD_VER)
				ssl3_init_finished_mac(s);
			break;
			
#ifndef OPENSSL_NO_SCTP
		case DTLS1_SCTP_ST_SR_READ_SOCK:
			
			if (BIO_dgram_sctp_msg_waiting(SSL_get_rbio(s)))		
				{
				s->s3->in_read_app_data=2;
				s->rwstate=SSL_READING;
				BIO_clear_retry_flags(SSL_get_rbio(s));
				BIO_set_retry_read(SSL_get_rbio(s));
				ret = -1;
				goto end;
				}
			
			s->state=SSL3_ST_SR_FINISHED_A;
			break;
			
		case DTLS1_SCTP_ST_SW_WRITE_SOCK:
			ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
			if (ret < 0) goto end;
			
			if (ret == 0)
				{
				if (s->d1->next_state != SSL_ST_OK)
					{
					s->s3->in_read_app_data=2;
					s->rwstate=SSL_READING;
					BIO_clear_retry_flags(SSL_get_rbio(s));
					BIO_set_retry_read(SSL_get_rbio(s));
					ret = -1;
					goto end;
					}
				}

			s->state=s->d1->next_state;
			break;
#endif

		case SSL3_ST_SW_SRVR_HELLO_A:
		case SSL3_ST_SW_SRVR_HELLO_B:
			s->renegotiate = 2;
			dtls1_start_timer(s);
			ret=dtls1_send_server_hello(s);
			if (ret <= 0) goto end;

			if (s->hit)
				{
#ifndef OPENSSL_NO_SCTP
				/* Add new shared key for SCTP-Auth,
				 * will be ignored if no SCTP used.
				 */
				snprintf((char*) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
				         DTLS1_SCTP_AUTH_LABEL);

				SSL_export_keying_material(s, sctpauthkey,
				                           sizeof(sctpauthkey), labelbuffer,
				                           sizeof(labelbuffer), NULL, 0, 0);
				
				BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
                         sizeof(sctpauthkey), sctpauthkey);
#endif
#ifndef OPENSSL_NO_TLSEXT
				if (s->tlsext_ticket_expected)
					s->state=SSL3_ST_SW_SESSION_TICKET_A;
				else
					s->state=SSL3_ST_SW_CHANGE_A;
#else
				s->state=SSL3_ST_SW_CHANGE_A;
#endif
				}
			else
				s->state=SSL3_ST_SW_CERT_A;
			s->init_num=0;
			break;

		case SSL3_ST_SW_CERT_A:
		case SSL3_ST_SW_CERT_B:
			/* Check if it is anon DH or normal PSK */
			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
				&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
				{
				dtls1_start_timer(s);
				ret=dtls1_send_server_certificate(s);
				if (ret <= 0) goto end;
#ifndef OPENSSL_NO_TLSEXT
				if (s->tlsext_status_expected)
					s->state=SSL3_ST_SW_CERT_STATUS_A;
				else
					s->state=SSL3_ST_SW_KEY_EXCH_A;
				}
			else
				{
				skip = 1;
				s->state=SSL3_ST_SW_KEY_EXCH_A;
				}
#else
				}
			else
				skip=1;

			s->state=SSL3_ST_SW_KEY_EXCH_A;
#endif
			s->init_num=0;
			break;

		case SSL3_ST_SW_KEY_EXCH_A:
		case SSL3_ST_SW_KEY_EXCH_B:
			alg_k = s->s3->tmp.new_cipher->algorithm_mkey;

			/* clear this, it may get reset by
			 * send_server_key_exchange */
			if ((s->options & SSL_OP_EPHEMERAL_RSA)
#ifndef OPENSSL_NO_KRB5
				&& !(alg_k & SSL_kKRB5)
#endif /* OPENSSL_NO_KRB5 */
				)
				/* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
				 * even when forbidden by protocol specs
				 * (handshake may fail as clients are not required to
				 * be able to handle this) */
				s->s3->tmp.use_rsa_tmp=1;
			else
				s->s3->tmp.use_rsa_tmp=0;

			/* only send if a DH key exchange or
			 * RSA but we have a sign only certificate */
			if (s->s3->tmp.use_rsa_tmp
			/* PSK: send ServerKeyExchange if PSK identity
			 * hint if provided */
#ifndef OPENSSL_NO_PSK
			    || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
#endif
			    || (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
			    || (alg_k & SSL_kEECDH)
			    || ((alg_k & SSL_kRSA)
				&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
				    || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)
					&& EVP_PKEY_size(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)
					)
				    )
				)
			    )
				{
				dtls1_start_timer(s);
				ret=dtls1_send_server_key_exchange(s);
				if (ret <= 0) goto end;
				}
			else
				skip=1;

			s->state=SSL3_ST_SW_CERT_REQ_A;
			s->init_num=0;
			break;

		case SSL3_ST_SW_CERT_REQ_A:
		case SSL3_ST_SW_CERT_REQ_B:
			if (/* don't request cert unless asked for it: */
				!(s->verify_mode & SSL_VERIFY_PEER) ||
				/* if SSL_VERIFY_CLIENT_ONCE is set,
				 * don't request cert during re-negotiation: */
				((s->session->peer != NULL) &&
				 (s->verify_mode & SSL_VERIFY_CLIENT_ONCE)) ||
				/* never request cert in anonymous ciphersuites
				 * (see section "Certificate request" in SSL 3 drafts
				 * and in RFC 2246): */
				((s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL) &&
				 /* ... except when the application insists on verification
				  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
				 !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
				 /* never request cert in Kerberos ciphersuites */
				(s->s3->tmp.new_cipher->algorithm_auth & SSL_aKRB5)
				/* With normal PSK Certificates and
				 * Certificate Requests are omitted */
				|| (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK))
				{
				/* no cert request */
				skip=1;
				s->s3->tmp.cert_request=0;
				s->state=SSL3_ST_SW_SRVR_DONE_A;
#ifndef OPENSSL_NO_SCTP
				if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
					{
					s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
					s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
					}
#endif
				}
			else
				{
				s->s3->tmp.cert_request=1;
				dtls1_start_timer(s);
				ret=dtls1_send_certificate_request(s);
				if (ret <= 0) goto end;
#ifndef NETSCAPE_HANG_BUG
				s->state=SSL3_ST_SW_SRVR_DONE_A;
#ifndef OPENSSL_NO_SCTP
				if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
					{
					s->d1->next_state = SSL3_ST_SW_SRVR_DONE_A;
					s->state = DTLS1_SCTP_ST_SW_WRITE_SOCK;
					}
#endif
#else
				s->state=SSL3_ST_SW_FLUSH;
				s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
#ifndef OPENSSL_NO_SCTP
				if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
					{
					s->d1->next_state = s->s3->tmp.next_state;
					s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK;
					}
#endif
#endif
				s->init_num=0;
				}
			break;

		case SSL3_ST_SW_SRVR_DONE_A:
		case SSL3_ST_SW_SRVR_DONE_B:
			dtls1_start_timer(s);
			ret=dtls1_send_server_done(s);
			if (ret <= 0) goto end;
			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
			s->state=SSL3_ST_SW_FLUSH;
			s->init_num=0;
			break;
		
		case SSL3_ST_SW_FLUSH:
			s->rwstate=SSL_WRITING;
			if (BIO_flush(s->wbio) <= 0)
				{
				/* If the write error was fatal, stop trying */
				if (!BIO_should_retry(s->wbio))
					{
					s->rwstate=SSL_NOTHING;
					s->state=s->s3->tmp.next_state;
					}
				
				ret= -1;
				goto end;
				}
			s->rwstate=SSL_NOTHING;
			s->state=s->s3->tmp.next_state;
			break;

		case SSL3_ST_SR_CERT_A:
		case SSL3_ST_SR_CERT_B:
			/* Check for second client hello (MS SGC) */
			ret = ssl3_check_client_hello(s);
			if (ret <= 0)
				goto end;
			if (ret == 2)
				{
				dtls1_stop_timer(s);
				s->state = SSL3_ST_SR_CLNT_HELLO_C;
				}
			else {
				/* could be sent for a DH cert, even if we
				 * have not asked for it :-) */
				ret=ssl3_get_client_certificate(s);
				if (ret <= 0) goto end;
				s->init_num=0;
				s->state=SSL3_ST_SR_KEY_EXCH_A;
			}
			break;

		case SSL3_ST_SR_KEY_EXCH_A:
		case SSL3_ST_SR_KEY_EXCH_B:
			ret=ssl3_get_client_key_exchange(s);
			if (ret <= 0) goto end;
#ifndef OPENSSL_NO_SCTP
			/* Add new shared key for SCTP-Auth,
			 * will be ignored if no SCTP used.
			 */
			snprintf((char *) labelbuffer, sizeof(DTLS1_SCTP_AUTH_LABEL),
			         DTLS1_SCTP_AUTH_LABEL);

			SSL_export_keying_material(s, sctpauthkey,
			                           sizeof(sctpauthkey), labelbuffer,
			                           sizeof(labelbuffer), NULL, 0, 0);

			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
			         sizeof(sctpauthkey), sctpauthkey);
#endif

			s->state=SSL3_ST_SR_CERT_VRFY_A;
			s->init_num=0;

			if (ret == 2)
				{
				/* For the ECDH ciphersuites when
				 * the client sends its ECDH pub key in
				 * a certificate, the CertificateVerify
				 * message is not sent.
				 */
				s->state=SSL3_ST_SR_FINISHED_A;
				s->init_num = 0;
				}
			else
				{
				s->state=SSL3_ST_SR_CERT_VRFY_A;
				s->init_num=0;

				/* We need to get hashes here so if there is
				 * a client cert, it can be verified */ 
				s->method->ssl3_enc->cert_verify_mac(s,
					NID_md5,
					&(s->s3->tmp.cert_verify_md[0]));
				s->method->ssl3_enc->cert_verify_mac(s,
					NID_sha1,
					&(s->s3->tmp.cert_verify_md[MD5_DIGEST_LENGTH]));
				}
			break;

		case SSL3_ST_SR_CERT_VRFY_A:
		case SSL3_ST_SR_CERT_VRFY_B:

			s->d1->change_cipher_spec_ok = 1;
			/* we should decide if we expected this one */
			ret=ssl3_get_cert_verify(s);
			if (ret <= 0) goto end;
#ifndef OPENSSL_NO_SCTP
			if (BIO_dgram_is_sctp(SSL_get_wbio(s)) &&
			    state == SSL_ST_RENEGOTIATE)
				s->state=DTLS1_SCTP_ST_SR_READ_SOCK;
			else
#endif			
				s->state=SSL3_ST_SR_FINISHED_A;
			s->init_num=0;
			break;

		case SSL3_ST_SR_FINISHED_A:
		case SSL3_ST_SR_FINISHED_B:
			s->d1->change_cipher_spec_ok = 1;
			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
				SSL3_ST_SR_FINISHED_B);
			if (ret <= 0) goto end;
			dtls1_stop_timer(s);
			if (s->hit)
				s->state=SSL_ST_OK;
#ifndef OPENSSL_NO_TLSEXT
			else if (s->tlsext_ticket_expected)
				s->state=SSL3_ST_SW_SESSION_TICKET_A;
#endif
			else
				s->state=SSL3_ST_SW_CHANGE_A;
			s->init_num=0;
			break;

#ifndef OPENSSL_NO_TLSEXT
		case SSL3_ST_SW_SESSION_TICKET_A:
		case SSL3_ST_SW_SESSION_TICKET_B:
			ret=dtls1_send_newsession_ticket(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_SW_CHANGE_A;
			s->init_num=0;
			break;

		case SSL3_ST_SW_CERT_STATUS_A:
		case SSL3_ST_SW_CERT_STATUS_B:
			ret=ssl3_send_cert_status(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_SW_KEY_EXCH_A;
			s->init_num=0;
			break;

#endif

		case SSL3_ST_SW_CHANGE_A:
		case SSL3_ST_SW_CHANGE_B:

			s->session->cipher=s->s3->tmp.new_cipher;
			if (!s->method->ssl3_enc->setup_key_block(s))
				{ ret= -1; goto end; }

			ret=dtls1_send_change_cipher_spec(s,
				SSL3_ST_SW_CHANGE_A,SSL3_ST_SW_CHANGE_B);

			if (ret <= 0) goto end;

#ifndef OPENSSL_NO_SCTP
			/* Change to new shared key of SCTP-Auth,
			 * will be ignored if no SCTP used.
			 */
			BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY, 0, NULL);
#endif

			s->state=SSL3_ST_SW_FINISHED_A;
			s->init_num=0;

			if (!s->method->ssl3_enc->change_cipher_state(s,
				SSL3_CHANGE_CIPHER_SERVER_WRITE))
				{
				ret= -1;
				goto end;
				}

			dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
			break;

		case SSL3_ST_SW_FINISHED_A:
		case SSL3_ST_SW_FINISHED_B:
			ret=dtls1_send_finished(s,
				SSL3_ST_SW_FINISHED_A,SSL3_ST_SW_FINISHED_B,
				s->method->ssl3_enc->server_finished_label,
				s->method->ssl3_enc->server_finished_label_len);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_SW_FLUSH;
			if (s->hit)
				s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A;
			else
				{
				s->s3->tmp.next_state=SSL_ST_OK;
#ifndef OPENSSL_NO_SCTP
				if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
					{
					s->d1->next_state = s->s3->tmp.next_state;
					s->s3->tmp.next_state=DTLS1_SCTP_ST_SW_WRITE_SOCK;
					}
#endif
				}
			s->init_num=0;
			break;

		case SSL_ST_OK:
			/* clean a few things up */
			ssl3_cleanup_key_block(s);

#if 0
			BUF_MEM_free(s->init_buf);
			s->init_buf=NULL;
#endif

			/* remove buffering on output */
			ssl_free_wbio_buffer(s);

			s->init_num=0;

			if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
				{
				s->renegotiate=0;
				s->new_session=0;
				
				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
				
				s->ctx->stats.sess_accept_good++;
				/* s->server=1; */
				s->handshake_func=dtls1_accept;

				if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
				}
			
			ret = 1;

			/* done handshaking, next message is client hello */
			s->d1->handshake_read_seq = 0;
			/* next message is server hello */
			s->d1->handshake_write_seq = 0;
			s->d1->next_handshake_write_seq = 0;
			goto end;
			/* break; */

		default:
			SSLerr(SSL_F_DTLS1_ACCEPT,SSL_R_UNKNOWN_STATE);
			ret= -1;
			goto end;
			/* break; */
			}
Example #30
0
int
main(int argc, char **argv)
{
	ARGS arg;
#define PROG_NAME_SIZE	39
	char pname[PROG_NAME_SIZE + 1];
	FUNCTION f, *fp;
	const char *prompt;
	char buf[1024];
	char *to_free = NULL;
	int n, i, ret = 0;
	char *p;
	LHASH_OF(FUNCTION) * prog = NULL;
	long errline;

	arg.data = NULL;
	arg.count = 0;

	if (pledge("stdio inet dns rpath wpath cpath proc flock tty", NULL) == -1) {
		fprintf(stderr, "openssl: pledge: %s\n", strerror(errno));
		exit(1);
	}

	bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
	if (bio_err == NULL) {
		fprintf(stderr, "openssl: failed to initialise bio_err\n");
		exit(1);
	}

	if (BIO_sock_init() != 1) {
		BIO_printf(bio_err, "BIO_sock_init failed\n");
		exit(1);
	}

	CRYPTO_set_locking_callback(lock_dbg_cb);

	openssl_startup();

	/* Lets load up our environment a little */
	p = getenv("OPENSSL_CONF");
	if (p == NULL) {
		p = to_free = make_config_name();
		if (p == NULL) {
			BIO_printf(bio_err, "error making config file name\n");
			goto end;
		}
	}

	default_config_file = p;

	config = NCONF_new(NULL);
	i = NCONF_load(config, p, &errline);
	if (i == 0) {
		if (ERR_GET_REASON(ERR_peek_last_error()) ==
		    CONF_R_NO_SUCH_FILE) {
			BIO_printf(bio_err,
			    "WARNING: can't open config file: %s\n", p);
			ERR_clear_error();
			NCONF_free(config);
			config = NULL;
		} else {
			ERR_print_errors(bio_err);
			NCONF_free(config);
			exit(1);
		}
	}

	if (!load_config(bio_err, NULL)) {
		BIO_printf(bio_err, "failed to load configuration\n");
		goto end;
	}

	prog = prog_init();

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

	f.name = pname;
	fp = lh_FUNCTION_retrieve(prog, &f);
	if (fp != NULL) {
		argv[0] = pname;

		single_execution = 1;
		ret = fp->func(argc, argv);
		goto end;
	}
	/*
	 * ok, now check that there are not arguments, if there are, run with
	 * them, shifting the ssleay off the front
	 */
	if (argc != 1) {
		argc--;
		argv++;

		single_execution = 1;
		ret = do_cmd(prog, argc, argv);
		if (ret < 0)
			ret = 0;
		goto end;
	}
	/* ok, lets enter the old 'OpenSSL>' mode */

	for (;;) {
		ret = 0;
		p = buf;
		n = sizeof buf;
		i = 0;
		for (;;) {
			p[0] = '\0';
			if (i++)
				prompt = ">";
			else
				prompt = "OpenSSL> ";
			fputs(prompt, stdout);
			fflush(stdout);
			if (!fgets(p, n, stdin))
				goto end;
			if (p[0] == '\0')
				goto end;
			i = strlen(p);
			if (i <= 1)
				break;
			if (p[i - 2] != '\\')
				break;
			i -= 2;
			p += i;
			n -= i;
		}
		if (!chopup_args(&arg, buf, &argc, &argv))
			break;

		ret = do_cmd(prog, argc, argv);
		if (ret < 0) {
			ret = 0;
			goto end;
		}
		if (ret != 0)
			BIO_printf(bio_err, "error in %s\n", argv[0]);
		(void) BIO_flush(bio_err);
	}
	BIO_printf(bio_err, "bad exit\n");
	ret = 1;

end:
	free(to_free);

	if (config != NULL) {
		NCONF_free(config);
		config = NULL;
	}
	if (prog != NULL)
		lh_FUNCTION_free(prog);
	free(arg.data);

	openssl_shutdown();

	if (bio_err != NULL) {
		BIO_free(bio_err);
		bio_err = NULL;
	}
	return (ret);
}