Ejemplo n.º 1
0
int network_init(server *srv) {
	buffer *b;
	size_t i, j;
	network_backend_t backend;

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
	EC_KEY *ecdh;
	int nid;
#endif
#endif

#ifdef USE_OPENSSL
# ifndef OPENSSL_NO_DH
	DH *dh;
# endif
	BIO *bio;

       /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
	* -----BEGIN DH PARAMETERS-----
	* MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
	* mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
	* +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
	* w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
	* sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
	* jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
	* -----END DH PARAMETERS-----
	*/

	static const unsigned char dh1024_p[]={
		0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
		0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
		0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
		0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
		0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
		0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
		0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
		0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
		0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
		0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
		0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
	};

	static const unsigned char dh1024_g[]={
		0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
		0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
		0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
		0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
		0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
		0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
		0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
		0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
		0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
		0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
		0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
	};
#endif

	struct nb_map {
		network_backend_t nb;
		const char *name;
	} network_backends[] = {
		/* lowest id wins */
#if defined USE_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "sendfile" },
#endif
#if defined USE_LINUX_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "linux-sendfile" },
#endif
#if defined USE_FREEBSD_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "freebsd-sendfile" },
#endif
#if defined USE_SOLARIS_SENDFILEV
		{ NETWORK_BACKEND_SENDFILE,   "solaris-sendfilev" },
#endif
#if defined USE_WRITEV
		{ NETWORK_BACKEND_WRITEV,     "writev" },
#endif
		{ NETWORK_BACKEND_WRITE,      "write" },
		{ NETWORK_BACKEND_UNSET,       NULL }
	};

#ifdef USE_OPENSSL
	/* load SSL certificates */
	for (i = 0; i < srv->config_context->used; i++) {
		specific_config *s = srv->config_storage[i];
#ifndef SSL_OP_NO_COMPRESSION
# define SSL_OP_NO_COMPRESSION 0
#endif
		long ssloptions =
			SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;

		if (buffer_string_is_empty(s->ssl_pemfile) && buffer_string_is_empty(s->ssl_ca_file)) continue;

		if (srv->ssl_is_init == 0) {
			SSL_load_error_strings();
			SSL_library_init();
			OpenSSL_add_all_algorithms();
			srv->ssl_is_init = 1;

			if (0 == RAND_status()) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"not enough entropy in the pool");
				return -1;
			}
		}

		if (!buffer_string_is_empty(s->ssl_pemfile)) {
#ifdef OPENSSL_NO_TLSEXT
			data_config *dc = (data_config *)srv->config_context->data[i];
			if (COMP_HTTP_HOST == dc->comp) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
				return -1;
			}
#endif
			if (network_openssl_load_pemfile(srv, i)) return -1;
		}


		if (!buffer_string_is_empty(s->ssl_ca_file)) {
			s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
			if (NULL == s->ssl_ca_file_cert_names) {
				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
			}
		}

		if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue;

		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		/* completely useless identifier; required for client cert verification to work with sessions */
		if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) {
			log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:",
				"failed to set session context",
				ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		if (s->ssl_empty_fragments) {
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
			ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#else
			ssloptions &= ~0x00000800L; /* hardcode constant */
			log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:",
					"'insert empty fragments' not supported by the openssl version used to compile lighttpd with");
#endif
		}

		SSL_CTX_set_options(s->ssl_ctx, ssloptions);
		SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);

		if (!s->ssl_use_sslv2) {
			/* disable SSLv2 */
			if ((SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) != SSL_OP_NO_SSLv2) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!s->ssl_use_sslv3) {
			/* disable SSLv3 */
			if ((SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) != SSL_OP_NO_SSLv3) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!buffer_string_is_empty(s->ssl_cipher_list)) {
			/* Disable support for low encryption ciphers */
			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}

			if (s->ssl_honor_cipher_order) {
				SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
			}
		}

#ifndef OPENSSL_NO_DH
		/* Support for Diffie-Hellman key exchange */
		if (!buffer_string_is_empty(s->ssl_dh_file)) {
			/* DH parameters from file */
			bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r");
			if (bio == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr);
				return -1;
			}
			dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			BIO_free(bio);
			if (dh == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr);
				return -1;
			}
		} else {
			BIGNUM *dh_p, *dh_g;
			/* Default DH parameters from RFC5114 */
			dh = DH_new();
			if (dh == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed");
				return -1;
			}
			dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL);
			dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL);
			if ((dh_p == NULL) || (dh_g == NULL)) {
				DH_free(dh);
				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed");
				return -1;
			}
		      #if OPENSSL_VERSION_NUMBER < 0x10100000L \
			|| defined(LIBRESSL_VERSION_NUMBER)
			dh->p = dh_p;
			dh->g = dh_g;
			dh->length = 160;
		      #else
			DH_set0_pqg(dh, dh_p, NULL, dh_g);
			DH_set_length(dh, 160);
		      #endif
		}
		SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
		SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
		DH_free(dh);
#else
		if (!buffer_string_is_empty(s->ssl_dh_file)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr);
		}
#endif

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
		/* Support for Elliptic-Curve Diffie-Hellman key exchange */
		if (!buffer_string_is_empty(s->ssl_ec_curve)) {
			/* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
			nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr);
			if (nid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr);
				return -1;
			}
		} else {
			/* Default curve */
			nid = OBJ_sn2nid("prime256v1");
		}
		ecdh = EC_KEY_new_by_curve_name(nid);
		if (ecdh == NULL) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr);
			return -1;
		}
		SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh);
		SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE);
		EC_KEY_free(ecdh);
#endif
#endif

		/* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */
		for (j = 0; j < srv->config_context->used; j++) {
			specific_config *s1 = srv->config_storage[j];

			if (!buffer_string_is_empty(s1->ssl_ca_file)) {
				if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) {
					log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
							ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file);
					return -1;
				}
			}
		}

		if (s->ssl_verifyclient) {
			if (NULL == s->ssl_ca_file_cert_names) {
				log_error_write(srv, __FILE__, __LINE__, "s",
					"SSL: You specified ssl.verifyclient.activate but no ca_file"
				);
				return -1;
			}
			SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names));
			SSL_CTX_set_verify(
				s->ssl_ctx,
				SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
				NULL
			);
			SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
		}

		if (SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
					"Private key does not match the certificate public key, reason:",
					ERR_error_string(ERR_get_error(), NULL),
					s->ssl_pemfile);
			return -1;
		}
		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

# ifndef OPENSSL_NO_TLSEXT
		if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
		    !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					"failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
			return -1;
		}
# endif
	}
#endif

	b = buffer_init();

	buffer_copy_buffer(b, srv->srvconf.bindhost);
	buffer_append_string_len(b, CONST_STR_LEN(":"));
	buffer_append_int(b, srv->srvconf.port);

	if (0 != network_server_init(srv, b, srv->config_storage[0])) {
		buffer_free(b);
		return -1;
	}
	buffer_free(b);

#ifdef USE_OPENSSL
	srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
#endif

	/* get a usefull default */
	backend = network_backends[0].nb;

	/* match name against known types */
	if (!buffer_string_is_empty(srv->srvconf.network_backend)) {
		for (i = 0; network_backends[i].name; i++) {
			/**/
			if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
				backend = network_backends[i].nb;
				break;
			}
		}
		if (NULL == network_backends[i].name) {
			/* we don't know it */

			log_error_write(srv, __FILE__, __LINE__, "sb",
					"server.network-backend has a unknown value:",
					srv->srvconf.network_backend);

			return -1;
		}
	}

	switch(backend) {
	case NETWORK_BACKEND_WRITE:
		srv->network_backend_write = network_write_chunkqueue_write;
		break;
#if defined(USE_WRITEV)
	case NETWORK_BACKEND_WRITEV:
		srv->network_backend_write = network_write_chunkqueue_writev;
		break;
#endif
#if defined(USE_SENDFILE)
	case NETWORK_BACKEND_SENDFILE:
		srv->network_backend_write = network_write_chunkqueue_sendfile;
		break;
#endif
	default:
		return -1;
	}

	/* check for $SERVER["socket"] */
	for (i = 1; i < srv->config_context->used; i++) {
		data_config *dc = (data_config *)srv->config_context->data[i];
		specific_config *s = srv->config_storage[i];

		/* not our stage */
		if (COMP_SERVER_SOCKET != dc->comp) continue;

		if (dc->cond != CONFIG_COND_EQ) continue;

		/* check if we already know this socket,
		 * if yes, don't init it */
		for (j = 0; j < srv->srv_sockets.used; j++) {
			if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
				break;
			}
		}

		if (j == srv->srv_sockets.used) {
			if (0 != network_server_init(srv, dc->string, s)) return -1;
		}
	}

	return 0;
}
Ejemplo n.º 2
0
int MAIN(int argc, char **argv)
	{
	DH *dh=NULL;
	int i,badops=0,text=0;
#ifndef OPENSSL_NO_DSA
	int dsaparam=0;
#endif
	BIO *in=NULL,*out=NULL;
	int informat,outformat,check=0,noout=0,C=0,ret=1;
	char *infile,*outfile,*prog;
	char *inrand=NULL;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif
	int num = 0, g = 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;

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

	prog=argv[0];
	argc--;
	argv++;
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
#ifndef OPENSSL_NO_ENGINE
		else if (strcmp(*argv,"-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine= *(++argv);
			}
#endif
		else if (strcmp(*argv,"-check") == 0)
			check=1;
		else if (strcmp(*argv,"-text") == 0)
			text=1;
#ifndef OPENSSL_NO_DSA
		else if (strcmp(*argv,"-dsaparam") == 0)
			dsaparam=1;
#endif
		else if (strcmp(*argv,"-C") == 0)
			C=1;
		else if (strcmp(*argv,"-noout") == 0)
			noout=1;
		else if (strcmp(*argv,"-2") == 0)
			g=2;
		else if (strcmp(*argv,"-5") == 0)
			g=5;
		else if (strcmp(*argv,"-rand") == 0)
			{
			if (--argc < 1) goto bad;
			inrand= *(++argv);
			}
		else if (((sscanf(*argv,"%d",&num) == 0) || (num <= 0)))
			goto bad;
		argv++;
		argc--;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] [numbits]\n",prog);
		BIO_printf(bio_err,"where options are\n");
		BIO_printf(bio_err," -inform arg   input format - one of DER PEM\n");
		BIO_printf(bio_err," -outform arg  output format - one of DER PEM\n");
		BIO_printf(bio_err," -in arg       input file\n");
		BIO_printf(bio_err," -out arg      output file\n");
#ifndef OPENSSL_NO_DSA
		BIO_printf(bio_err," -dsaparam     read or generate DSA parameters, convert to DH\n");
#endif
		BIO_printf(bio_err," -check        check the DH parameters\n");
		BIO_printf(bio_err," -text         print a text form of the DH parameters\n");
		BIO_printf(bio_err," -C            Output C code\n");
		BIO_printf(bio_err," -2            generate parameters using  2 as the generator value\n");
		BIO_printf(bio_err," -5            generate parameters using  5 as the generator value\n");
		BIO_printf(bio_err," numbits       number of bits in to generate (default 2048)\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...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
		BIO_printf(bio_err,"               - load the file (or the files in the directory) into\n");
		BIO_printf(bio_err,"               the random number generator\n");
		BIO_printf(bio_err," -noout        no output\n");
		goto end;
		}

	ERR_load_crypto_strings();

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

	if (g && !num)
		num = DEFBITS;

#ifndef OPENSSL_NO_DSA
	if (dsaparam)
		{
		if (g)
			{
			BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n");
			goto end;
			}
		}
	else
#endif
		{
		/* DH parameters */
		if (num && !g)
			g = 2;
		}

	if(num) {

		BN_GENCB cb;
		BN_GENCB_set(&cb, dh_cb, bio_err);
		if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL)
			{
			BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n");
			}
		if (inrand != NULL)
			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
				app_RAND_load_files(inrand));

#ifndef OPENSSL_NO_DSA
		if (dsaparam)
			{
			DSA *dsa = DSA_new();
			
			BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num);
			if(!dsa || !DSA_generate_parameters_ex(dsa, num,
						NULL, 0, NULL, NULL, &cb))
				{
				if(dsa) DSA_free(dsa);
				ERR_print_errors(bio_err);
				goto end;
				}

			dh = DSA_dup_DH(dsa);
			DSA_free(dsa);
			if (dh == NULL)
				{
				ERR_print_errors(bio_err);
				goto end;
				}
			}
		else
