Example #1
0
		bool Engine::set_p12_certificate_privatekey(const Data & data, const std::string & password)
		{
			if( data.empty() ) // BIO undefined behaviour when writing 0
				return false;
			BIO *mem = BIO_new(BIO_s_mem());
			BIO_write(mem, data.getData(), data.getSize());
			PKCS12 * pkcs12 = d2i_PKCS12_bio(mem, NULL);
			BIO_free(mem);
			mem = 0;
			X509 * cax = 0;
			EVP_PKEY * pkey = 0;
//			int succ = 
			PKCS12_parse(pkcs12, password.c_str(), &pkey, &cax, NULL);
//			int err = ERR_get_error();
//			const char * err_str = ERR_error_string(err, 0);
			int cert_res = SSL_use_certificate(ssl, cax);
			if (cax)
				X509_free(cax);
			cax = 0;
			int key_res = SSL_use_PrivateKey(ssl, pkey);
			if( pkey )
				EVP_PKEY_free(pkey);
			pkey = 0;
			int check_res = SSL_check_private_key(ssl);
			return cert_res == 1 && key_res == 1 && check_res == 1;
		}
Example #2
0
		bool Engine::set_pem_certificate_privatekey(const Data & data, const std::string & password)
		{
			if( data.empty() ) // BIO undefined behaviour when writing 0
				return false;
			BIO *mem = BIO_new(BIO_s_mem());
			BIO_write(mem, data.getData(), data.getSize());
			X509 * cax = PEM_read_bio_X509(mem, NULL, 0, const_cast<char *>(password.c_str())); // Stupid C guys
			BIO_free(mem);
			mem = 0;
			
			mem = BIO_new(BIO_s_mem());
			BIO_write(mem, data.getData(), data.getSize());
			EVP_PKEY * pkey = PEM_read_bio_PrivateKey(mem, NULL, 0, const_cast<char *>(password.c_str())); // Stupid C guys
			BIO_free(mem);
			mem = 0;
			
			int cert_res = SSL_use_certificate(ssl, cax);
			if (cax)
				X509_free(cax);
			cax = 0;
			int key_res = SSL_use_PrivateKey(ssl, pkey);
			if( pkey )
				EVP_PKEY_free(pkey);
			pkey = 0;
			int check_res = SSL_check_private_key(ssl);
			return cert_res == 1 && key_res == 1 && check_res == 1;
		}
