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; }
/// loads one private key int Certificate::loadPrivateKeyFromFile( void ) { const int certificateFileCheckResult = validateCertificateFilename(m_privkeyfn); if(certificateFileCheckResult < 0) return certificateFileCheckResult; m_ssl = SSL_new( SSL_CTX_new( SSLv23_method() ) ); SSL_use_PrivateKey_file( m_ssl, m_privkeyfn.c_str(), m_type); return( 0 ); }
static int cmd_PrivateKey(SSL_CONF_CTX *cctx, const char *value) { int rv = 1; if (!(cctx->flags & SSL_CONF_FLAG_CERTIFICATE)) return -2; if (cctx->ctx) rv = SSL_CTX_use_PrivateKey_file(cctx->ctx, value, SSL_FILETYPE_PEM); if (cctx->ssl) rv = SSL_use_PrivateKey_file(cctx->ssl, value, SSL_FILETYPE_PEM); return rv > 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; }
DSCRPTR nbr_ssl_accept(DSCRPTR fd, void *addr, int *alen, SKCONF *cfg) { int r, ret; sslfd_t *sfd = nbr_array_alloc(g_ssl.socks), *afd = (sslfd_t *)fd; if (!sfd) { SSL_ERROUT(ERROR,EXPIRE,"sfd alloc fail"); goto bad; } if ((sfd->fd = nbr_osdep_tcp_accept(afd->fd, addr, alen, cfg)) == INVALID_FD) { SSL_ERROUT(ERROR,ACCEPT,"ssl accept fail"); goto bad; } if (!(sfd->ssl = SSL_new(g_ssl.server))) { SSL_ERROUT(ERROR,EXPIRE,"ssl new fail"); goto bad; } #if defined(_DEBUG) sfd->ssl->info_callback = (void (*)())ssl_info_callback; #endif if (!g_ssl.pubkey || SSL_use_certificate_file(sfd->ssl, g_ssl.pubkey, SSL_FILETYPE_PEM) < 0) { SSL_ERROUT(ERROR,EXPIRE,"ssl SSL_use_certificate_file fail"); goto bad; } if (!g_ssl.privkey || SSL_use_PrivateKey_file(sfd->ssl, g_ssl.privkey, SSL_FILETYPE_PEM) < 0) { SSL_ERROUT(ERROR,EXPIRE,"ssl SSL_use_PrivateKey_file fail"); goto bad; } SSL_set_fd(sfd->ssl, sfd->fd); if ((r = SSL_accept(sfd->ssl)) <= 0) { ret = SSL_get_error(sfd->ssl, ret); if (ret == SSL_ERROR_WANT_READ || ret == SSL_ERROR_WANT_WRITE) { return 0; /* connection pending */ } ERR_print_errors_fp(stderr); SSL_ERROUT(ERROR,ACCEPT,"ssl_accept fail (%d/%d)", r, ret); goto bad; } return (DSCRPTR)sfd; bad: ssl_free_fd(sfd); return INVALID_FD; }
int main( int argc, char *argv[]) { int port = 10001; int n; int s; if (argc > 1) { sscanf( argv[1], "%d", &port); } SSL_library_init(); SSL_load_error_strings(); s = socket( PF_INET, SOCK_STREAM, 0); if (s != -1) { int cs; char buf[1024]; struct sockaddr_in sa; int on; on = 1; setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof( on)); memset( &sa, 0, sizeof( sa)); sa.sin_family = AF_INET; sa.sin_port = htons( port); sa.sin_addr.s_addr = INADDR_ANY; bind( s, (struct sockaddr *)&sa, sizeof( sa)); listen( s, 1); while (1) { printf( "accepting on port %d..\n", port); cs = accept( s, NULL, NULL); if (cs != -1) { SSL *ssl = 0; SSL_CTX *ssl_ctx = 0; ssl_ctx = SSL_CTX_new( SSLv23_server_method()); if (ssl_ctx) { ssl = SSL_new( ssl_ctx); if (ssl) { n = SSL_use_PrivateKey_file( ssl, key_file, 1); if (n != 1) printf( "failed to SSL use key (%d, %d)\n", n, SSL_get_error( ssl, n)); n = SSL_use_certificate_file( ssl, certificate_file, 1); if (n != 1) printf( "failed to SSL use cert (%d, %d)\n", n, SSL_get_error( ssl, n)); if (SSL_set_fd( ssl, cs)) { printf( "SSL accepting..\n"); n = SSL_accept( ssl); if (n == 1) { printf( "ssl initiated\n"); if ((n = SSL_read( ssl, buf, sizeof( buf))) > 0) { if (n > (sizeof( buf) - 1)) n = sizeof( buf) - 1; buf[n] = 0; printf( "SSL_read %d bytes [%s]\n", n, buf); } else printf( "failed to SSL read\n"); } else { #ifdef WIN32 unsigned long err = ERR_get_error(); printf( "failed to SSL accept (%d, %d) (%ld, %s)\n", n, SSL_get_error( ssl, n), err, ERR_error_string( err, NULL)); #else printf( "failed to SSL accept (%d)\n", n); #endif } } else printf( "failed to SSL set fd\n"); SSL_shutdown( ssl); } else printf( "couldn't create server ssl\n"); SSL_CTX_free( ssl_ctx); } else printf( "couldn't create server ctx\n"); close( cs); } else perror( "accept"); } } else perror( "socket"); return 0; }
static int ngx_http_multiple_ssl_set_der_certificate(ngx_ssl_conn_t *ssl_conn, ngx_str_t *cert, ngx_str_t *key) { BIO *bio = NULL; X509 *x509 = NULL; u_long n; bio = BIO_new_file((char *) cert->data, "r"); if (bio == NULL) { return NGX_ERROR; } x509 = PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL); if (x509 == NULL) { BIO_free(bio); return NGX_ERROR; } SSL_certs_clear(ssl_conn); if (SSL_use_certificate(ssl_conn, x509) == 0) { X509_free(x509); BIO_free(bio); return NGX_ERROR; } #if 0 if (SSL_set_ex_data(ssl_conn, ngx_ssl_certificate_index, x509) == 0) { X509_free(x509); BIO_free(bio); return NGX_ERROR; } #endif X509_free(x509); x509 = NULL; /* read rest of the chain */ for ( ;; ) { x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (x509 == NULL) { n = ERR_peek_last_error(); if (ERR_GET_LIB(n) == ERR_LIB_PEM && ERR_GET_REASON(n) == PEM_R_NO_START_LINE) { ERR_clear_error(); break; } BIO_free(bio); return NGX_ERROR; } if (SSL_add0_chain_cert(ssl_conn, x509) == 0) { X509_free(x509); BIO_free(bio); return NGX_ERROR; } } BIO_free(bio); bio = NULL; if (SSL_use_PrivateKey_file(ssl_conn, (char *) key->data, SSL_FILETYPE_PEM) != 1) { return NGX_ERROR; } return NGX_OK; }
/** 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; }