#endif
			{
			dh = DH_new();
			BIO_printf(bio_err,"Generating DH parameters, %d bit long safe prime, generator %d\n",num,g);
			BIO_printf(bio_err,"This is going to take a long time\n");
			if(!dh || !DH_generate_parameters_ex(dh, num, g, &cb))
				{
				ERR_print_errors(bio_err);
				goto end;
				}
			}

		app_RAND_write_file(NULL, bio_err);
	} else {

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

		if	(informat != FORMAT_ASN1 && informat != FORMAT_PEM)
			{
			BIO_printf(bio_err,"bad input format specified\n");
			goto end;
			}

#ifndef OPENSSL_NO_DSA
		if (dsaparam)
			{
			DSA *dsa;
			
			if (informat == FORMAT_ASN1)
				dsa=d2i_DSAparams_bio(in,NULL);
			else /* informat == FORMAT_PEM */
				dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL);
			
			if (dsa == NULL)
				{
				BIO_printf(bio_err,"unable to load DSA parameters\n");
				ERR_print_errors(bio_err);
				goto end;
				}
			
			dh = DSA_dup_DH(dsa);
			DSA_free(dsa);
			if (dh == NULL)
				{
				ERR_print_errors(bio_err);
				goto end;
				}
			}
		else
#endif
			{
			if (informat == FORMAT_ASN1)
				dh=d2i_DHparams_bio(in,NULL);
			else /* informat == FORMAT_PEM */
				dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL);
			
			if (dh == NULL)
				{
				BIO_printf(bio_err,"unable to load DH parameters\n");
				ERR_print_errors(bio_err);
				goto end;
				}
			}
		
		/* dh != NULL */
	}
	
	out=BIO_new(BIO_s_file());
	if (out == NULL)
		{
		ERR_print_errors(bio_err);
		goto end;
		}
	if (outfile == NULL)
		{
		BIO_set_fp(out,stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outfile) <= 0)
			{
			perror(outfile);
			goto end;
			}
		}


	if (text)
		{
		DHparams_print(out,dh);
		}
	
	if (check)
		{
		if (!DH_check(dh,&i))
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		if (i & DH_CHECK_P_NOT_PRIME)
			printf("p value is not prime\n");
		if (i & DH_CHECK_P_NOT_SAFE_PRIME)
			printf("p value is not a safe prime\n");
		if (i & DH_UNABLE_TO_CHECK_GENERATOR)
			printf("unable to check the generator value\n");
		if (i & DH_NOT_SUITABLE_GENERATOR)
			printf("the g value is not a generator\n");
		if (i == 0)
			printf("DH parameters appear to be ok.\n");
		}
	if (C)
		{
		unsigned char *data;
		int len,l,bits;

		len=BN_num_bytes(dh->p);
		bits=BN_num_bits(dh->p);
		data=(unsigned char *)OPENSSL_malloc(len);
		if (data == NULL)
			{
			perror("OPENSSL_malloc");
			goto end;
			}
		printf("#ifndef HEADER_DH_H\n"
		       "#include <openssl/dh.h>\n"
		       "#endif\n");
		printf("DH *get_dh%d()\n\t{\n",bits);

		l=BN_bn2bin(dh->p,data);
		printf("\tstatic unsigned char dh%d_p[]={",bits);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) printf("\n\t\t");
			printf("0x%02X,",data[i]);
			}
		printf("\n\t\t};\n");

		l=BN_bn2bin(dh->g,data);
		printf("\tstatic unsigned char dh%d_g[]={",bits);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) printf("\n\t\t");
			printf("0x%02X,",data[i]);
			}
		printf("\n\t\t};\n");

		printf("\tDH *dh;\n\n");
		printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n");
		printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n",
			bits,bits);
		printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n",
			bits,bits);
		printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
		printf("\t\t{ DH_free(dh); return(NULL); }\n");
		if (dh->length)
			printf("\tdh->length = %ld;\n", dh->length);
		printf("\treturn(dh);\n\t}\n");
		OPENSSL_free(data);
		}


	if (!noout)
		{
		if 	(outformat == FORMAT_ASN1)
			i=i2d_DHparams_bio(out,dh);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_DHparams(out,dh);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i)
			{
			BIO_printf(bio_err,"unable to write DH parameters\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		}
	ret=0;
end:
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	if (dh != NULL) DH_free(dh);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Ejemplo n.º 3
0
int ssl_server_init(char* ca_file, char *crt_file, char *key_file, char *dhp_file, char *ssl_cipher_list)
{
	static const char *ssl_ctx_id = "httpd";
	long ssl_options;

	if (!crt_file || !f_exists(crt_file)) {
		httpd_log("%s: Server certificate (%s) is not found!", SYSLOG_ID_SSL, crt_file);
		httpd_log("Please manual build the certificate via \"%s\" script.", "https-cert.sh");
		return -1;
	}

	if (!key_file || !f_exists(key_file)) {
		httpd_log("%s: Server private key (%s) is not found!", SYSLOG_ID_SSL, key_file);
		httpd_log("Please manual build the certificate via \"%s\" script.", "https-cert.sh");
		return -1;
	}

	SSL_load_error_strings();
	SSL_library_init();

	ssl_ctx = SSL_CTX_new(SSLv23_server_method());
	if (!ssl_ctx) {
		httpd_log("%s: Unable to create SSL context!", SYSLOG_ID_SSL);
		return -1;
	}

	ssl_options = SSL_OP_ALL | SSL_OP_NO_COMPRESSION | SSL_OP_NO_SSLv2 |
			SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;

	SSL_CTX_set_options(ssl_ctx, ssl_options);
	SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);

	if (ssl_cipher_list && strlen(ssl_cipher_list) > 2) {
		if (SSL_CTX_set_cipher_list(ssl_ctx, ssl_cipher_list) != 1) {
			httpd_log("%s: Cannot set SSL cipher list (%s)!", SYSLOG_ID_SSL, ssl_cipher_list);
		} else {
			SSL_CTX_set_options(ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
		}
	}

	if (ca_file && f_exists(ca_file)) {
		if (SSL_CTX_load_verify_locations(ssl_ctx, ca_file, NULL) != 1) {
			httpd_log("%s: Cannot load CA certificate (%s)!", SYSLOG_ID_SSL, ca_file);
		}
	}

	if (SSL_CTX_use_certificate_file(ssl_ctx, crt_file, SSL_FILETYPE_PEM) != 1) {
		httpd_log("%s: Cannot load server certificate (%s)!", SYSLOG_ID_SSL, crt_file);
		ssl_server_uninit();
		return 1;
	}

	if (SSL_CTX_use_PrivateKey_file(ssl_ctx, key_file, SSL_FILETYPE_PEM) != 1) {
		httpd_log("%s: Cannot load server private key (%s)!", SYSLOG_ID_SSL, key_file);
		ssl_server_uninit();
		return 1;
	}

	if (SSL_CTX_check_private_key(ssl_ctx) != 1) {
		httpd_log("%s: Private key does not match the certificate!", SYSLOG_ID_SSL);
		ssl_server_uninit();
		return 1;
	}

	if (dhp_file && f_exists(dhp_file)) {
		/* DH parameters from file */
		BIO *bio = BIO_new_file(dhp_file, "r");
		if (bio) {
			DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			BIO_free(bio);
			if (dh) {
				SSL_CTX_set_tmp_dh(ssl_ctx, dh);
				SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE);
				DH_free(dh);
			} else {
				httpd_log("%s: Cannot load DH parameters (%s)!", SYSLOG_ID_SSL, dhp_file);
			}
		}
	} else {
		/* Default DH parameters from RFC5114 */
		DH *dh = DH_new();
		if (dh) {
			dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
			dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
			dh->length = 160;
			if (dh->p && dh->g) {
				SSL_CTX_set_tmp_dh(ssl_ctx, dh);
				SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_DH_USE);
			}
			DH_free(dh);
		}
	}

	SSL_CTX_set_default_read_ahead(ssl_ctx, 1);

	SSL_CTX_set_session_cache_mode(ssl_ctx, SSL_SESS_CACHE_SERVER);
	SSL_CTX_set_session_id_context(ssl_ctx, (unsigned char *)ssl_ctx_id, strlen(ssl_ctx_id));
	SSL_CTX_sess_set_cache_size(ssl_ctx, 10);

	SSL_CTX_set_info_callback(ssl_ctx, http_ssl_info_cb);

	return 0;
}
Ejemplo n.º 4
0
int main(int argc, char **argv)
{
    SSL_library_init();
    SSL_load_error_strings();

    BIO * bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

    /* Set up a SIGPIPE handler */
    signal(SIGPIPE, SIG_IGN);

    /* Create our context*/
    SSL_CTX * ctx = SSL_CTX_new(SSLv23_method());

    /* Load our keys and certificates*/
    if(!(SSL_CTX_use_certificate_chain_file(ctx, "ftests/fixtures/rdpproxy-cert.pem")))
    {
        BIO_printf(bio_err, "Can't read certificate file\n");
        ERR_print_errors(bio_err);
        exit(0);
    }

    SSL_CTX_set_default_passwd_cb(ctx, password_cb0);
    SSL_CTX_set_default_passwd_cb_userdata(ctx, const_cast<char *>("inquisition"));
    if(!(SSL_CTX_use_PrivateKey_file(ctx, "ftests/fixtures/rdpproxy-key.pem", SSL_FILETYPE_PEM)))
    {
        BIO_printf(bio_err,"Can't read key file\n");
        ERR_print_errors(bio_err);
        exit(0);
    }

    DH *ret=nullptr;
    BIO *bio;

    if ((bio=BIO_new_file("ftests/fixtures/dh1024.pem","r")) == nullptr){
        BIO_printf(bio_err,"Couldn't open DH file\n");
        ERR_print_errors(bio_err);
        exit(0);
    }

    ret=PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr);
    BIO_free(bio);
    if(SSL_CTX_set_tmp_dh(ctx, ret)<0)
    {
        BIO_printf(bio_err,"Couldn't set DH parameters\n");
        ERR_print_errors(bio_err);
        exit(0);
    }


    union
    {
      struct sockaddr s;
      struct sockaddr_storage ss;
      struct sockaddr_in s4;
      struct sockaddr_in6 s6;
    } ucs;
    memset(&ucs, 0, sizeof(ucs));

    int val=1;

    int sock = socket(AF_INET, SOCK_STREAM,0);
    if(sock < 0) {
        fprintf(stderr, "Failed to make socket\n");
        exit(0);
    }

    memset(&ucs.s4, 0, sizeof(ucs));
    ucs.s4.sin_addr.s_addr = INADDR_ANY;
    ucs.s4.sin_family = AF_INET;
    ucs.s4.sin_port = htons(4433);
    setsockopt(sock,SOL_SOCKET,SO_REUSEADDR, &val,sizeof(val));

    int bind_res = bind(sock,&ucs.s,  sizeof(ucs));
    if(bind_res < 0){
        fprintf(stderr, "Failed to bind\n");
        exit(0);
    }
    listen(sock,5);

    while(1){
      int s = accept(sock,nullptr,nullptr);
      if(s < 0){
        fprintf(stderr,"Problem accepting\n");
        exit(0);
      }

     pid_t pid = fork();

     if(pid){
       close(s);
     }
     else {
        rdp_serve(ctx, s, bio_err);
        exit(0);
      }
    }
    SSL_CTX_free(ctx);
    exit(0);
  }
