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