Example #3
0
bool VSslServer::setKeyCrtStuff(VError& error, SSL* con, EVP_PKEY* key, X509* crt)
{
  LOG_ASSERT(key != NULL);
  LOG_ASSERT(crt != NULL);

  // LOG_DEBUG("con=%p key=%p crt=%p", con, key, crt); // gilgil temp 2014.03.14
  int res = SSL_use_certificate(con, crt);
  if (res <= 0)
  {
    error = VSslError(QString("SSL_use_certificate return %1").arg(res), VSslError::IN_SSL_CTX_USE_CERTIFICATE);
    return false;
  }

  res = SSL_use_PrivateKey(con, key);
  if (res <= 0)
  {
    error = VSslError(QString("SSL_use_PrivateKey return %1").arg(res), VSslError::SSL_CTX_USER_PRIVATEKEY);
    return false;
  }

  res = SSL_check_private_key(con);
  if (!res)
  {
    error = VSslError(QString("SSL_check_private_key return %1").arg(res), VSslError::SSL_CTX_CHECK_PRIVATEKEY);
    return false;
  }

  return true;
}
Example #4
0
int tls_connection_private_key(void *_ssl_ctx, struct tls_connection *conn,
			       const char *private_key,
			       const char *private_key_passwd)
{
	SSL_CTX *ssl_ctx = _ssl_ctx;
	char *passwd;

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

	if (private_key_passwd) {
		passwd = strdup(private_key_passwd);
		if (passwd == NULL)
			return -1;
	} else
		passwd = NULL;

	SSL_CTX_set_default_passwd_cb(ssl_ctx, tls_passwd_cb);
	SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, passwd);
	if (SSL_use_PrivateKey_file(conn->ssl, private_key,
				    SSL_FILETYPE_ASN1) != 1 &&
	    SSL_use_PrivateKey_file(conn->ssl, private_key,
				    SSL_FILETYPE_PEM) != 1 &&
	    tls_read_pkcs12(ssl_ctx, conn->ssl, private_key, passwd)) {
		wpa_printf(MSG_INFO, "SSL: Failed to load private key: %s",
			   ERR_error_string(ERR_get_error(), NULL));
		free(passwd);
		ERR_clear_error();
		return -1;
	}
	ERR_clear_error();
	free(passwd);
	SSL_CTX_set_default_passwd_cb(ssl_ctx, NULL);
	
	if (!SSL_check_private_key(conn->ssl)) {
		wpa_printf(MSG_INFO, "SSL: Private key failed "
			   "verification: %s",
			   ERR_error_string(ERR_get_error(), NULL));
		return -1;
	}

	return 0;
}
Example #5
0
static int conn_init_client_ssl(Connection *ret, Octstr *certkeyfile)
{
    ret->ssl = SSL_new(global_ssl_context);

    /*
     * The current thread's error queue must be empty before
     * the TLS/SSL I/O operation is attempted, or SSL_get_error()
     * will not work reliably.
     */
    ERR_clear_error();

    if (certkeyfile != NULL) {
        SSL_use_certificate_file(ret->ssl, octstr_get_cstr(certkeyfile),
                                 SSL_FILETYPE_PEM);
        SSL_use_PrivateKey_file(ret->ssl, octstr_get_cstr(certkeyfile),
                                SSL_FILETYPE_PEM);
        if (SSL_check_private_key(ret->ssl) != 1) {
            error(0, "conn_open_ssl: private key isn't consistent with the "
                     "certificate from file %s (or failed reading the file)",
                  octstr_get_cstr(certkeyfile));
            return -1;
        }
    }

    /* SSL_set_fd can fail, so check it */
    if (SSL_set_fd(ret->ssl, ret->fd) == 0) {
        /* SSL_set_fd failed, log error */
        error(errno, "SSL: OpenSSL: %.256s", ERR_error_string(ERR_get_error(), NULL));
        return -1;
    }

    /*
     * make sure the socket is non-blocking while we do SSL_connect
     */
    if (socket_set_blocking(ret->fd, 0) < 0) {
        return -1;
    }
    BIO_set_nbio(SSL_get_rbio(ret->ssl), 1);
    BIO_set_nbio(SSL_get_wbio(ret->ssl), 1);

    SSL_set_connect_state(ret->ssl);
    
    return 0;
}
Example #6
0
static int openssl_ssl_use(lua_State*L)
{
  SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl");
  X509* x = CHECK_OBJECT(2, X509, "openssl.x509");
  EVP_PKEY* pkey = CHECK_OBJECT(3, EVP_PKEY, "openssl.evp_pkey");
  int ret;

  luaL_argcheck(L, openssl_pkey_is_private(pkey), 3, "must be private key");
  ret = SSL_use_PrivateKey(s, pkey);
  if (ret == 1)
  {
    ret = SSL_use_certificate(s, x);
    if (ret == 1)
    {
      ret = SSL_check_private_key(s);
    }
  }
  return openssl_pushresult(L, ret);
}
Example #7
0
/* Load certificate and private key */
static void tls_certkey(SSL *_tls)
{
	int ret, ret2;

	if(!_tls)
	{
		TLSERROR("Certificate cannot be loaded.");
		return;
	}

	if((!_key) || (!_cert) || (!_callback))
	{
		printf("WARNING: certificates are disabled!\n");
		return;
	}

	SSL_CTX_set_default_passwd_cb(_tlsctx, _callback);

	/*ret = SSL_CTX_load_verify_locations(_tlsctx, "/usr/lib/ssl/cacert.pem", NULL);
	if(ret != 1)
	{
		TLSERROR("Couldn't load root CA file!");
		ret2 = ERR_get_error();
		printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL),
		ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2));
	}*/

	ret = SSL_use_RSAPrivateKey_file(_tls, _key, SSL_FILETYPE_PEM);
	if(ret != 1)
	{
		TLSERROR("Error loading TLS PEM private key.");
		ret2 = ERR_get_error();
		printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL),
		ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2));
	}
	ret = SSL_use_certificate_file(_tls, _cert, SSL_FILETYPE_PEM);
	if(ret != 1) TLSERROR("Error loading TLS PEM certificate.");
	ret = SSL_check_private_key(_tls);
	if(!ret) TLSERROR("Private key doesn't match certificate public key.");
	printf("*** certificate loaded ***\n");
}
Example #8
0
QByteArray SSLConnect::getUrl( RequestType type, const QString &value )
{
	if( !d->ssl )
		return QByteArray();

	if( !SSL_check_private_key( d->ssl ) )
	{
		d->setError();
		return QByteArray();
	}

	QString label;
	HTTPRequest req;
	switch( type )
	{
	case AccessCert:
	{
		label = tr("Loading server access certificate. Please wait.");
		SOAPDocument s( "GetAccessToken", "urn:GetAccessToken" );
		s.writeParameter( "Language", Settings::language().toUpper() );
		s.writeParameter( "RequestTime", "" );
		s.writeParameter( "SoftwareName", "DigiDoc3" );
		s.writeParameter( "SoftwareVersion", qApp->applicationVersion() );
		s.finalize();
		req = HTTPRequest( "POST", "1.1", "https://id.sk.ee/GetAccessTokenWS/" );
		req.setRawHeader( "Content-Type", "text/xml" );
		req.setRawHeader( "SOAPAction", QByteArray() );
		req.setRawHeader( "Connection", "close" );
		req.setContent( s.document() );
		break;
	}
	case MobileInfo:
	{
		label = tr("Loading Mobile info");
		SOAPDocument s( "GetMIDTokens", "urn:GetMIDTokens" );
		s.finalize();
		req = HTTPRequest( "POST", "1.1", "https://id.sk.ee/MIDInfoWS/" );
		req.setRawHeader( "Content-Type", "text/xml" );
		req.setRawHeader( "SOAPAction", QByteArray() );
		req.setRawHeader( "Connection", "close" );
		req.setContent( s.document() );
		break;
	}
	case EmailInfo:
		label = tr("Loading Email info");
		req = HTTPRequest( "GET", "1.0",
			"https://sisene.www.eesti.ee/idportaal/postisysteem.naita_suunamised" );
		break;
	case ActivateEmails:
		label = tr("Loading Email info");
		req = HTTPRequest( "GET", "1.0",
			QString("https://www.eesti.ee/portaal/!postisysteem.suunamised?%1").arg( value ) );
		break;
	case PictureInfo:
		label = tr("Downloading picture");
		req = HTTPRequest( "GET", "1.0",
			"https://sisene.www.eesti.ee/idportaal/portaal.idpilt" );
		break;
	default: return QByteArray();
	}

	QByteArray url = req.url().host().toUtf8();
	BIO *sock = BIO_new_connect( (char*)url.constData() );
	BIO_set_conn_port( sock, "https" );
	if( BIO_do_connect( sock ) <= 0 )
	{
		d->setError( tr( "Failed to connect to host. Are you connected to the internet?" ) );
		return QByteArray();
	}

	SSL_set_bio( d->ssl, sock, sock );
	if( !SSL_connect( d->ssl ) )
	{
		d->setError();
		return QByteArray();
	}

	QByteArray header = req.request();
	if( !SSL_write( d->ssl, header.constData(), header.size() ) )
	{
		d->setError();
		return QByteArray();
	}

	QProgressDialog p( label, QString(), 0, 0, qApp->activeWindow() );
	p.setWindowFlags( (p.windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowCloseButtonHint );
	if( QProgressBar *bar = p.findChild<QProgressBar*>() )
		bar->setTextVisible( false );
	p.open();

	return SSLReadThread( d ).waitForDone();
}
Example #9
0
/** Create a new server TLS session
 *
 * Configures a new server TLS session, configuring options, setting callbacks etc...
 *
 * @param ctx		to alloc session data in. Should usually be NULL unless the lifetime of the
 *			session is tied to another talloc'd object.
 * @param conf		values for this TLS session.
 * @param request	The current #REQUEST.
 * @param client_cert	Whether to require a client_cert.
 * @return
 *	- A new session on success.
 *	- NULL on error.
 */
tls_session_t *tls_session_init_server(TALLOC_CTX *ctx, fr_tls_conf_t *conf, REQUEST *request, bool client_cert)
{
	tls_session_t	*session = NULL;
	SSL		*new_tls = NULL;
	int		verify_mode = 0;
	VALUE_PAIR	*vp;
	SSL_CTX		*ssl_ctx;

	rad_assert(request != NULL);
	rad_assert(conf->ctx_count > 0);

	RDEBUG2("Initiating new TLS session");

	ssl_ctx = conf->ctx[(conf->ctx_count == 1) ? 0 : conf->ctx_next++ % conf->ctx_count];	/* mutex not needed */
	rad_assert(ssl_ctx);

	new_tls = SSL_new(ssl_ctx);
	if (new_tls == NULL) {
		tls_log_error(request, "Error creating new TLS session");
		return NULL;
	}

	session = talloc_zero(ctx, tls_session_t);
	if (session == NULL) {
		RERROR("Error allocating memory for TLS session");
		SSL_free(new_tls);

		return NULL;
	}
	session_init(session);
	session->ctx = ssl_ctx;
	session->ssl = new_tls;

	talloc_set_destructor(session, _tls_session_free);

	/*
	 *	Initialize callbacks
	 */
	session->record_init = record_init;
	session->record_close = record_close;
	session->record_from_buff = record_from_buff;
	session->record_to_buff = record_to_buff;

	/*
	 *	Create & hook the BIOs to handle the dirty side of the
	 *	SSL.  This is *very important* as we want to handle
	 *	the transmission part.  Now the only IO interface
	 *	that SSL is aware of, is our defined BIO buffers.
	 *
	 *	This means that all SSL IO is done to/from memory,
	 *	and we can update those BIOs from the packets we've
	 *	received.
	 */
	session->into_ssl = BIO_new(BIO_s_mem());
	session->from_ssl = BIO_new(BIO_s_mem());
	SSL_set_bio(session->ssl, session->into_ssl, session->from_ssl);

	/*
	 *	Add the message callback to identify what type of
	 *	message/handshake is passed
	 */
	SSL_set_msg_callback(new_tls, tls_session_msg_cb);
	SSL_set_msg_callback_arg(new_tls, session);
	SSL_set_info_callback(new_tls, tls_session_info_cb);

	/*
	 *	This sets the context sessions can be resumed in.
	 *	This is to prevent sessions being created by one application
	 *	and used by another.  In our case it prevents sessions being
	 *	reused between modules, or TLS server components such as
	 *	RADSEC.
	 *
	 *	A context must always be set when doing session resumption
	 *	otherwise session resumption will fail.
	 *
	 *	As the context ID must be <= 32, we digest the context
	 *	data with sha256.
	 */
	rad_assert(conf->session_id_name);
	{
		char		*context_id;
		EVP_MD_CTX	*md_ctx;
		uint8_t		digest[SHA256_DIGEST_LENGTH];

		static_assert(sizeof(digest) <= SSL_MAX_SSL_SESSION_ID_LENGTH,
			      "SSL_MAX_SSL_SESSION_ID_LENGTH must be >= SHA256_DIGEST_LENGTH");

		if (tmpl_aexpand(session, &context_id, request, conf->session_id_name, NULL, NULL) < 0) {
			RPEDEBUG("Failed expanding session ID");
			talloc_free(session);
		}

		MEM(md_ctx = EVP_MD_CTX_create());
		EVP_DigestInit_ex(md_ctx, EVP_sha256(), NULL);
		EVP_DigestUpdate(md_ctx, context_id, talloc_array_length(context_id) - 1);
		EVP_DigestFinal_ex(md_ctx, digest, NULL);
		EVP_MD_CTX_destroy(md_ctx);
		talloc_free(context_id);

		if (!fr_cond_assert(SSL_set_session_id_context(session->ssl, digest, sizeof(digest)) == 1)) {
			talloc_free(session);
			return NULL;
		}
	}

	/*
	 *	Add the session certificate to the session.
	 */
	vp = fr_pair_find_by_da(request->control, attr_tls_session_cert_file, TAG_ANY);
	if (vp) {
		RDEBUG2("Loading TLS session certificate \"%s\"", vp->vp_strvalue);

		if (SSL_use_certificate_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
			tls_log_error(request, "Failed loading TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}

		if (SSL_use_PrivateKey_file(session->ssl, vp->vp_strvalue, SSL_FILETYPE_PEM) != 1) {
			tls_log_error(request, "Failed loading TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}

		if (SSL_check_private_key(session->ssl) != 1) {
			tls_log_error(request, "Failed validating TLS session certificate \"%s\"",
				      vp->vp_strvalue);
			talloc_free(session);
			return NULL;
		}
	/*
	 *	Better to perform explicit checks, than rely
	 *	on OpenSSL's opaque error messages.
	 */
	} else {
		if (!conf->chains || !conf->chains[0]->private_key_file) {
			ERROR("TLS Server requires a private key file");
			talloc_free(session);
			return NULL;
		}

		if (!conf->chains || !conf->chains[0]->certificate_file) {
			ERROR("TLS Server requires a certificate file");
			talloc_free(session);
			return NULL;
		}
	}

	/*
	 *	In Server mode we only accept.
	 *
	 *	This sets up the SSL session to work correctly with
	 *	tls_session_handhsake.
	 */
	SSL_set_accept_state(session->ssl);

	/*
	 *	Verify the peer certificate, if asked.
	 */
	if (client_cert) {
		RDEBUG2("Setting verify mode to require certificate from client");
		verify_mode = SSL_VERIFY_PEER;
		verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		verify_mode |= SSL_VERIFY_CLIENT_ONCE;
	}
	SSL_set_verify(session->ssl, verify_mode, tls_validate_cert_cb);

	SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_CONF, (void *)conf);
	SSL_set_ex_data(session->ssl, FR_TLS_EX_INDEX_TLS_SESSION, (void *)session);

	/*
	 *	We use default fragment size, unless the Framed-MTU
	 *	tells us it's too big.  Note that we do NOT account
	 *	for the EAP-TLS headers if conf->fragment_size is
	 *	large, because that config item looks to be confusing.
	 *
	 *	i.e. it should REALLY be called MTU, and the code here
	 *	should figure out what that means for TLS fragment size.
	 *	asking the administrator to know the internal details
	 *	of EAP-TLS in order to calculate fragment sizes is
	 *	just too much.
	 */
	session->mtu = conf->fragment_size;
	vp = fr_pair_find_by_da(request->packet->vps, attr_framed_mtu, TAG_ANY);
	if (vp && (vp->vp_uint32 > 100) && (vp->vp_uint32 < session->mtu)) {
		RDEBUG2("Setting fragment_len to %u from &Framed-MTU", vp->vp_uint32);
		session->mtu = vp->vp_uint32;
	}

	if (conf->session_cache_server) session->allow_session_resumption = true; /* otherwise it's false */

	return session;
}