Ejemplo n.º 5
0
int MAIN(int argc, char **argv)
	{
#ifndef OPENSSL_NO_ENGINE
	ENGINE *e = NULL;
#endif
	DH *dh=NULL;
	int i,badops=0,text=0;
	BIO *in=NULL,*out=NULL;
	int informat,outformat,check=0,noout=0,C=0,ret=1;
	char *infile,*outfile,*prog;
#ifndef OPENSSL_NO_ENGINE
	char *engine;
#endif

	apps_startup();

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

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

#ifndef OPENSSL_NO_ENGINE
	engine=NULL;
#endif
	infile=NULL;
	outfile=NULL;
	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

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

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog);
		BIO_printf(bio_err,"where options are\n");
		BIO_printf(bio_err," -inform arg   input format - one of DER PEM\n");
		BIO_printf(bio_err," -outform arg  output format - one of DER PEM\n");
		BIO_printf(bio_err," -in arg       input file\n");
		BIO_printf(bio_err," -out arg      output file\n");
		BIO_printf(bio_err," -check        check the DH parameters\n");
		BIO_printf(bio_err," -text         print a text form of the DH parameters\n");
		BIO_printf(bio_err," -C            Output C code\n");
		BIO_printf(bio_err," -noout        no output\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err," -engine e     use engine e, possibly a hardware device.\n");
#endif
		goto end;
		}

	ERR_load_crypto_strings();

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

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

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

	if	(informat == FORMAT_ASN1)
		dh=d2i_DHparams_bio(in,NULL);
	else if (informat == FORMAT_PEM)
		dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL);
	else
		{
		BIO_printf(bio_err,"bad input format specified\n");
		goto end;
		}
	if (dh == NULL)
		{
		BIO_printf(bio_err,"unable to load DH parameters\n");
		ERR_print_errors(bio_err);
		goto end;
		}

	

	if (text)
		{
		DHparams_print(out,dh);
#ifdef undef
		TINYCLR_SSL_PRINTF("p=");
		BN_print(OPENSSL_TYPE__FILE_STDOUT,dh->p);
		TINYCLR_SSL_PRINTF("\ng=");
		BN_print(OPENSSL_TYPE__FILE_STDOUT,dh->g);
		TINYCLR_SSL_PRINTF("\n");
		if (dh->length != 0)
			TINYCLR_SSL_PRINTF("recommended private length=%ld\n",dh->length);
#endif
		}
	
	if (check)
		{
		if (!DH_check(dh,&i))
			{
			ERR_print_errors(bio_err);
			goto end;
			}
		if (i & DH_CHECK_P_NOT_PRIME)
			TINYCLR_SSL_PRINTF("p value is not prime\n");
		if (i & DH_CHECK_P_NOT_SAFE_PRIME)
			TINYCLR_SSL_PRINTF("p value is not a safe prime\n");
		if (i & DH_UNABLE_TO_CHECK_GENERATOR)
			TINYCLR_SSL_PRINTF("unable to check the generator value\n");
		if (i & DH_NOT_SUITABLE_GENERATOR)
			TINYCLR_SSL_PRINTF("the g value is not a generator\n");
		if (i == 0)
			TINYCLR_SSL_PRINTF("DH parameters appear to be ok.\n");
		}
	if (C)
		{
		unsigned char *data;
		int len,l,bits;

		len=BN_num_bytes(dh->p);
		bits=BN_num_bits(dh->p);
		data=(unsigned char *)OPENSSL_malloc(len);
		if (data == NULL)
			{
			TINYCLR_SSL_PERROR("OPENSSL_malloc");
			goto end;
			}
		l=BN_bn2bin(dh->p,data);
		TINYCLR_SSL_PRINTF("static unsigned char dh%d_p[]={",bits);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) TINYCLR_SSL_PRINTF("\n\t");
			TINYCLR_SSL_PRINTF("0x%02X,",data[i]);
			}
		TINYCLR_SSL_PRINTF("\n\t};\n");

		l=BN_bn2bin(dh->g,data);
		TINYCLR_SSL_PRINTF("static unsigned char dh%d_g[]={",bits);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) TINYCLR_SSL_PRINTF("\n\t");
			TINYCLR_SSL_PRINTF("0x%02X,",data[i]);
			}
		TINYCLR_SSL_PRINTF("\n\t};\n\n");

		TINYCLR_SSL_PRINTF("DH *get_dh%d()\n\t{\n",bits);
		TINYCLR_SSL_PRINTF("\tDH *dh;\n\n");
		TINYCLR_SSL_PRINTF("\tif ((dh=DH_new()) == NULL) return(NULL);\n");
		TINYCLR_SSL_PRINTF("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n",
			bits,bits);
		TINYCLR_SSL_PRINTF("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n",
			bits,bits);
		TINYCLR_SSL_PRINTF("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
		TINYCLR_SSL_PRINTF("\t\treturn(NULL);\n");
		TINYCLR_SSL_PRINTF("\treturn(dh);\n\t}\n");
		OPENSSL_free(data);
		}


	if (!noout)
		{
		if 	(outformat == FORMAT_ASN1)
			i=i2d_DHparams_bio(out,dh);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_DHparams(out,dh);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i)
			{
			BIO_printf(bio_err,"unable to write DH parameters\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		}
	ret=0;
end:
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	if (dh != NULL) DH_free(dh);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Ejemplo n.º 6
0
int
dhparam_main(int argc, char **argv)
{
	BIO *in = NULL, *out = NULL;
	char *num_bits = NULL;
	DH *dh = NULL;
	int num = 0;
	int ret = 1;
	int i;

	if (single_execution) {
		if (pledge("stdio rpath wpath cpath", NULL) == -1) {
			perror("pledge");
			exit(1);
		}
	}

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

	dhparam_config.informat = FORMAT_PEM;
	dhparam_config.outformat = FORMAT_PEM;

	if (options_parse(argc, argv, dhparam_options, &num_bits, NULL) != 0) {
		dhparam_usage();
		return (1);
	}

	if (num_bits != NULL) {
		if(sscanf(num_bits, "%d", &num) == 0 || num <= 0) {
			BIO_printf(bio_err, "invalid number of bits: %s\n",
			    num_bits);
			return (1);
		}
	}

	if (dhparam_config.g && !num)
		num = DEFBITS;

	if (dhparam_config.dsaparam) {
		if (dhparam_config.g) {
			BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n");
			goto end;
		}
	} else {
		/* DH parameters */
		if (num && !dhparam_config.g)
			dhparam_config.g = 2;
	}

	if (num) {

		BN_GENCB cb;
		BN_GENCB_set(&cb, dh_cb, bio_err);
		if (dhparam_config.dsaparam) {
			DSA *dsa = DSA_new();

			BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num);
			if (!dsa || !DSA_generate_parameters_ex(dsa, num,
				NULL, 0, NULL, NULL, &cb)) {
				if (dsa)
					DSA_free(dsa);
				ERR_print_errors(bio_err);
				goto end;
			}
			dh = DSA_dup_DH(dsa);
			DSA_free(dsa);
			if (dh == NULL) {
				ERR_print_errors(bio_err);
				goto end;
			}
		} else {
			dh = DH_new();
			BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime, generator %d\n", num, dhparam_config.g);
			BIO_printf(bio_err, "This is going to take a long time\n");
			if (!dh || !DH_generate_parameters_ex(dh, num, dhparam_config.g, &cb)) {
				ERR_print_errors(bio_err);
				goto end;
			}
		}
	} else {

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

		if (dhparam_config.informat != FORMAT_ASN1 &&
		    dhparam_config.informat != FORMAT_PEM) {
			BIO_printf(bio_err, "bad input format specified\n");
			goto end;
		}
		if (dhparam_config.dsaparam) {
			DSA *dsa;

			if (dhparam_config.informat == FORMAT_ASN1)
				dsa = d2i_DSAparams_bio(in, NULL);
			else	/* informat == FORMAT_PEM */
				dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);

			if (dsa == NULL) {
				BIO_printf(bio_err, "unable to load DSA parameters\n");
				ERR_print_errors(bio_err);
				goto end;
			}
			dh = DSA_dup_DH(dsa);
			DSA_free(dsa);
			if (dh == NULL) {
				ERR_print_errors(bio_err);
				goto end;
			}
		} else
		{
			if (dhparam_config.informat == FORMAT_ASN1)
				dh = d2i_DHparams_bio(in, NULL);
			else	/* informat == FORMAT_PEM */
				dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);

			if (dh == NULL) {
				BIO_printf(bio_err, "unable to load DH parameters\n");
				ERR_print_errors(bio_err);
				goto end;
			}
		}

		/* dh != NULL */
	}

	out = BIO_new(BIO_s_file());
	if (out == NULL) {
		ERR_print_errors(bio_err);
		goto end;
	}
	if (dhparam_config.outfile == NULL) {
		BIO_set_fp(out, stdout, BIO_NOCLOSE);
	} else {
		if (BIO_write_filename(out, dhparam_config.outfile) <= 0) {
			perror(dhparam_config.outfile);
			goto end;
		}
	}


	if (dhparam_config.text) {
		DHparams_print(out, dh);
	}
	if (dhparam_config.check) {
		if (!DH_check(dh, &i)) {
			ERR_print_errors(bio_err);
			goto end;
		}
		if (i & DH_CHECK_P_NOT_PRIME)
			printf("p value is not prime\n");
		if (i & DH_CHECK_P_NOT_SAFE_PRIME)
			printf("p value is not a safe prime\n");
		if (i & DH_UNABLE_TO_CHECK_GENERATOR)
			printf("unable to check the generator value\n");
		if (i & DH_NOT_SUITABLE_GENERATOR)
			printf("the g value is not a generator\n");
		if (i == 0)
			printf("DH parameters appear to be ok.\n");
	}
	if (dhparam_config.C) {
		unsigned char *data;
		int len, l, bits;

		len = BN_num_bytes(dh->p);
		bits = BN_num_bits(dh->p);
		data = malloc(len);
		if (data == NULL) {
			perror("malloc");
			goto end;
		}
		printf("#ifndef HEADER_DH_H\n"
		    "#include <openssl/dh.h>\n"
		    "#endif\n");
		printf("DH *get_dh%d()\n\t{\n", bits);

		l = BN_bn2bin(dh->p, data);
		printf("\tstatic unsigned char dh%d_p[] = {", bits);
		for (i = 0; i < l; i++) {
			if ((i % 12) == 0)
				printf("\n\t\t");
			printf("0x%02X, ", data[i]);
		}
		printf("\n\t\t};\n");

		l = BN_bn2bin(dh->g, data);
		printf("\tstatic unsigned char dh%d_g[] = {", bits);
		for (i = 0; i < l; i++) {
			if ((i % 12) == 0)
				printf("\n\t\t");
			printf("0x%02X, ", data[i]);
		}
		printf("\n\t\t};\n");

		printf("\tDH *dh;\n\n");
		printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n");
		printf("\tdh->p = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n",
		    bits, bits);
		printf("\tdh->g = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n",
		    bits, bits);
		printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
		printf("\t\t{ DH_free(dh); return(NULL); }\n");
		if (dh->length)
			printf("\tdh->length = %ld;\n", dh->length);
		printf("\treturn(dh);\n\t}\n");
		free(data);
	}
	if (!dhparam_config.noout) {
		if (dhparam_config.outformat == FORMAT_ASN1)
			i = i2d_DHparams_bio(out, dh);
		else if (dhparam_config.outformat == FORMAT_PEM)
			i = PEM_write_bio_DHparams(out, dh);
		else {
			BIO_printf(bio_err, "bad output format specified for outfile\n");
			goto end;
		}
		if (!i) {
			BIO_printf(bio_err, "unable to write DH parameters\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	ret = 0;

end:
	BIO_free(in);
	if (out != NULL)
		BIO_free_all(out);
	if (dh != NULL)
		DH_free(dh);

	return (ret);
}
Ejemplo n.º 7
0
int
rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile)
{
	DH *dh;
	unsigned long err;
	if(cert == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No certificate file");
		return 0;
	}
	if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, cert) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, cert))
	{
		err = ERR_get_error();
		rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert,
			   get_ssl_error(err));
		return 0;
	}

	if(keyfile == NULL)
	{
		rb_lib_log("rb_setup_ssl_server: No key file");
		return 0;
	}


	if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM))
	{
		err = ERR_get_error();
		rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile,
			   get_ssl_error(err));
		return 0;
	}

	if(dhfile != NULL)
	{
		/* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */
		BIO *bio = BIO_new_file(dhfile, "r");
		if(bio != NULL)
		{
			dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			if(dh == NULL)
			{
				err = ERR_get_error();
				rb_lib_log
					("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
					 dhfile, get_ssl_error(err));
				BIO_free(bio);
				return 0;
			}
			BIO_free(bio);
			SSL_CTX_set_tmp_dh(ssl_server_ctx, dh);
		}
		else
		{
			err = ERR_get_error();
			rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s",
				   dhfile, get_ssl_error(err));
		}
	}
	return 1;
}
Ejemplo n.º 8
0
void Context::initDH(const std::string& dhParamsFile)
{
#ifndef OPENSSL_NO_DH
    // 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
	// -----BEGIN DH PARAMETERS-----
	// MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
	// mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
	// +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
	// w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
	// sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
	// jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
	// -----END DH PARAMETERS-----
	//

	static const unsigned char dh1024_p[] = 
	{
		0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
		0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
		0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
		0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
		0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
		0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
		0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
		0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
		0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
		0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
		0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
	};

	static const unsigned char dh1024_g[] = 
	{
		0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
		0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
		0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
		0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
		0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
		0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
		0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
		0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
		0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
		0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
		0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
	};

	DH* dh = 0;
	if (!dhParamsFile.empty()) 
	{
		BIO* bio = BIO_new_file(dhParamsFile.c_str(), "r");
		if (!bio) 
		{
			std::string msg = Utility::getLastError();
			throw SSLContextException(std::string("Error opening Diffie-Hellman parameters file ") + dhParamsFile, msg);
		}
		dh = PEM_read_bio_DHparams(bio, 0, 0, 0);
		BIO_free(bio);
		if (!dh) 
		{
			std::string msg = Utility::getLastError();
			throw SSLContextException(std::string("Error reading Diffie-Hellman parameters from file ") + dhParamsFile, msg);
		}
	} 
	else 
	{
		dh = DH_new();
		if (!dh) 
		{
			std::string msg = Utility::getLastError();
			throw SSLContextException("Error creating Diffie-Hellman parameters", msg);
		}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
		BIGNUM* p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0);
		BIGNUM* g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0);
		DH_set0_pqg(dh, p, 0, g);
		DH_set_length(dh, 160);
		if (!p || !g)
		{
			DH_free(dh);
			throw SSLContextException("Error creating Diffie-Hellman parameters");
		}
#else
		dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0);
		dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0);
		dh->length = 160;
		if ((!dh->p) || (!dh->g)) 
		{
			DH_free(dh);
			throw SSLContextException("Error creating Diffie-Hellman parameters");
		}
#endif
	}
	SSL_CTX_set_tmp_dh(_pSSLContext, dh);
	SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_DH_USE);
	DH_free(dh);
#else
	if (!dhParamsFile.empty())
		throw SSLContextException("OpenSSL does not support DH");
#endif
}
Ejemplo n.º 9
0
LQ_EXTERN_C void* LQ_CALL LqConnSslCreate
(
    const void* MethodSSL, /* Example SSLv23_method()*/
    const char* CertFile, /* Example: "server.pem"*/
    const char* KeyFile, /*Example: "server.key"*/
    const char* CipherList,
    int TypeCertFile, /*SSL_FILETYPE_ASN1 (The file is in abstract syntax notation 1 (ASN.1) format.) or SSL_FILETYPE_PEM (The file is in base64 privacy enhanced mail (PEM) format.)*/
    const char* CAFile,
    const char* DhpFile
) {
#ifdef HAVE_OPENSSL

    static const unsigned char dh1024_p[] = {
        0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
        0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
        0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
        0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
        0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
        0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
        0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
        0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
        0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
        0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
        0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
    };

    static const unsigned char dh1024_g[] = {
        0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
        0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
        0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
        0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
        0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
        0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
        0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
        0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
        0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
        0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
        0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
    };

    SSL_CTX* NewCtx = NULL;

    bool r = false;
    static bool IsLoaded = false;

	if(MethodSSL == NULL)
		MethodSSL = SSLv23_server_method();
	
	do {
		if(!IsLoaded) {
			IsLoaded = true;
			SSL_library_init();
			OpenSSL_add_all_algorithms();
			SSL_load_error_strings();
		}

		if((NewCtx = SSL_CTX_new((const SSL_METHOD*)MethodSSL)) == NULL)
			break;
		SSL_CTX_set_read_ahead(NewCtx, 1);
		SSL_CTX_set_verify(NewCtx, SSL_VERIFY_NONE, NULL);

		if(CipherList != NULL) {
			if(SSL_CTX_set_cipher_list(NewCtx, CipherList) == 1)
				SSL_CTX_set_options(NewCtx, SSL_OP_CIPHER_SERVER_PREFERENCE);
		}

		if(CAFile != NULL) {
			if(!SSL_CTX_load_verify_locations(NewCtx, CAFile, NULL)) {
				SSL_CTX_free(NewCtx);
				NewCtx = NULL;
				break;
			}

		}
		if((SSL_CTX_use_certificate_file(NewCtx, CertFile, TypeCertFile) <= 0) ||
			(SSL_CTX_use_PrivateKey_file(NewCtx, KeyFile, TypeCertFile) <= 0)) {
			SSL_CTX_free(NewCtx);
			NewCtx = NULL;
			break;
		}

		if(SSL_CTX_check_private_key(NewCtx) != 1) {
			SSL_CTX_free(NewCtx);
			NewCtx = NULL;
			break;
		}

		if(DhpFile != NULL) {
			BIO *bio = BIO_new_file(DhpFile, "r");
			if(bio) {
				DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
				BIO_free(bio);
				if(dh) {
					SSL_CTX_set_tmp_dh(NewCtx, dh);
					SSL_CTX_set_options(NewCtx, SSL_OP_SINGLE_DH_USE);
					DH_free(dh);
				}
			}
		} else {
			DH *dh = DH_new();
			if(dh) {
				dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL);
				dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL);
				dh->length = 160;
				if(dh->p && dh->g) {
					SSL_CTX_set_tmp_dh(NewCtx, dh);
					SSL_CTX_set_options(NewCtx, SSL_OP_SINGLE_DH_USE);
				}
				DH_free(dh);
			}
		}
	} while(false);
    return NewCtx;
#else
	lq_errno_set(ENOSYS);
    return NULL;
#endif
}
Ejemplo n.º 10
0
int
dh_main(int argc, char **argv)
{
    DH *dh = NULL;
    int i, badops = 0, text = 0;
    BIO *in = NULL, *out = NULL;
    int informat, outformat, check = 0, noout = 0, C = 0, ret = 1;
    char *infile, *outfile, *prog;
#ifndef OPENSSL_NO_ENGINE
    char *engine;
#endif

#ifndef OPENSSL_NO_ENGINE
    engine = NULL;
#endif
    infile = NULL;
    outfile = NULL;
    informat = FORMAT_PEM;
    outformat = FORMAT_PEM;

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

    if (badops) {
bad:
        BIO_printf(bio_err, "%s [options] <infile >outfile\n", prog);
        BIO_printf(bio_err, "where options are\n");
        BIO_printf(bio_err, " -inform arg   input format - one of DER PEM\n");
        BIO_printf(bio_err, " -outform arg  output format - one of DER PEM\n");
        BIO_printf(bio_err, " -in arg       input file\n");
        BIO_printf(bio_err, " -out arg      output file\n");
        BIO_printf(bio_err, " -check        check the DH parameters\n");
        BIO_printf(bio_err, " -text         print a text form of the DH parameters\n");
        BIO_printf(bio_err, " -C            Output C code\n");
        BIO_printf(bio_err, " -noout        no output\n");
#ifndef OPENSSL_NO_ENGINE
        BIO_printf(bio_err, " -engine e     use engine e, possibly a hardware device.\n");
#endif
        goto end;
    }

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

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

    if (informat == FORMAT_ASN1)
        dh = d2i_DHparams_bio(in, NULL);
    else if (informat == FORMAT_PEM)
        dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
    else {
        BIO_printf(bio_err, "bad input format specified\n");
        goto end;
    }
    if (dh == NULL) {
        BIO_printf(bio_err, "unable to load DH parameters\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    if (text) {
        DHparams_print(out, dh);
    }
    if (check) {
        if (!DH_check(dh, &i)) {
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i & DH_CHECK_P_NOT_PRIME)
            printf("p value is not prime\n");
        if (i & DH_CHECK_P_NOT_SAFE_PRIME)
            printf("p value is not a safe prime\n");
        if (i & DH_UNABLE_TO_CHECK_GENERATOR)
            printf("unable to check the generator value\n");
        if (i & DH_NOT_SUITABLE_GENERATOR)
            printf("the g value is not a generator\n");
        if (i == 0)
            printf("DH parameters appear to be ok.\n");
    }
    if (C) {
        unsigned char *data;
        int len, l, bits;

        len = BN_num_bytes(dh->p);
        bits = BN_num_bits(dh->p);
        data = malloc(len);
        if (data == NULL) {
            perror("malloc");
            goto end;
        }
        l = BN_bn2bin(dh->p, data);
        printf("static unsigned char dh%d_p[] = {", bits);
        for (i = 0; i < l; i++) {
            if ((i % 12) == 0)
                printf("\n\t");
            printf("0x%02X, ", data[i]);
        }
        printf("\n\t};\n");

        l = BN_bn2bin(dh->g, data);
        printf("static unsigned char dh%d_g[] = {", bits);
        for (i = 0; i < l; i++) {
            if ((i % 12) == 0)
                printf("\n\t");
            printf("0x%02X, ", data[i]);
        }
        printf("\n\t};\n\n");

        printf("DH *get_dh%d()\n\t{\n", bits);
        printf("\tDH *dh;\n\n");
        printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n");
        printf("\tdh->p = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n",
               bits, bits);
        printf("\tdh->g = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n",
               bits, bits);
        printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
        printf("\t\treturn(NULL);\n");
        printf("\treturn(dh);\n\t}\n");
        free(data);
    }
    if (!noout) {
        if (outformat == FORMAT_ASN1)
            i = i2d_DHparams_bio(out, dh);
        else if (outformat == FORMAT_PEM)
            i = PEM_write_bio_DHparams(out, dh);
        else {
            BIO_printf(bio_err, "bad output format specified for outfile\n");
            goto end;
        }
        if (!i) {
            BIO_printf(bio_err, "unable to write DH parameters\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    }
    ret = 0;

end:
    BIO_free(in);
    if (out != NULL)
        BIO_free_all(out);
    if (dh != NULL)
        DH_free(dh);

    return (ret);
}
Ejemplo n.º 11
0
int
dh_main(int argc, char **argv)
{
	DH *dh = NULL;
	int i;
	BIO *in = NULL, *out = NULL;
	int ret = 1;

	if (single_execution) {
		if (pledge("stdio rpath wpath cpath", NULL) == -1) {
			perror("pledge");
			exit(1);
		}
	}

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

	dh_config.informat = FORMAT_PEM;
	dh_config.outformat = FORMAT_PEM;

	if (options_parse(argc, argv, dh_options, NULL, NULL) != 0) {
		dh_usage();
		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 (dh_config.infile == NULL)
		BIO_set_fp(in, stdin, BIO_NOCLOSE);
	else {
		if (BIO_read_filename(in, dh_config.infile) <= 0) {
			perror(dh_config.infile);
			goto end;
		}
	}
	if (dh_config.outfile == NULL) {
		BIO_set_fp(out, stdout, BIO_NOCLOSE);
	} else {
		if (BIO_write_filename(out, dh_config.outfile) <= 0) {
			perror(dh_config.outfile);
			goto end;
		}
	}

	if (dh_config.informat == FORMAT_ASN1)
		dh = d2i_DHparams_bio(in, NULL);
	else if (dh_config.informat == FORMAT_PEM)
		dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
	else {
		BIO_printf(bio_err, "bad input format specified\n");
		goto end;
	}
	if (dh == NULL) {
		BIO_printf(bio_err, "unable to load DH parameters\n");
		ERR_print_errors(bio_err);
		goto end;
	}
	if (dh_config.text) {
		DHparams_print(out, dh);
	}
	if (dh_config.check) {
		if (!DH_check(dh, &i)) {
			ERR_print_errors(bio_err);
			goto end;
		}
		if (i & DH_CHECK_P_NOT_PRIME)
			printf("p value is not prime\n");
		if (i & DH_CHECK_P_NOT_SAFE_PRIME)
			printf("p value is not a safe prime\n");
		if (i & DH_UNABLE_TO_CHECK_GENERATOR)
			printf("unable to check the generator value\n");
		if (i & DH_NOT_SUITABLE_GENERATOR)
			printf("the g value is not a generator\n");
		if (i == 0)
			printf("DH parameters appear to be ok.\n");
	}
	if (dh_config.C) {
		unsigned char *data;
		int len, l, bits;

		len = BN_num_bytes(dh->p);
		bits = BN_num_bits(dh->p);
		data = malloc(len);
		if (data == NULL) {
			perror("malloc");
			goto end;
		}
		l = BN_bn2bin(dh->p, data);
		printf("static unsigned char dh%d_p[] = {", bits);
		for (i = 0; i < l; i++) {
			if ((i % 12) == 0)
				printf("\n\t");
			printf("0x%02X, ", data[i]);
		}
		printf("\n\t};\n");

		l = BN_bn2bin(dh->g, data);
		printf("static unsigned char dh%d_g[] = {", bits);
		for (i = 0; i < l; i++) {
			if ((i % 12) == 0)
				printf("\n\t");
			printf("0x%02X, ", data[i]);
		}
		printf("\n\t};\n\n");

		printf("DH *get_dh%d()\n\t{\n", bits);
		printf("\tDH *dh;\n\n");
		printf("\tif ((dh = DH_new()) == NULL) return(NULL);\n");
		printf("\tdh->p = BN_bin2bn(dh%d_p, sizeof(dh%d_p), NULL);\n",
		    bits, bits);
		printf("\tdh->g = BN_bin2bn(dh%d_g, sizeof(dh%d_g), NULL);\n",
		    bits, bits);
		printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n");
		printf("\t\treturn(NULL);\n");
		printf("\treturn(dh);\n\t}\n");
		free(data);
	}
	if (!dh_config.noout) {
		if (dh_config.outformat == FORMAT_ASN1)
			i = i2d_DHparams_bio(out, dh);
		else if (dh_config.outformat == FORMAT_PEM)
			i = PEM_write_bio_DHparams(out, dh);
		else {
			BIO_printf(bio_err, "bad output format specified for outfile\n");
			goto end;
		}
		if (!i) {
			BIO_printf(bio_err, "unable to write DH parameters\n");
			ERR_print_errors(bio_err);
			goto end;
		}
	}
	ret = 0;

end:
	BIO_free(in);
	if (out != NULL)
		BIO_free_all(out);
	if (dh != NULL)
		DH_free(dh);

	return (ret);
}
Ejemplo n.º 12
0
/*
 * initialize a new TLS context
 */
static int
tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
{
	tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx;
	int i;

	if ( is_server ) {
		SSL_CTX_set_session_id_context( ctx,
			(const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 );
	}

#ifdef SSL_OP_NO_TLSv1
#ifdef SSL_OP_NO_TLSv1_1
#ifdef SSL_OP_NO_TLSv1_2
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 |
			SSL_OP_NO_TLSv1_2 );
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 );
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1);
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 )
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 );
	else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 )
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 );

	if ( lo->ldo_tls_ciphersuite &&
		!SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) )
	{
		Debug( LDAP_DEBUG_ANY,
			   "TLS: could not set cipher list %s.\n",
			   lo->ldo_tls_ciphersuite, 0, 0 );
		tlso_report_error();
		return -1;
	}

	if (lo->ldo_tls_cacertfile != NULL || lo->ldo_tls_cacertdir != NULL) {
		if ( !SSL_CTX_load_verify_locations( ctx,
				lt->lt_cacertfile, lt->lt_cacertdir ) ||
			!SSL_CTX_set_default_verify_paths( ctx ) )
		{
			Debug( LDAP_DEBUG_ANY, "TLS: "
				"could not load verify locations (file:`%s',dir:`%s').\n",
				lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
				lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
				0 );
			tlso_report_error();
			return -1;
		}

		if ( is_server ) {
			STACK_OF(X509_NAME) *calist;
			/* List of CA names to send to a client */
			calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir );
			if ( !calist ) {
				Debug( LDAP_DEBUG_ANY, "TLS: "
					"could not load client CA list (file:`%s',dir:`%s').\n",
					lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
					lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
					0 );
				tlso_report_error();
				return -1;
			}

			SSL_CTX_set_client_CA_list( ctx, calist );
		}
	}

	if ( lo->ldo_tls_certfile &&
		!SSL_CTX_use_certificate_file( ctx,
			lt->lt_certfile, SSL_FILETYPE_PEM ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"TLS: could not use certificate `%s'.\n",
			lo->ldo_tls_certfile,0,0);
		tlso_report_error();
		return -1;
	}

	/* Key validity is checked automatically if cert has already been set */
	if ( lo->ldo_tls_keyfile &&
		!SSL_CTX_use_PrivateKey_file( ctx,
			lt->lt_keyfile, SSL_FILETYPE_PEM ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"TLS: could not use key file `%s'.\n",
			lo->ldo_tls_keyfile,0,0);
		tlso_report_error();
		return -1;
	}

	if ( is_server && lo->ldo_tls_dhfile ) {
		DH *dh;
		BIO *bio;

		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use DH parameters file `%s'.\n",
				lo->ldo_tls_dhfile,0,0);
			tlso_report_error();
			return -1;
		}
		if (!( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not read DH parameters file `%s'.\n",
				lo->ldo_tls_dhfile,0,0);
			tlso_report_error();
			BIO_free( bio );
			return -1;
		}
		BIO_free( bio );
		SSL_CTX_set_tmp_dh( ctx, dh );
		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE );
		DH_free( dh );
	}

	if ( is_server && lo->ldo_tls_ecname ) {
#ifdef OPENSSL_NO_EC
		Debug( LDAP_DEBUG_ANY,
			"TLS: Elliptic Curves not supported.\n", 0,0,0 );
		return -1;
#else
		EC_KEY *ecdh;

		int nid = OBJ_sn2nid( lt->lt_ecname );
		if ( nid == NID_undef ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use EC name `%s'.\n",
				lo->ldo_tls_ecname,0,0);
			tlso_report_error();
			return -1;
		}
		ecdh = EC_KEY_new_by_curve_name( nid );
		if ( ecdh == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not generate key for EC name `%s'.\n",
				lo->ldo_tls_ecname,0,0);
			tlso_report_error();
			return -1;
		}
		SSL_CTX_set_tmp_ecdh( ctx, ecdh );
		SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE );
		EC_KEY_free( ecdh );
#endif
	}

	if ( tlso_opt_trace ) {
		SSL_CTX_set_info_callback( ctx, tlso_info_cb );
	}

	i = SSL_VERIFY_NONE;
	if ( lo->ldo_tls_require_cert ) {
		i = SSL_VERIFY_PEER;
		if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
			 lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) {
			i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		}
	}

	SSL_CTX_set_verify( ctx, i,
		lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ?
		tlso_verify_ok : tlso_verify_cb );
#if OPENSSL_VERSION_NUMBER < 0x10100000
	SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb );
#endif
#ifdef HAVE_OPENSSL_CRL
	if ( lo->ldo_tls_crlcheck ) {
		X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx );
		if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) {
			X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK );
		} else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) {
			X509_STORE_set_flags( x509_s, 
					X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL  );
		}
	}
#endif
	return 0;
}
Ejemplo n.º 13
0
int tls_connection_dh(void *ssl_ctx, struct tls_connection *conn,
		      const char *dh_file)
{
#ifdef OPENSSL_NO_DH
	if (dh_file == NULL)
		return 0;
	wpa_printf(MSG_ERROR, "TLS: openssl does not include DH support, but "
		   "dh_file specified");
	return -1;
#else /* OPENSSL_NO_DH */
	DH *dh;
	BIO *bio;

	if (dh_file == NULL)
		return 0;
	if (conn == NULL)
		return -1;

	bio = BIO_new_file(dh_file, "r");
	if (bio == NULL) {
		wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
			   dh_file, ERR_error_string(ERR_get_error(), NULL));
		return -1;
	}
	dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
	BIO_free(bio);
#ifndef OPENSSL_NO_DSA
	while (dh == NULL) {
		DSA *dsa;
		wpa_printf(MSG_DEBUG, "TLS: Failed to parse DH file '%s': %s -"
			   " trying to parse as DSA params", dh_file,
			   ERR_error_string(ERR_get_error(), NULL));
		bio = BIO_new_file(dh_file, "r");
		if (bio == NULL)
			break;
		dsa = PEM_read_bio_DSAparams(bio, NULL, NULL, NULL);
		BIO_free(bio);
		if (!dsa) {
			wpa_printf(MSG_DEBUG, "TLS: Failed to parse DSA file "
				   "'%s': %s", dh_file,
				   ERR_error_string(ERR_get_error(), NULL));
			break;
		}

		wpa_printf(MSG_DEBUG, "TLS: DH file in DSA param format");
		dh = DSA_dup_DH(dsa);
		DSA_free(dsa);
		if (dh == NULL) {
			wpa_printf(MSG_INFO, "TLS: Failed to convert DSA "
				   "params into DH params");
			break;
		}
		break;
	}
#endif /* !OPENSSL_NO_DSA */
	if (dh == NULL) {
		wpa_printf(MSG_INFO, "TLS: Failed to read/parse DH/DSA file "
			   "'%s'", dh_file);
		return -1;
	}

	if (SSL_set_tmp_dh(conn->ssl, dh) != 1) {
		wpa_printf(MSG_INFO, "TLS: Failed to set DH params from '%s': "
			   "%s", dh_file,
			   ERR_error_string(ERR_get_error(), NULL));
		DH_free(dh);
		return -1;
	}
	DH_free(dh);
	return 0;
#endif /* OPENSSL_NO_DH */
}
Ejemplo n.º 14
0
/*
 * initialize a new TLS context
 */
static int
tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
{
	tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx;
	int i;

	if ( is_server ) {
		SSL_CTX_set_session_id_context( ctx,
			(const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 );
	}

#ifdef SSL_OP_NO_TLSv1
#ifdef SSL_OP_NO_TLSv1_1
#ifdef SSL_OP_NO_TLSv1_2
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 |
			SSL_OP_NO_TLSv1_2 );
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 );
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0)
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
			SSL_OP_NO_TLSv1);
	else
#endif
	if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 )
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 );
	else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 )
		SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 );

	if ( lo->ldo_tls_ciphersuite &&
		!SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) )
	{
		Debug( LDAP_DEBUG_ANY,
			   "TLS: could not set cipher list %s.\n",
			   lo->ldo_tls_ciphersuite, 0, 0 );
		tlso_report_error();
		return -1;
	}

	if (lo->ldo_tls_cacertfile != NULL || lo->ldo_tls_cacertdir != NULL) {
		if ( !SSL_CTX_load_verify_locations( ctx,
				lt->lt_cacertfile, lt->lt_cacertdir ) ||
			!SSL_CTX_set_default_verify_paths( ctx ) )
		{
			Debug( LDAP_DEBUG_ANY, "TLS: "
				"could not load verify locations (file:`%s',dir:`%s').\n",
				lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
				lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
				0 );
			tlso_report_error();
			return -1;
		}

		if ( is_server ) {
			STACK_OF(X509_NAME) *calist;
			/* List of CA names to send to a client */
			calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir );
			if ( !calist ) {
				Debug( LDAP_DEBUG_ANY, "TLS: "
					"could not load client CA list (file:`%s',dir:`%s').\n",
					lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "",
					lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "",
					0 );
				tlso_report_error();
				return -1;
			}

			SSL_CTX_set_client_CA_list( ctx, calist );
		}
	}

	if ( lo->ldo_tls_certfile &&
		!SSL_CTX_use_certificate_file( ctx,
			lt->lt_certfile, SSL_FILETYPE_PEM ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"TLS: could not use certificate `%s'.\n",
			lo->ldo_tls_certfile,0,0);
		tlso_report_error();
		return -1;
	}

	/* Key validity is checked automatically if cert has already been set */
	if ( lo->ldo_tls_keyfile &&
		!SSL_CTX_use_PrivateKey_file( ctx,
			lt->lt_keyfile, SSL_FILETYPE_PEM ) )
	{
		Debug( LDAP_DEBUG_ANY,
			"TLS: could not use key file `%s'.\n",
			lo->ldo_tls_keyfile,0,0);
		tlso_report_error();
		return -1;
	}

	if ( lo->ldo_tls_dhfile ) {
		DH *dh = NULL;
		BIO *bio;
		dhplist *p;

		if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) {
			Debug( LDAP_DEBUG_ANY,
				"TLS: could not use DH parameters file `%s'.\n",
				lo->ldo_tls_dhfile,0,0);
			tlso_report_error();
			return -1;
		}
		while (( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) {
			p = LDAP_MALLOC( sizeof(dhplist) );
			if ( p != NULL ) {
				p->keylength = DH_size( dh ) * 8;
				p->param = dh;
				p->next = tlso_dhparams;
				tlso_dhparams = p;
			}
		}
		BIO_free( bio );
	}

	if ( tlso_opt_trace ) {
		SSL_CTX_set_info_callback( ctx, tlso_info_cb );
	}

	i = SSL_VERIFY_NONE;
	if ( lo->ldo_tls_require_cert ) {
		i = SSL_VERIFY_PEER;
		if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND ||
			 lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) {
			i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		}
	}

	SSL_CTX_set_verify( ctx, i,
		lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ?
		tlso_verify_ok : tlso_verify_cb );
	SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb );
	if ( lo->ldo_tls_dhfile ) {
		SSL_CTX_set_tmp_dh_callback( ctx, tlso_tmp_dh_cb );
	}
#ifdef HAVE_OPENSSL_CRL
	if ( lo->ldo_tls_crlcheck ) {
		X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx );
		if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) {
			X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK );
		} else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) {
			X509_STORE_set_flags( x509_s, 
					X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL  );
		}
	}
#endif
	return 0;
}
Ejemplo n.º 15
0
int dhparam_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL;
    DH *dh = NULL;
    char *infile = NULL, *outfile = NULL, *prog, *inrand = NULL;
    int dsaparam = 0, i, text = 0, C = 0, ret = 1, num = 0, g = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0;
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, dhparam_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(dhparam_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENGINE:
            (void)setup_engine(opt_arg(), 0);
            break;
        case OPT_CHECK:
            check = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_DSAPARAM:
            dsaparam = 1;
            break;
        case OPT_C:
            C = 1;
            break;
        case OPT_2:
            g = 2;
            break;
        case OPT_5:
            g = 5;
            break;
        case OPT_NOOUT:
            noout = 1;
            break;
        case OPT_RAND:
            inrand = opt_arg();
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

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

    if (g && !num)
        num = DEFBITS;

# ifndef OPENSSL_NO_DSA
    if (dsaparam && g) {
        BIO_printf(bio_err,
                   "generator may not be chosen for DSA parameters\n");
        goto end;
    }
# endif
    /* DH parameters */
    if (num && !g)
        g = 2;

    if (num) {

        BN_GENCB *cb;
        cb = BN_GENCB_new();
        if (cb == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }

        BN_GENCB_set(cb, dh_cb, bio_err);
        if (!app_RAND_load_file(NULL, 1) && inrand == NULL) {
            BIO_printf(bio_err,
                       "warning, not much extra random data, consider using the -rand option\n");
        }
        if (inrand != NULL)
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));

# ifndef OPENSSL_NO_DSA
        if (dsaparam) {
            DSA *dsa = DSA_new();

            BIO_printf(bio_err,
                       "Generating DSA parameters, %d bit long prime\n", num);
            if (dsa == NULL
                || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL,
                                               cb)) {
                DSA_free(dsa);
                BN_GENCB_free(cb);
                ERR_print_errors(bio_err);
                goto end;
            }

            dh = DSA_dup_DH(dsa);
            DSA_free(dsa);
            if (dh == NULL) {
                BN_GENCB_free(cb);
                ERR_print_errors(bio_err);
                goto end;
            }
        } else
# endif
        {
            dh = DH_new();
            BIO_printf(bio_err,
                       "Generating DH parameters, %d bit long safe prime, generator %d\n",
                       num, g);
            BIO_printf(bio_err, "This is going to take a long time\n");
            if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) {
                BN_GENCB_free(cb);
                ERR_print_errors(bio_err);
                goto end;
            }
        }

        BN_GENCB_free(cb);
        app_RAND_write_file(NULL);
    } else {

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

# ifndef OPENSSL_NO_DSA
        if (dsaparam) {
            DSA *dsa;

            if (informat == FORMAT_ASN1)
                dsa = d2i_DSAparams_bio(in, NULL);
            else                /* informat == FORMAT_PEM */
                dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);

            if (dsa == NULL) {
                BIO_printf(bio_err, "unable to load DSA parameters\n");
                ERR_print_errors(bio_err);
                goto end;
            }

            dh = DSA_dup_DH(dsa);
            DSA_free(dsa);
            if (dh == NULL) {
                ERR_print_errors(bio_err);
                goto end;
            }
        } else
# endif
        {
            if (informat == FORMAT_ASN1)
                dh = d2i_DHparams_bio(in, NULL);
            else                /* informat == FORMAT_PEM */
                dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);

            if (dh == NULL) {
                BIO_printf(bio_err, "unable to load DH parameters\n");
                ERR_print_errors(bio_err);
                goto end;
            }
        }

        /* dh != NULL */
    }

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

    if (text) {
        DHparams_print(out, dh);
    }

    if (check) {
        if (!DH_check(dh, &i)) {
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i & DH_CHECK_P_NOT_PRIME)
            printf("p value is not prime\n");
        if (i & DH_CHECK_P_NOT_SAFE_PRIME)
            printf("p value is not a safe prime\n");
        if (i & DH_UNABLE_TO_CHECK_GENERATOR)
            printf("unable to check the generator value\n");
        if (i & DH_NOT_SUITABLE_GENERATOR)
            printf("the g value is not a generator\n");
        if (i == 0)
            printf("DH parameters appear to be ok.\n");
    }
    if (C) {
        unsigned char *data;
        int len, bits;

        len = BN_num_bytes(dh->p);
        bits = BN_num_bits(dh->p);
        data = app_malloc(len, "print a BN");
        BIO_printf(out, "#ifndef HEADER_DH_H\n"
                        "# include <openssl/dh.h>\n"
                        "#endif\n"
                        "\n");
        BIO_printf(out, "DH *get_dh%d()\n{\n", bits);
        print_bignum_var(out, dh->p, "dhp", bits, data);
        print_bignum_var(out, dh->g, "dhg", bits, data);
        BIO_printf(out, "    DH *dh = DN_new();\n"
                        "\n"
                        "    if (dh == NULL)\n"
                        "        return NULL;\n");
        BIO_printf(out, "    dh->p = BN_bin2bn(dhp_%d, sizeof (dhp_%d), NULL);\n",
               bits, bits);
        BIO_printf(out, "    dh->g = BN_bin2bn(dhg_%d, sizeof (dhg_%d), NULL);\n",
               bits, bits);
        BIO_printf(out, "    if (!dh->p || !dh->g) {\n"
                        "        DH_free(dh);\n"
                        "        return NULL;\n"
                        "    }\n");
        if (dh->length)
            BIO_printf(out,
                        "    dh->length = %ld;\n", dh->length);
        BIO_printf(out, "    return dh;\n}\n");
        OPENSSL_free(data);
    }

    if (!noout) {
        if (outformat == FORMAT_ASN1)
            i = i2d_DHparams_bio(out, dh);
        else if (dh->q)
            i = PEM_write_bio_DHxparams(out, dh);
        else
            i = PEM_write_bio_DHparams(out, dh);
        if (!i) {
            BIO_printf(bio_err, "unable to write DH parameters\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    }
    ret = 0;
 end:
    BIO_free(in);
    BIO_free_all(out);
    DH_free(dh);
    return (ret);
}
Ejemplo n.º 16
0
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {

        SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
        if (!ctx) {
                uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
                return NULL;
        }

        // this part is taken from nginx and stud, removing unneeded functionality
        // stud (for me) has made the best choice on choosing DH approach

        long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
// disable compression (if possibile)
#ifdef SSL_OP_NO_COMPRESSION
        ssloptions |= SSL_OP_NO_COMPRESSION;
#endif

// release/reuse buffers as soon as possibile
#ifdef SSL_MODE_RELEASE_BUFFERS
        SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif

        if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
                uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
                SSL_CTX_free(ctx);
                return NULL;
        }

// this part is based from stud
        BIO *bio = BIO_new_file(crt, "r");
        if (bio) {
                DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
                BIO_free(bio);
                if (dh) {
                        SSL_CTX_set_tmp_dh(ctx, dh);
                        DH_free(dh);
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
#ifdef NID_X9_62_prime256v1
                        EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
                        SSL_CTX_set_tmp_ecdh(ctx, ecdh);
                        EC_KEY_free(ecdh);
#endif
#endif
#endif
                }
        }

        if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
                uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name);
                SSL_CTX_free(ctx);
                return NULL;
        }


	// if ciphers are specified, prefer server ciphers
        if (ciphers && strlen(ciphers) > 0) {
                if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
                        uwsgi_log("[uwsgi-ssl] unable to set requested ciphers (%s) for context \"%s\"\n", ciphers, name);
                        SSL_CTX_free(ctx);
                        return NULL;
                }

                ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
        }

        // set session context (if possibile), this is required for client certificate authentication
        if (name) {
                SSL_CTX_set_session_id_context(ctx, (unsigned char *) name, strlen(name));
        }

        if (client_ca) {
                if (client_ca[0] == '!') {
                        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, uwsgi_ssl_verify_callback);
                        client_ca++;
                }
                else {
                        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, uwsgi_ssl_verify_callback);
                }
                // in the future we should allow to set the verify depth
                SSL_CTX_set_verify_depth(ctx, 1);
                if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) {
                        uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name);
                        SSL_CTX_free(ctx);
                        return NULL;
                }
                STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca);
                if (!list) {
                        uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name);
                        SSL_CTX_free(ctx);
                        return NULL;
                }

                SSL_CTX_set_client_CA_list(ctx, list);
        }


        SSL_CTX_set_info_callback(ctx, uwsgi_ssl_info_cb);
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
        SSL_CTX_set_tlsext_servername_callback(ctx, uwsgi_sni_cb);
#endif

        // disable session caching by default
        SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);

	if (uwsgi.ssl_sessions_use_cache) {

		// we need to early initialize locking and caching
		uwsgi_setup_locking();
		uwsgi_cache_create_all();

		uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
		if (!uwsgi.ssl_sessions_cache) {
			// check for default cache
			if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
				uwsgi.ssl_sessions_cache = uwsgi.caches;
			}
			else {
				uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
				exit(1);
			}
		}

                if (!uwsgi.ssl_sessions_cache->max_items) {
                        uwsgi_log("you have to enable uWSGI cache to use it as SSL session store !!!\n");
                        exit(1);
                }

                if (uwsgi.ssl_sessions_cache->blocksize < 4096) {
                        uwsgi_log("cache blocksize for SSL session store must be at least 4096 bytes\n");
                        exit(1);
                }

                SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|
                        SSL_SESS_CACHE_NO_INTERNAL|
                        SSL_SESS_CACHE_NO_AUTO_CLEAR);

#ifdef SSL_OP_NO_TICKET
                ssloptions |= SSL_OP_NO_TICKET;
#endif

                // just for fun
                SSL_CTX_sess_set_cache_size(ctx, 0);

                // set the callback for ssl sessions
                SSL_CTX_sess_set_new_cb(ctx, uwsgi_ssl_session_new_cb);
                SSL_CTX_sess_set_get_cb(ctx, uwsgi_ssl_session_get_cb);
                SSL_CTX_sess_set_remove_cb(ctx, uwsgi_ssl_session_remove_cb);
        }

        SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);

        SSL_CTX_set_options(ctx, ssloptions);


        return ctx;
}
Ejemplo n.º 17
0
static int __ssl_setup(struct ast_tls_config *cfg, int client)
{
#ifndef DO_SSL
	cfg->enabled = 0;
	return 0;
#else
	int disable_ssl = 0;
 
	if (!cfg->enabled) {
		return 0;
	}

	/* Get rid of an old SSL_CTX since we're about to
	 * allocate a new one
	 */
	if (cfg->ssl_ctx) {
		SSL_CTX_free(cfg->ssl_ctx);
		cfg->ssl_ctx = NULL;
	}

	if (client) {
#ifndef OPENSSL_NO_SSL2
		if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) {
			ast_log(LOG_WARNING, "Usage of SSLv2 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
			cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method());
		} else
#endif
#ifndef OPENSSL_NO_SSL3_METHOD
		if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) {
			ast_log(LOG_WARNING, "Usage of SSLv3 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n");
			cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
		} else
#endif
		if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) {
			cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method());
		} else {
			disable_ssl = 1;
			cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method());
		}
	} else {
		disable_ssl = 1;
		cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
	}

	if (!cfg->ssl_ctx) {
		ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n");
		cfg->enabled = 0;
		return 0;
	}

	/* Due to the POODLE vulnerability, completely disable
	 * SSLv2 and SSLv3 if we are not explicitly told to use
	 * them. SSLv23_*_method supports TLSv1+.
	 */
	if (disable_ssl) {
		long ssl_opts;

		ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
		SSL_CTX_set_options(cfg->ssl_ctx, ssl_opts);
	}

	SSL_CTX_set_verify(cfg->ssl_ctx,
		ast_test_flag(&cfg->flags, AST_SSL_VERIFY_CLIENT) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE,
		NULL);

	if (!ast_strlen_zero(cfg->certfile)) {
		char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile;
		if (SSL_CTX_use_certificate_chain_file(cfg->ssl_ctx, cfg->certfile) == 0) {
			if (!client) {
				/* Clients don't need a certificate, but if its setup we can use it */
				ast_log(LOG_ERROR, "TLS/SSL error loading cert file. <%s>\n", cfg->certfile);
				cfg->enabled = 0;
				SSL_CTX_free(cfg->ssl_ctx);
				cfg->ssl_ctx = NULL;
				return 0;
			}
		}
		if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) {
			if (!client) {
				/* Clients don't need a private key, but if its setup we can use it */
				ast_log(LOG_ERROR, "TLS/SSL error loading private key file. <%s>\n", tmpprivate);
				cfg->enabled = 0;
				SSL_CTX_free(cfg->ssl_ctx);
				cfg->ssl_ctx = NULL;
				return 0;
			}
		}
	}
	if (!ast_strlen_zero(cfg->cipher)) {
		if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) {
			if (!client) {
				ast_log(LOG_ERROR, "TLS/SSL cipher error <%s>\n", cfg->cipher);
				cfg->enabled = 0;
				SSL_CTX_free(cfg->ssl_ctx);
				cfg->ssl_ctx = NULL;
				return 0;
			}
		}
	}
	if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) {
		if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) {
			ast_log(LOG_ERROR, "TLS/SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath);
		}
	}

#ifdef HAVE_OPENSSL_EC

	if (!ast_strlen_zero(cfg->pvtfile)) {
		BIO *bio = BIO_new_file(cfg->pvtfile, "r");
		if (bio != NULL) {
			DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			if (dh != NULL) {
				if (SSL_CTX_set_tmp_dh(cfg->ssl_ctx, dh)) {
					long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE;
					options = SSL_CTX_set_options(cfg->ssl_ctx, options);
					ast_verb(2, "TLS/SSL DH initialized, PFS cipher-suites enabled\n");
				}
				DH_free(dh);
			}
			BIO_free(bio);
		}
	}
	#ifndef SSL_CTRL_SET_ECDH_AUTO
		#define SSL_CTRL_SET_ECDH_AUTO 94
	#endif
	/* SSL_CTX_set_ecdh_auto(cfg->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */
	if (SSL_CTX_ctrl(cfg->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) {
		ast_verb(2, "TLS/SSL ECDH initialized (automatic), faster PFS ciphers enabled\n");
	} else {
		/* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */
		EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
		if (ecdh != NULL) {
			if (SSL_CTX_set_tmp_ecdh(cfg->ssl_ctx, ecdh)) {
				ast_verb(2, "TLS/SSL ECDH initialized (secp256r1), faster PFS cipher-suites enabled\n");
			}
			EC_KEY_free(ecdh);
		}
	}

#endif /* #ifdef HAVE_OPENSSL_EC */

	ast_verb(2, "TLS/SSL certificate ok\n");	/* We should log which one that is ok. This message doesn't really make sense in production use */
	return 1;
#endif
}
Ejemplo n.º 18
0
/* デフォルトの証明書は 自分:/usr/local/ct/cert/tn.pem 認証局:/usr/local/ct/cert/root.pem */
int kTLSInitialize(int sessionMode,int initialmode,int timeout,char *passwd,char *rootPEM,char *myPEM,
		   char *dhPEM,int version,int nagle,int clientveri,int tmprsa,char *enc)
{
    BIO         *bio;
    SSL_METHOD *meth;
    RSA *rsa;
    DH *dh=0;
    struct stat tmp;

    /* Nagleアルゴリズムの無効化フラグの保存 */
    NagleFlag=nagle;

    if(TLSctx){
      /* 強制初期化モードがある場合 */
      if(initialmode){
	TLSClose(NULL,0);
	kLogWrite(L_TLS, "%s: TLS ReInitialize", __FUNCTION__);
      }
      else
	return RETURN_OK;
    }

    /* パラメータの取得 */
    timeout = timeout<=0 ? SESSION_TIMEOUT : timeout;
    TLSSessionMode = sessionMode;
    kLogWrite(L_TLS,"%s: Session cache mode : %s   Session timeout : %d(s)",__FUNCTION__,sessionMode?"Enable":"Disable",timeout);

    rootPEM = (rootPEM && rootPEM[0]) ? rootPEM : ROOT_PEM;
    myPEM   = (myPEM && myPEM[0]) ?   myPEM   : MY_PEM;
    dhPEM   = (dhPEM && dhPEM[0]) ?   dhPEM   : DHFILE1024;
    strcpy(TLSPasswd,(passwd && passwd[0]) ?  passwd  : PASSWORD);

    if(lstat(rootPEM,&tmp)<0){
      kLogWrite(L_ERROR, "%s: TLS Initialize file[%s] not exist", __FUNCTION__,rootPEM);
      return(RETURN_NG);
    }
    if(lstat(myPEM,&tmp)<0){
      kLogWrite(L_ERROR, "%s: TLS Initialize file[%s] not exist", __FUNCTION__,myPEM);
      return(RETURN_NG);
    }
    if(lstat(dhPEM,&tmp)<0){
      kLogWrite(L_ERROR, "%s: TLS Initialize file[%s] not exist", __FUNCTION__,dhPEM);
      return(RETURN_NG);
    }

    /* SSLライブラリの初期化 */
    if(!SSL_library_init()){
      kLogWrite(L_ERROR, "%s: OpenSSL initialization failed!",__FUNCTION__);
      return(RETURN_NG);
    }
    kLogWrite(L_TLS,"%s: SSL_library_init OK",__FUNCTION__);

    /* エラーメッセージの視覚化 */
    SSL_load_error_strings();

    RAND_load_file("/dev/urandom", 1024);
    kLogWrite(L_TLS,"%s: RAND_load_file OK",__FUNCTION__);

    /* SSL_METHODオブジェクトの取得 */
    if(version == 2)
      meth=SSLv2_method();
    else if(version == 3)
      meth=SSLv3_method();
    else if(version == 1)
      meth=TLSv1_method();
    else if(version == 23)
      meth=SSLv23_method();
    else
      meth=TLSv1_method();

    kLogWrite(L_TLS,"%s: SSL verion [%d] 2:SSLv2 23:SSLv23 3:SSLv3 1:TLSv1",__FUNCTION__,version);
    
    /* SSL_CTXオブジェクトの取得 */
    TLSctx=SSL_CTX_new(meth);
    kLogWrite(L_TLS,"%s: SSL_CTX_new OK",__FUNCTION__);

    /* SSL_CTXオブジェクトに証明書と秘密鍵を同時にロードする */
    if(!(SSL_CTX_use_certificate_file(TLSctx,myPEM,SSL_FILETYPE_PEM))){
      TLSClose(NULL,0);
      kLogWrite(L_ERROR, "%s: Couldn't read certificate file",__FUNCTION__);
      return(RETURN_NG);
    }
    kLogWrite(L_TLS,"%s: SSL_CTX_use_certificate_file[%s] OK",__FUNCTION__,myPEM);

    /* パスフレーズのコールバック関数を登録する */
    SSL_CTX_set_default_passwd_cb(TLSctx,password_cb);

    if(!(SSL_CTX_use_PrivateKey_file(TLSctx,myPEM,SSL_FILETYPE_PEM))){
      TLSClose(NULL,0);
      kLogWrite(L_ERROR, "%s: Couldn't read key file",__FUNCTION__);
      return(RETURN_NG);
    }
    kLogWrite(L_TLS,"%s: SSL_CTX_use_PrivateKey_file[%s] OK",__FUNCTION__,myPEM);
  
    /* SSL_CTXオブジェクトに信頼できるCA証明書をロードする */
    if(!(SSL_CTX_load_verify_locations(TLSctx,rootPEM,0))){
      TLSClose(NULL,0);
      kLogWrite(L_ERROR, "%s: Couldn't read CA list",__FUNCTION__);
      return(RETURN_NG);
    }
    kLogWrite(L_TLS,"%s: SSL_CTX_load_verify_locations[%s] OK",__FUNCTION__,rootPEM);

    /* 認証コールバック関数の登録 */
    /* Server Key Exchange オプションを付与する (クライアント認証を行う) */
    kLogWrite(L_TLS,"%s: Server Key Exchange option : %s",__FUNCTION__,clientveri?"Enable":"Disable");
    SSL_CTX_set_verify(TLSctx, clientveri?SSL_VERIFY_PEER:SSL_VERIFY_NONE,VerifyCallback);
    kLogWrite(L_TLS,"%s:  SSL_CTX_set_verify[%s] OK",__FUNCTION__,clientveri?"PEER":"NONE");
    
    /* 信頼できる証明書に到達するまでのチェーンの回数を指定する */
    /* SSL_CTX_set_verify_depth(TLSctx,1); */

    /* SSLv2を選択不可にする */
    if(version != 2 && version != 23){
      SSL_CTX_set_options(TLSctx,SSL_OP_NO_SSLv2);
      kLogWrite(L_TLS,"%s: SSL_CTX_set_options NO_SSLv2",__FUNCTION__);
    }

    /* Certificate Request オプションを付与する (一時的RSAを使う ) */
    kLogWrite(L_TLS,"%s: Certificate Request option : %s",__FUNCTION__,tmprsa?"Enable":"Disable");
    if(tmprsa){

      /* BIOオブジェクトを使ってファイルをオープンする */
      if ((bio=BIO_new_file(dhPEM,"r")) == NULL){
	TLSClose(NULL,0);
	kLogWrite(L_ERROR, "%s: Couldn't open DH file",__FUNCTION__);
	return(RETURN_NG);
      }
      kLogWrite(L_TLS,"%s: BIO_new_file[%s] OK",__FUNCTION__,dhPEM);
    
      /* DHパラメータを読み込む */
      dh=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
      kLogWrite(L_TLS,"%s: PEM_read_bio_DHparams[%s] OK",__FUNCTION__,dhPEM);
      
      /* ファイルをクローズする */
      BIO_free(bio);
    
      /* DHパラメータをCTXオブジェクトにロードする */
      if(SSL_CTX_set_tmp_dh(TLSctx,dh)<0){
	TLSClose(NULL,0);
	kLogWrite(L_ERROR, "%s: Couldn't set DH parameters",__FUNCTION__);
	return(RETURN_NG);
      }
      kLogWrite(L_TLS,"%s: SSL_CTX_set_tmp_dh OK",__FUNCTION__);
    }

    /* 暗号スイートの選択 */
    if(enc && enc[0]){
      kLogWrite(L_TLS,"%s: Encrypt suit specified",__FUNCTION__);

      if(SSL_CTX_set_cipher_list(TLSctx,enc))
	kLogWrite(L_TLS,"%s:  SSL_CTX_set_cipher_list[%s] OK",__FUNCTION__,enc);
      else
	kLogWrite(L_TLS,"%s:  SSL_CTX_set_cipher_list[%s] invalid",__FUNCTION__,enc);
    }

    /* RSA鍵のペアを生成する */
    rsa=RSA_generate_key(512,RSA_F4,NULL,NULL);
    kLogWrite(L_TLS,"%s: RSA_generate_key OK",__FUNCTION__);
    
    /* RSA鍵をCTXオブジェクトにロードする */
    if (!SSL_CTX_set_tmp_rsa(TLSctx,rsa)){
      TLSClose(NULL,0);
      kLogWrite(L_ERROR, "%s: Couldn't set RSA key", __FUNCTION__);
      return(RETURN_NG);
    }
    kLogWrite(L_TLS,"%s: SSL_CTX_set_tmp_rsa OK",__FUNCTION__);
    
    RSA_free(rsa);
  
    /* セッションキャッシュを有効モードに設定する */
    SSL_CTX_set_session_id_context(TLSctx,(void*)&TLSServerSessionIdContext, sizeof(TLSServerSessionIdContext));
    kLogWrite(L_TLS,"%s: SSL_CTX_set_session_id_context OK", __FUNCTION__);

    /* セッション削除時のコールバック設定 */
    SSL_CTX_sess_set_remove_cb(TLSctx,remove_session_cb);
    SSL_CTX_set_timeout(TLSctx,timeout);

    kLogWrite(L_TLS,"%s: Nagle algorithm : %s",__FUNCTION__,NagleFlag?"Enable":"Disable");

    return(RETURN_OK);
}
Ejemplo n.º 19
0
static int openssl_ssl_ctx_set_tmp(lua_State *L)
{
  SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx");
  static const char* which[] =
  {
    "dh",
    "rsa",
    "ecdh",
    NULL
  };

  int nwhich = luaL_checkoption(L, 2, NULL, which);
  int ret = 0;

  if (lua_isfunction(L, 3))
  {
    lua_pushvalue(L, 3);
    ret = 1;
    switch (nwhich)
    {
    case 0:
      openssl_setvalue(L, ctx, "tmp_dh_callback");
      SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_callback);
      break;
    case 1:
      openssl_setvalue(L, ctx, "tmp_rsa_callback");
      SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_callback);
      break;
    case 2:
    {
      luaL_argcheck(L, lua_isstring(L, 4), 4, "must supply curve name");
      openssl_setvalue(L, ctx, "tmp_ecdh_callback");
      SSL_CTX_set_tmp_ecdh_callback(ctx, tmp_ecdh_callback);
      lua_pushvalue(L, 4);
      openssl_setvalue(L, ctx, "curve");
    }
    break;
    }
  }
  else if (lua_isstring(L, 3))
  {
    BIO* bio = load_bio_object(L, 3);
    switch (nwhich)
    {
    case 0:
    {
      DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
      if (dh)
        ret = SSL_CTX_set_tmp_dh(ctx, dh);
      else
        luaL_error(L, "generate new tmp dh fail");
    }
    break;
    case 1:
    {
      RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL);
      if (rsa)
        ret = SSL_CTX_set_tmp_rsa(ctx, rsa);
      else
        luaL_error(L, "generate new tmp rsa fail");
    }
    break;
    case 2:
    {
      int nid = NID_undef;

      EC_KEY* ec = PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL);
      if (ec == NULL)
      {
        nid = OBJ_txt2nid(lua_tostring(L, 3));
        if (nid != NID_undef)
          ec = EC_KEY_new_by_curve_name(nid);
      }
      if (ec)
        ret = SSL_CTX_set_tmp_ecdh(ctx, ec);
      else
        luaL_error(L, "generate new tmp ec_key fail");
    }
    break;
    }
    BIO_free(bio);
  }
  else if (lua_isuserdata(L, 3))
  {
    luaL_argerror(L, 3, "userdata arg NYI");
  }
  else
    luaL_argerror(L, 3, "should be tmp key callback function or pem string or key object");

  return openssl_pushresult(L, ret);
}
Ejemplo n.º 20
0
int dhparam_main(int argc, char **argv)
{
    BIO *in = NULL, *out = NULL;
    DH *dh = NULL;
    char *infile = NULL, *outfile = NULL, *prog;
    ENGINE *e = NULL;
#ifndef OPENSSL_NO_DSA
    int dsaparam = 0;
#endif
    int i, text = 0, C = 0, ret = 1, num = 0, g = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0;
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, dhparam_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(dhparam_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
                goto opthelp;
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_CHECK:
            check = 1;
            break;
        case OPT_TEXT:
            text = 1;
            break;
        case OPT_DSAPARAM:
#ifndef OPENSSL_NO_DSA
            dsaparam = 1;
#endif
            break;
        case OPT_C:
            C = 1;
            break;
        case OPT_2:
            g = 2;
            break;
        case OPT_5:
            g = 5;
            break;
        case OPT_NOOUT:
            noout = 1;
            break;
        case OPT_R_CASES:
            if (!opt_rand(o))
                goto end;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0))
        goto end;

    if (g && !num)
        num = DEFBITS;

# ifndef OPENSSL_NO_DSA
    if (dsaparam && g) {
        BIO_printf(bio_err,
                   "generator may not be chosen for DSA parameters\n");
        goto end;
    }
# endif

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

    /* DH parameters */
    if (num && !g)
        g = 2;

    if (num) {

        BN_GENCB *cb;
        cb = BN_GENCB_new();
        if (cb == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }

        BN_GENCB_set(cb, dh_cb, bio_err);

# ifndef OPENSSL_NO_DSA
        if (dsaparam) {
            DSA *dsa = DSA_new();

            BIO_printf(bio_err,
                       "Generating DSA parameters, %d bit long prime\n", num);
            if (dsa == NULL
                || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL,
                                               cb)) {
                DSA_free(dsa);
                BN_GENCB_free(cb);
                ERR_print_errors(bio_err);
                goto end;
            }

            dh = DSA_dup_DH(dsa);
            DSA_free(dsa);
            if (dh == NULL) {
                BN_GENCB_free(cb);
                ERR_print_errors(bio_err);
                goto end;
            }
        } else
# endif
        {
            dh = DH_new();
            BIO_printf(bio_err,
                       "Generating DH parameters, %d bit long safe prime, generator %d\n",
                       num, g);
            BIO_printf(bio_err, "This is going to take a long time\n");
            if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) {
                BN_GENCB_free(cb);
                ERR_print_errors(bio_err);
                goto end;
            }
        }

        BN_GENCB_free(cb);
    } else {

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

# ifndef OPENSSL_NO_DSA
        if (dsaparam) {
            DSA *dsa;

            if (informat == FORMAT_ASN1)
                dsa = d2i_DSAparams_bio(in, NULL);
            else                /* informat == FORMAT_PEM */
                dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL);

            if (dsa == NULL) {
                BIO_printf(bio_err, "unable to load DSA parameters\n");
                ERR_print_errors(bio_err);
                goto end;
            }

            dh = DSA_dup_DH(dsa);
            DSA_free(dsa);
            if (dh == NULL) {
                ERR_print_errors(bio_err);
                goto end;
            }
        } else
# endif
        {
            if (informat == FORMAT_ASN1) {
                /*
                 * We have no PEM header to determine what type of DH params it
                 * is. We'll just try both.
                 */
                dh = d2i_DHparams_bio(in, NULL);
                /* BIO_reset() returns 0 for success for file BIOs only!!! */
                if (dh == NULL && BIO_reset(in) == 0)
                    dh = d2i_DHxparams_bio(in, NULL);
            } else {
                /* informat == FORMAT_PEM */
                dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
            }

            if (dh == NULL) {
                BIO_printf(bio_err, "unable to load DH parameters\n");
                ERR_print_errors(bio_err);
                goto end;
            }
        }

        /* dh != NULL */
    }

    if (text) {
        DHparams_print(out, dh);
    }

    if (check) {
        if (!DH_check(dh, &i)) {
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i & DH_CHECK_P_NOT_PRIME)
            BIO_printf(bio_err, "WARNING: p value is not prime\n");
        if (i & DH_CHECK_P_NOT_SAFE_PRIME)
            BIO_printf(bio_err, "WARNING: p value is not a safe prime\n");
        if (i & DH_CHECK_Q_NOT_PRIME)
            BIO_printf(bio_err, "WARNING: q value is not a prime\n");
        if (i & DH_CHECK_INVALID_Q_VALUE)
            BIO_printf(bio_err, "WARNING: q value is invalid\n");
        if (i & DH_CHECK_INVALID_J_VALUE)
            BIO_printf(bio_err, "WARNING: j value is invalid\n");
        if (i & DH_UNABLE_TO_CHECK_GENERATOR)
            BIO_printf(bio_err,
                       "WARNING: unable to check the generator value\n");
        if (i & DH_NOT_SUITABLE_GENERATOR)
            BIO_printf(bio_err, "WARNING: the g value is not a generator\n");
        if (i == 0)
            BIO_printf(bio_err, "DH parameters appear to be ok.\n");
        if (num != 0 && i != 0) {
            /*
             * We have generated parameters but DH_check() indicates they are
             * invalid! This should never happen!
             */
            BIO_printf(bio_err, "ERROR: Invalid parameters generated\n");
            goto end;
        }
    }
    if (C) {
        unsigned char *data;
        int len, bits;
        const BIGNUM *pbn, *gbn;

        len = DH_size(dh);
        bits = DH_bits(dh);
        DH_get0_pqg(dh, &pbn, NULL, &gbn);
        data = app_malloc(len, "print a BN");

        BIO_printf(out, "static DH *get_dh%d(void)\n{\n", bits);
        print_bignum_var(out, pbn, "dhp", bits, data);
        print_bignum_var(out, gbn, "dhg", bits, data);
        BIO_printf(out, "    DH *dh = DH_new();\n"
                        "    BIGNUM *p, *g;\n"
                        "\n"
                        "    if (dh == NULL)\n"
                        "        return NULL;\n");
        BIO_printf(out, "    p = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n",
                   bits, bits);
        BIO_printf(out, "    g = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n",
                   bits, bits);
        BIO_printf(out, "    if (p == NULL || g == NULL\n"
                        "            || !DH_set0_pqg(dh, p, NULL, g)) {\n"
                        "        DH_free(dh);\n"
                        "        BN_free(p);\n"
                        "        BN_free(g);\n"
                        "        return NULL;\n"
                        "    }\n");
        if (DH_get_length(dh) > 0)
            BIO_printf(out,
                        "    if (!DH_set_length(dh, %ld)) {\n"
                        "        DH_free(dh);\n"
                        "        return NULL;\n"
                        "    }\n", DH_get_length(dh));
        BIO_printf(out, "    return dh;\n}\n");
        OPENSSL_free(data);
    }

    if (!noout) {
        const BIGNUM *q;
        DH_get0_pqg(dh, NULL, &q, NULL);
        if (outformat == FORMAT_ASN1) {
            if (q != NULL)
                i = i2d_DHxparams_bio(out, dh);
            else
                i = i2d_DHparams_bio(out, dh);
        } else if (q != NULL) {
            i = PEM_write_bio_DHxparams(out, dh);
        } else {
            i = PEM_write_bio_DHparams(out, dh);
        }
        if (!i) {
            BIO_printf(bio_err, "unable to write DH parameters\n");
            ERR_print_errors(bio_err);
            goto end;
        }
    }
    ret = 0;
 end:
    BIO_free(in);
    BIO_free_all(out);
    DH_free(dh);
    release_engine(e);
    return ret;
}
Ejemplo n.º 21
0
/*
 * Create a new TLS_CONTEXT instance.
 *
 * Returns: Pointer to TLS_CONTEXT instance on success
 *          NULL on failure;
 */
TLS_CONTEXT *new_tls_context(const char *ca_certfile,
                             const char *ca_certdir,
                             const char *crlfile,
                             const char *certfile,
                             const char *keyfile,
                             CRYPTO_PEM_PASSWD_CB *pem_callback,
                             const void *pem_userdata,
                             const char *dhfile,
                             bool verify_peer)
{
   TLS_CONTEXT *ctx;
   BIO *bio;
   DH *dh;

   ctx = (TLS_CONTEXT *)malloc(sizeof(TLS_CONTEXT));

   /*
    * Allocate our OpenSSL TLSv1 Context
    */
   ctx->openssl = SSL_CTX_new(TLSv1_method());

   if (!ctx->openssl) {
      openssl_post_errors(M_FATAL, _("Error initializing SSL context"));
      goto err;
   }

   /*
    * Set up pem encryption callback
    */
   if (pem_callback) {
      ctx->pem_callback = pem_callback;
      ctx->pem_userdata = pem_userdata;
   } else {
      ctx->pem_callback = crypto_default_pem_callback;
      ctx->pem_userdata = NULL;
   }
   ctx->verify_peer = verify_peer;

   SSL_CTX_set_default_passwd_cb(ctx->openssl, tls_pem_callback_dispatch);
   SSL_CTX_set_default_passwd_cb_userdata(ctx->openssl, (void *) ctx);

   /*
    * Set certificate verification paths. This requires that at least one value be non-NULL
    */
   if (ca_certfile || ca_certdir) {
      if (!SSL_CTX_load_verify_locations(ctx->openssl, ca_certfile, ca_certdir)) {
         openssl_post_errors(M_FATAL, _("Error loading certificate verification stores"));
         goto err;
      }
   } else if (verify_peer) {
      /* At least one CA is required for peer verification */
      Jmsg0(NULL, M_ERROR, 0, _("Either a certificate file or a directory must be"
                         " specified as a verification store\n"));
      goto err;
   }

#if (OPENSSL_VERSION_NUMBER >= 0x00907000L)
   /*
    * Set certificate revocation list.
    */
   if (crlfile) {
      X509_STORE *store;
      X509_LOOKUP *lookup;

      store = SSL_CTX_get_cert_store(ctx->openssl);
      if (!store) {
         openssl_post_errors(M_FATAL, _("Error loading revocation list file"));
         goto err;
      }

      lookup = X509_STORE_add_lookup(store, X509_LOOKUP_crl_reloader());
      if (!lookup) {
         openssl_post_errors(M_FATAL, _("Error loading revocation list file"));
         goto err;
      }

      if (!load_new_crl_file(lookup, (char *)crlfile)) {
         openssl_post_errors(M_FATAL, _("Error loading revocation list file"));
         goto err;
      }

      X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
   }
#endif

   /*
    * Load our certificate file, if available. This file may also contain a
    * private key, though this usage is somewhat unusual.
    */
   if (certfile) {
      if (!SSL_CTX_use_certificate_chain_file(ctx->openssl, certfile)) {
         openssl_post_errors(M_FATAL, _("Error loading certificate file"));
         goto err;
      }
   }

   /*
    * Load our private key.
    */
   if (keyfile) {
      if (!SSL_CTX_use_PrivateKey_file(ctx->openssl, keyfile, SSL_FILETYPE_PEM)) {
         openssl_post_errors(M_FATAL, _("Error loading private key"));
         goto err;
      }
   }

   /*
    * Load Diffie-Hellman Parameters.
    */
   if (dhfile) {
      if (!(bio = BIO_new_file(dhfile, "r"))) {
         openssl_post_errors(M_FATAL, _("Unable to open DH parameters file"));
         goto err;
      }
      dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
      BIO_free(bio);
      if (!dh) {
         openssl_post_errors(M_FATAL, _("Unable to load DH parameters from specified file"));
         goto err;
      }
      if (!SSL_CTX_set_tmp_dh(ctx->openssl, dh)) {
         openssl_post_errors(M_FATAL, _("Failed to set TLS Diffie-Hellman parameters"));
         DH_free(dh);
         goto err;
      }

      /*
       * Enable Single-Use DH for Ephemeral Keying
       */
      SSL_CTX_set_options(ctx->openssl, SSL_OP_SINGLE_DH_USE);
   }

   if (SSL_CTX_set_cipher_list(ctx->openssl, TLS_DEFAULT_CIPHERS) != 1) {
      Jmsg0(NULL, M_ERROR, 0,
             _("Error setting cipher list, no valid ciphers available\n"));
      goto err;
   }

   /*
    * Verify Peer Certificate
    */
   if (verify_peer) {
      /*
       * SSL_VERIFY_FAIL_IF_NO_PEER_CERT has no effect in client mode
       */
      SSL_CTX_set_verify(ctx->openssl,
                         SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                         openssl_verify_peer);
   } else {
      SSL_CTX_set_verify(ctx->openssl,
                         SSL_VERIFY_NONE,
                         NULL);
   }

   return ctx;

err:
   /*
    * Clean up after ourselves
    */
   if (ctx->openssl) {
      SSL_CTX_free(ctx->openssl);
   }
   free(ctx);
   return NULL;
}
Ejemplo n.º 22
0
		inline dh_key dh_key::from_parameters(bio::bio_ptr bio, pem_passphrase_callback_type callback, void* callback_arg)
		{
			return take_ownership(PEM_read_bio_DHparams(bio.raw(), NULL, callback, callback_arg));
		}