Initial work splitting OpenSSL code away.

This work moves all TLS / crypto related code into a tls_openssl.c
file and adds a tls_none.c which contains just stubs.

Allows compilation of Kore with TLS_BACKEND=none to remove building
against OpenSSL.

Also adds code for SHA1/SHA2 taken from openssh-portable so we don't
depend on those being present anymore in libcrypto.
This commit is contained in:
Joris Vink 2022-02-17 13:45:28 +01:00
parent 6dc162e7ee
commit 99a1581e19
20 changed files with 2585 additions and 1222 deletions

View File

@ -12,6 +12,7 @@ INSTALL_DIR=$(PREFIX)/bin
MAN_DIR?=$(PREFIX)/share/man
SHARE_DIR=$(PREFIX)/share/kore
INCLUDE_DIR=$(PREFIX)/include/kore
TLS_BACKEND?=openssl
TOOLS= kore-serve
@ -23,7 +24,8 @@ PYTHON_CURLOPT=misc/curl/python_curlopt.h
S_SRC= src/kore.c src/buf.c src/config.c src/connection.c \
src/domain.c src/filemap.c src/fileref.c src/json.c src/log.c \
src/mem.c src/msg.c src/module.c src/net.c src/pool.c src/runtime.c \
src/timer.c src/utils.c src/worker.c src/keymgr.c
src/sha1.c src/sha2.c src/timer.c src/utils.c src/worker.c
S_SRC+= src/tls_$(TLS_BACKEND).c
FEATURES=
FEATURES_INC=
@ -34,11 +36,15 @@ CFLAGS+=-Wsign-compare -Iinclude/kore -I$(OBJDIR) -std=c99 -pedantic
CFLAGS+=-Wtype-limits -fno-common
CFLAGS+=-DPREFIX='"$(PREFIX)"' -fstack-protector-all
ifneq ("$(OPENSSL_PATH)", "")
CFLAGS+=-I$(OPENSSL_PATH)/include
LDFLAGS+=-rdynamic -L$(OPENSSL_PATH)/lib -lssl -l$(KORE_CRYPTO)
else
LDFLAGS+=-rdynamic -lssl -l$(KORE_CRYPTO)
ifeq ("$(TLS_BACKEND)", "openssl")
S_SRC+=src/keymgr_openssl.c
ifneq ("$(OPENSSL_PATH)", "")
CFLAGS+=-I$(OPENSSL_PATH)/include
LDFLAGS+=-rdynamic -L$(OPENSSL_PATH)/lib -lssl -l$(KORE_CRYPTO)
else
LDFLAGS+=-rdynamic -lssl -l$(KORE_CRYPTO)
endif
endif
ifneq ("$(KORE_SINGLE_BINARY)", "")
@ -132,10 +138,12 @@ ifneq ("$(SANITIZE)", "")
endif
ifeq ("$(OSNAME)", "darwin")
OSSL_INCL=$(shell pkg-config openssl --cflags)
CFLAGS+=$(OSSL_INCL)
LDFLAGS+=$(shell pkg-config openssl --libs)
FEATURES_INC+=$(OSSL_INCL)
ifeq ("$(TLS_BACKEND)", "openssl")
OSSL_INCL=$(shell pkg-config openssl --cflags)
CFLAGS+=$(OSSL_INCL)
LDFLAGS+=$(shell pkg-config openssl --libs)
FEATURES_INC+=$(OSSL_INCL)
endif
S_SRC+=src/bsd.c
else ifeq ("$(OSNAME)", "linux")
CFLAGS+=-D_GNU_SOURCE=1 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2

View File

@ -49,10 +49,6 @@ void kore_acme_run(void);
void kore_acme_setup(void);
void kore_acme_get_paths(const char *, char **, char **);
void kore_acme_tls_challenge_use_cert(SSL *, struct kore_domain *);
int kore_acme_tls_alpn(SSL *, const unsigned char **, unsigned char *,
const unsigned char *, unsigned int, void *);
extern char *acme_email;
extern int acme_domains;
extern char *acme_provider;

View File

@ -22,7 +22,7 @@
#include <sys/types.h>
#include <sys/queue.h>
#include <openssl/sha.h>
#include "sha2.h"
#if defined(__cplusplus)
extern "C" {
@ -281,7 +281,7 @@ struct http_request {
const char *agent;
const char *referer;
struct connection *owner;
SHA256_CTX hashctx;
SHA2_CTX hashctx;
u_int8_t *headers;
struct kore_buf *http_body;
int http_body_fd;

View File

@ -30,10 +30,6 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/err.h>
#include <openssl/dh.h>
#include <openssl/ssl.h>
#include <errno.h>
#include <regex.h>
#include <stdarg.h>
@ -61,24 +57,6 @@ extern int daemon(int, int);
#endif
#endif
/*
* Figure out what type of OpenSSL API we are dealing with.
*/
#if defined(LIBRESSL_VERSION_NUMBER)
#if LIBRESSL_VERSION_NUMBER >= 0x3000000fL
#define KORE_OPENSSL_NEWER_API 1
#endif
#if LIBRESSL_VERSION_NUMBER >= 0x3020200fL
#define TLS1_3_VERSION 0x0304
#endif
#else
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
#define KORE_OPENSSL_NEWER_API 1
#endif
#endif
#if defined(__OpenBSD__)
#define KORE_USE_PLATFORM_PLEDGE 1
#endif
@ -236,8 +214,8 @@ struct connection {
u_int8_t state;
u_int8_t proto;
struct listener *owner;
X509 *cert;
SSL *ssl;
void *ssl;
void *cert;
char *tls_sni;
int tls_reneg;
u_int16_t flags;
@ -359,7 +337,7 @@ struct kore_domain {
char *crlfile;
char *certfile;
char *certkey;
SSL_CTX *ssl_ctx;
void *ssl_ctx;
int x509_verify_depth;
#if !defined(KORE_NO_HTTP)
TAILQ_HEAD(, kore_route) routes;
@ -610,8 +588,8 @@ struct kore_json_item {
u_int64_t u64;
} data;
int (*parse)(struct kore_json *,
struct kore_json_item *);
int (*parse)(struct kore_json *,
struct kore_json_item *);
TAILQ_ENTRY(kore_json_item) list;
};
@ -720,14 +698,11 @@ extern int skip_runas;
extern int kore_foreground;
extern char *kore_pidfile;
extern char *kore_tls_cipher_list;
extern volatile sig_atomic_t sig_recv;
extern int tls_version;
extern DH *tls_dhparam;
extern char *rand_file;
extern int keymgr_active;
extern char *kore_rand_file;
extern int kore_keymgr_active;
extern struct kore_privsep worker_privsep;
extern struct kore_privsep keymgr_privsep;
@ -753,6 +728,7 @@ extern struct kore_pool nb_pool;
extern struct kore_domain *primary_dom;
extern struct kore_server_list kore_servers;
/* kore.c */
void kore_signal(int);
void kore_shutdown(void);
void kore_signal_trap(int);
@ -760,6 +736,26 @@ void kore_signal_setup(void);
void kore_proctitle(const char *);
void kore_default_getopt(int, char **);
void kore_server_closeall(void);
void kore_server_cleanup(void);
void kore_server_free(struct kore_server *);
void kore_server_finalize(struct kore_server *);
struct kore_server *kore_server_create(const char *);
struct kore_server *kore_server_lookup(const char *);
void kore_listener_accept(void *, int);
struct listener *kore_listener_lookup(const char *);
void kore_listener_free(struct listener *);
struct listener *kore_listener_create(struct kore_server *);
int kore_listener_init(struct listener *, int, const char *);
int kore_sockopt(int, int, int);
int kore_server_bind_unix(struct kore_server *,
const char *, const char *);
int kore_server_bind(struct kore_server *,
const char *, const char *, const char *);
/* worker.c */
void kore_worker_reap(void);
int kore_worker_init(void);
void kore_worker_privsep(void);
@ -776,6 +772,7 @@ void kore_worker_entry(struct kore_worker *) __attribute__((noreturn));
struct kore_worker *kore_worker_data(u_int8_t);
struct kore_worker *kore_worker_data_byid(u_int16_t);
/* platform code (linux.c, bsd.c) */
void kore_platform_init(void);
void kore_platform_sandbox(void);
void kore_platform_event_init(void);
@ -803,12 +800,43 @@ void kore_platform_pledge(void);
void kore_platform_add_pledge(const char *);
#endif
/* tls variants. */
#define KORE_X509_NAME_COMMON_NAME 1
void kore_tls_init(void);
void kore_tls_cleanup(void);
void kore_tls_dh_check(void);
int kore_tls_supported(void);
void kore_tls_version_set(int);
void kore_tls_keymgr_init(void);
int kore_tls_dh_load(const char *);
void kore_tls_seed(const void *, size_t);
int kore_tls_ciphersuite_set(const char *);
int kore_tls_read(struct connection *, size_t *);
void kore_tls_domain_cleanup(struct kore_domain *);
int kore_tls_connection_accept(struct connection *);
void kore_tls_connection_cleanup(struct connection *);
int kore_tls_write(struct connection *, size_t, size_t *);
void kore_tls_domain_crl(struct kore_domain *, const void *, size_t);
void kore_tls_domain_setup(struct kore_domain *,
int, const void *, size_t);
void *kore_tls_rsakey_load(const char *);
void *kore_tls_rsakey_generate(const char *);
void *kore_tls_x509_issuer_name(struct connection *);
void *kore_tls_x509_subject_name(struct connection *);
int kore_tls_x509name_foreach(void *, int, void *,
int (*)(void *, int, int, const char *,
const void *, size_t, int));
/* accesslog.c */
void kore_accesslog_init(u_int16_t);
void kore_accesslog_worker_init(void);
void kore_accesslog_run(void *, u_int64_t);
void kore_accesslog_gather(void *, u_int64_t, int);
#if !defined(KORE_NO_HTTP)
/* auth.c */
int kore_auth_run(struct http_request *, struct kore_auth *);
int kore_auth_cookie(struct http_request *, struct kore_auth *);
int kore_auth_header(struct http_request *, struct kore_auth *);
@ -818,6 +846,7 @@ int kore_auth_new(const char *);
struct kore_auth *kore_auth_lookup(const char *);
#endif
/* timer.c */
void kore_timer_init(void);
void kore_timer_run(u_int64_t);
u_int64_t kore_timer_next_run(u_int64_t);
@ -825,29 +854,7 @@ void kore_timer_remove(struct kore_timer *);
struct kore_timer *kore_timer_add(void (*cb)(void *, u_int64_t),
u_int64_t, void *, int);
void kore_server_closeall(void);
void kore_server_cleanup(void);
void kore_server_free(struct kore_server *);
void kore_server_finalize(struct kore_server *);
struct kore_server *kore_server_create(const char *);
struct kore_server *kore_server_lookup(const char *);
void kore_listener_accept(void *, int);
struct listener *kore_listener_lookup(const char *);
void kore_listener_free(struct listener *);
struct listener *kore_listener_create(struct kore_server *);
int kore_listener_init(struct listener *, int, const char *);
int kore_sockopt(int, int, int);
int kore_server_bind_unix(struct kore_server *,
const char *, const char *);
int kore_server_bind(struct kore_server *,
const char *, const char *, const char *);
int kore_tls_sni_cb(SSL *, int *, void *);
void kore_tls_info_callback(const SSL *, int, int);
/* connection.c */
void kore_connection_init(void);
void kore_connection_cleanup(void);
void kore_connection_prune(int);
@ -865,7 +872,6 @@ void kore_connection_check_idletimer(u_int64_t,
int kore_connection_accept(struct listener *,
struct connection **);
u_int64_t kore_time_ms(void);
void kore_log_init(void);
void kore_log_file(const char *);
@ -873,9 +879,12 @@ void kore_log_file(const char *);
int kore_configure_setting(const char *, char *);
#endif
void *kore_malloc(size_t);
/* config.c */
void kore_parse_config(void);
void kore_parse_config_file(FILE *);
/* mem.c */
void *kore_malloc(size_t);
void *kore_calloc(size_t, size_t);
void *kore_realloc(void *, size_t);
void kore_free(void *);
@ -886,12 +895,19 @@ void *kore_mem_lookup(u_int32_t);
void kore_mem_tag(void *, u_int32_t);
void *kore_malloc_tagged(size_t, u_int32_t);
/* pool.c */
void *kore_pool_get(struct kore_pool *);
void kore_pool_put(struct kore_pool *, void *);
void kore_pool_init(struct kore_pool *, const char *,
size_t, size_t);
void kore_pool_cleanup(struct kore_pool *);
/* utils.c */
void kore_debug_internal(char *, int, const char *, ...);
void fatal(const char *, ...) __attribute__((noreturn));
void fatalx(const char *, ...) __attribute__((noreturn));
u_int64_t kore_time_ms(void);
char *kore_time_to_date(time_t);
char *kore_strdup(const char *);
time_t kore_date_to_time(const char *);
@ -909,19 +925,15 @@ int kore_base64_encode(const void *, size_t, char **);
int kore_base64_decode(const char *, u_int8_t **, size_t *);
int kore_base64url_encode(const void *, size_t, char **, int);
int kore_base64url_decode(const char *, u_int8_t **, size_t *, int);
int kore_x509_issuer_name(struct connection *, char **, int);
int kore_x509_subject_name(struct connection *, char **, int);
void *kore_mem_find(void *, size_t, const void *, size_t);
char *kore_text_trim(char *, size_t);
char *kore_read_line(FILE *, char *, size_t);
EVP_PKEY *kore_rsakey_load(const char *);
EVP_PKEY *kore_rsakey_generate(const char *);
int kore_x509_issuer_name(struct connection *, char **, int);
int kore_x509_subject_name(struct connection *, char **, int);
int kore_x509name_foreach(X509_NAME *, int, void *,
int (*)(void *, int, int, const char *,
const void *, size_t, int));
#if !defined(KORE_NO_HTTP)
/* websocket.c */
void kore_websocket_handshake(struct http_request *,
const char *, const char *, const char *);
int kore_websocket_send_clean(struct netbuf *);
@ -931,6 +943,7 @@ void kore_websocket_broadcast(struct connection *,
u_int8_t, const void *, size_t, int);
#endif
/* msg.c */
void kore_msg_init(void);
void kore_msg_worker_init(void);
void kore_msg_parent_init(void);
@ -942,6 +955,7 @@ int kore_msg_register(u_int8_t,
void (*cb)(struct kore_msg *, const void *));
#if !defined(KORE_NO_HTTP)
/* filemap.c */
void kore_filemap_init(void);
void kore_filemap_resolve_paths(void);
int kore_filemap_create(struct kore_domain *, const char *,
@ -950,13 +964,17 @@ extern char *kore_filemap_ext;
extern char *kore_filemap_index;
#endif
/* fileref.c */
void kore_fileref_init(void);
struct kore_fileref *kore_fileref_get(const char *, int);
struct kore_fileref *kore_fileref_create(struct kore_server *,
const char *, int, off_t, struct timespec *);
void kore_fileref_release(struct kore_fileref *);
/* domain.c */
struct kore_domain *kore_domain_new(const char *);
struct kore_domain *kore_domain_byid(u_int16_t);
struct kore_domain *kore_domain_lookup(struct kore_server *, const char *);
void kore_domain_init(void);
void kore_domain_cleanup(void);
@ -972,11 +990,9 @@ void kore_domain_load_crl(void);
void kore_domain_keymgr_init(void);
void kore_domain_callback(void (*cb)(struct kore_domain *));
int kore_domain_attach(struct kore_domain *, struct kore_server *);
void kore_domain_tlsinit(struct kore_domain *, int,
const void *, size_t);
void kore_domain_crl_add(struct kore_domain *, const void *, size_t);
#if !defined(KORE_NO_HTTP)
/* route.c */
void kore_route_reload(void);
void kore_route_free(struct kore_route *);
void kore_route_callback(struct kore_route *, const char *);
@ -987,6 +1003,7 @@ int kore_route_lookup(struct http_request *,
struct kore_domain *, int, struct kore_route **);
#endif
/* runtime.c */
struct kore_runtime_call *kore_runtime_getcall(const char *);
struct kore_module *kore_module_load(const char *,
const char *, int);
@ -1012,10 +1029,8 @@ void kore_runtime_wsmessage(struct kore_runtime_call *,
struct connection *, u_int8_t, const void *, size_t);
#endif
struct kore_domain *kore_domain_byid(u_int16_t);
struct kore_domain *kore_domain_lookup(struct kore_server *, const char *);
#if !defined(KORE_NO_HTTP)
/* validator.c */
void kore_validator_init(void);
void kore_validator_reload(void);
int kore_validator_add(const char *, u_int8_t, const char *);
@ -1025,12 +1040,9 @@ int kore_validator_check(struct http_request *,
struct kore_validator *kore_validator_lookup(const char *);
#endif
void fatal(const char *, ...) __attribute__((noreturn));
void fatalx(const char *, ...) __attribute__((noreturn));
const char *kore_worker_name(int);
void kore_debug_internal(char *, int, const char *, ...);
/* net.c */
u_int16_t net_read16(u_int8_t *);
u_int32_t net_read32(u_int8_t *);
u_int64_t net_read64(u_int8_t *);
@ -1045,9 +1057,7 @@ int net_send(struct connection *);
int net_send_flush(struct connection *);
int net_recv_flush(struct connection *);
int net_read(struct connection *, size_t *);
int net_read_tls(struct connection *, size_t *);
int net_write(struct connection *, size_t, size_t *);
int net_write_tls(struct connection *, size_t, size_t *);
void net_recv_reset(struct connection *, size_t,
int (*cb)(struct netbuf *));
void net_remove_netbuf(struct connection *, struct netbuf *);
@ -1060,6 +1070,7 @@ void net_send_stream(struct connection *, void *,
size_t, int (*cb)(struct netbuf *), struct netbuf **);
void net_send_fileref(struct connection *, struct kore_fileref *);
/* buf.c */
void kore_buf_free(struct kore_buf *);
struct kore_buf *kore_buf_alloc(size_t);
void kore_buf_init(struct kore_buf *, size_t);
@ -1074,6 +1085,7 @@ void kore_buf_appendv(struct kore_buf *, const char *, va_list);
void kore_buf_replace_string(struct kore_buf *,
const char *, const void *, size_t);
/* json.c */
int kore_json_errno(void);
int kore_json_parse(struct kore_json *);
void kore_json_cleanup(struct kore_json *);
@ -1088,6 +1100,7 @@ struct kore_json_item *kore_json_find(struct kore_json_item *,
struct kore_json_item *kore_json_create_item(struct kore_json_item *,
const char *, u_int32_t, ...);
/* keymgr.c */
void kore_keymgr_run(void);
void kore_keymgr_cleanup(int);

View File

@ -262,9 +262,6 @@ static char *revoke_url = NULL;
static char *account_id = NULL;
static char *account_url = NULL;
static u_int8_t acme_alpn_name[] =
{ 0xa, 'a', 'c', 'm', 'e', '-', 't', 'l', 's', '/', '1' };
struct kore_privsep acme_privsep;
int acme_domains = 0;
char *acme_email = NULL;
@ -358,39 +355,6 @@ kore_acme_run(void)
net_cleanup();
}
int
kore_acme_tls_alpn(SSL *ssl, const unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen, void *udata)
{
struct connection *c;
if ((c = SSL_get_ex_data(ssl, 0)) == NULL)
fatal("%s: no connection data present", __func__);
if (inlen != sizeof(acme_alpn_name))
return (SSL_TLSEXT_ERR_NOACK);
if (memcmp(acme_alpn_name, in, sizeof(acme_alpn_name)))
return (SSL_TLSEXT_ERR_NOACK);
*out = in + 1;
*outlen = inlen - 1;
c->flags |= CONN_TLS_ALPN_ACME_SEEN;
/*
* If SNI was already done, we can continue, otherwise we mark
* that we saw the right ALPN negotiation on this connection
* and wait for the SNI extension to be parsed.
*/
if (c->flags & CONN_TLS_SNI_SEEN) {
/* SNI was seen, we are on the right domain. */
kore_acme_tls_challenge_use_cert(ssl, udata);
}
return (SSL_TLSEXT_ERR_OK);
}
void
kore_acme_get_paths(const char *domain, char **key, char **cert)
{
@ -412,43 +376,6 @@ kore_acme_get_paths(const char *domain, char **key, char **cert)
*key = kore_strdup(path);
}
void
kore_acme_tls_challenge_use_cert(SSL *ssl, struct kore_domain *dom)
{
struct connection *c;
const unsigned char *ptr;
X509 *x509;
if (dom->acme == 0) {
kore_log(LOG_NOTICE, "[%s] ACME not active", dom->domain);
return;
}
if (dom->acme_challenge == 0) {
kore_log(LOG_NOTICE,
"[%s] ACME auth challenge not active", dom->domain);
return;
}
kore_log(LOG_INFO, "[%s] acme-tls/1 challenge requested",
dom->domain);
if ((c = SSL_get_ex_data(ssl, 0)) == NULL)
fatal("%s: no connection data present", __func__);
ptr = dom->acme_cert;
if ((x509 = d2i_X509(NULL, &ptr, dom->acme_cert_len)) == NULL)
fatal("d2i_X509: %s", ssl_errno_s);
if (SSL_use_certificate(ssl, x509) == 0)
fatal("SSL_use_certificate: %s", ssl_errno_s);
SSL_clear_chain_certs(ssl);
SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
c->proto = CONN_PROTO_ACME_ALPN;
}
static void
acme_parse_directory(void)
{

View File

@ -309,7 +309,6 @@ void
kore_parse_config(void)
{
FILE *fp;
BIO *bio;
struct passwd *pwd;
char path[PATH_MAX];
@ -334,16 +333,7 @@ kore_parse_config(void)
(void)fclose(fp);
}
if (tls_dhparam == NULL) {
if ((bio = BIO_new_file(KORE_DHPARAM_PATH, "r")) == NULL)
fatal("failed to open %s", KORE_DHPARAM_PATH);
tls_dhparam = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
if (tls_dhparam == NULL)
fatal("PEM_read_bio_DHparams(): %s", ssl_errno_s);
}
kore_tls_dh_check();
if (!kore_module_loaded())
fatal("no application module was loaded");
@ -631,8 +621,19 @@ configure_server(char *options)
static int
configure_tls(char *yesno)
{
if (!kore_tls_supported()) {
current_server->tls = 0;
if (!strcmp(yesno, "yes")) {
kore_log(LOG_ERR, "TLS not supported in this build");
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
}
if (current_server == NULL) {
kore_log(LOG_ERR, "bind keyword not inside a server context");
kore_log(LOG_ERR, "tls keyword not inside a server context");
return (KORE_RESULT_ERROR);
}
@ -805,12 +806,14 @@ configure_file(char *file)
static int
configure_tls_version(char *version)
{
int ver;
if (!strcmp(version, "1.3")) {
tls_version = KORE_TLS_VERSION_1_3;
ver = KORE_TLS_VERSION_1_3;
} else if (!strcmp(version, "1.2")) {
tls_version = KORE_TLS_VERSION_1_2;
ver = KORE_TLS_VERSION_1_2;
} else if (!strcmp(version, "both")) {
tls_version = KORE_TLS_VERSION_BOTH;
ver = KORE_TLS_VERSION_BOTH;
} else {
kore_log(LOG_ERR,
"unknown value for tls_version: %s (use 1.3, 1.2, both)",
@ -818,45 +821,21 @@ configure_tls_version(char *version)
return (KORE_RESULT_ERROR);
}
kore_tls_version_set(ver);
return (KORE_RESULT_OK);
}
static int
configure_tls_cipher(char *cipherlist)
{
if (strcmp(kore_tls_cipher_list, KORE_DEFAULT_CIPHER_LIST)) {
kore_log(LOG_ERR, "tls_cipher specified twice");
return (KORE_RESULT_ERROR);
}
kore_tls_cipher_list = kore_strdup(cipherlist);
return (KORE_RESULT_OK);
return (kore_tls_ciphersuite_set(cipherlist));
}
static int
configure_tls_dhparam(char *path)
{
BIO *bio;
if (tls_dhparam != NULL) {
kore_log(LOG_ERR, "tls_dhparam specified twice");
return (KORE_RESULT_ERROR);
}
if ((bio = BIO_new_file(path, "r")) == NULL) {
kore_log(LOG_ERR, "tls_dhparam file '%s' not accessible", path);
return (KORE_RESULT_ERROR);
}
tls_dhparam = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
if (tls_dhparam == NULL) {
kore_log(LOG_ERR, "PEM_read_bio_DHparams(): %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
return (KORE_RESULT_OK);
return (kore_tls_dh_load(path));
}
static int
@ -914,10 +893,10 @@ configure_client_verify(char *options)
static int
configure_rand_file(char *path)
{
if (rand_file != NULL)
kore_free(rand_file);
if (kore_rand_file != NULL)
kore_free(kore_rand_file);
rand_file = kore_strdup(path);
kore_rand_file = kore_strdup(path);
return (KORE_RESULT_OK);
}

View File

@ -147,8 +147,8 @@ kore_connection_accept(struct listener *listener, struct connection **out)
if (listener->server->tls) {
c->state = CONN_STATE_TLS_SHAKE;
c->write = net_write_tls;
c->read = net_read_tls;
c->write = kore_tls_write;
c->read = kore_tls_read;
} else {
c->state = CONN_STATE_ESTABLISHED;
c->write = net_write;
@ -250,7 +250,6 @@ kore_connection_event(void *arg, int error)
int
kore_connection_handle(struct connection *c)
{
int r;
struct listener *listener;
kore_debug("kore_connection_handle(%p) -> %d", c, c->state);
@ -258,75 +257,8 @@ kore_connection_handle(struct connection *c)
switch (c->state) {
case CONN_STATE_TLS_SHAKE:
if (primary_dom == NULL) {
kore_log(LOG_NOTICE,
"TLS handshake but no TLS configured on server");
if (!kore_tls_connection_accept(c))
return (KORE_RESULT_ERROR);
}
if (primary_dom->ssl_ctx == NULL) {
kore_log(LOG_NOTICE,
"TLS configuration for %s not yet complete",
primary_dom->domain);
return (KORE_RESULT_ERROR);
}
if (c->ssl == NULL) {
c->ssl = SSL_new(primary_dom->ssl_ctx);
if (c->ssl == NULL) {
kore_debug("SSL_new(): %s", ssl_errno_s);
return (KORE_RESULT_ERROR);
}
SSL_set_fd(c->ssl, c->fd);
SSL_set_accept_state(c->ssl);
if (!SSL_set_ex_data(c->ssl, 0, c)) {
kore_debug("SSL_set_ex_data(): %s",
ssl_errno_s);
return (KORE_RESULT_ERROR);
}
if (primary_dom->cafile != NULL)
c->flags |= CONN_LOG_TLS_FAILURE;
}
ERR_clear_error();
r = SSL_accept(c->ssl);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
kore_connection_start_idletimer(c);
return (KORE_RESULT_OK);
default:
kore_debug("SSL_accept(): %s", ssl_errno_s);
if (c->flags & CONN_LOG_TLS_FAILURE) {
kore_log(LOG_NOTICE,
"SSL_accept: %s", ssl_errno_s);
}
return (KORE_RESULT_ERROR);
}
}
#if defined(KORE_USE_ACME)
if (c->proto == CONN_PROTO_ACME_ALPN) {
kore_log(LOG_INFO, "disconnecting acme client");
kore_connection_disconnect(c);
return (KORE_RESULT_OK);
}
#endif
if (SSL_get_verify_mode(c->ssl) & SSL_VERIFY_PEER) {
c->cert = SSL_get_peer_certificate(c->ssl);
if (c->cert == NULL) {
kore_log(LOG_NOTICE, "no peer certificate");
return (KORE_RESULT_ERROR);
}
} else {
c->cert = NULL;
}
if (c->owner != NULL) {
listener = (struct listener *)c->owner;
@ -383,16 +315,7 @@ kore_connection_remove(struct connection *c)
kore_debug("kore_connection_remove(%p)", c);
if (c->ssl != NULL) {
SSL_shutdown(c->ssl);
SSL_free(c->ssl);
}
if (c->cert != NULL)
X509_free(c->cert);
if (c->tls_sni != NULL)
kore_free(c->tls_sni);
kore_tls_connection_cleanup(c);
close(c->fd);

View File

@ -17,13 +17,6 @@
#include <sys/param.h>
#include <sys/types.h>
#include <openssl/x509.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <poll.h>
#include <fnmatch.h>
#include "kore.h"
@ -37,35 +30,9 @@
#endif
#define KORE_DOMAIN_CACHE 16
#define SSL_SESSION_ID "kore_ssl_sessionid"
struct kore_domain *primary_dom = NULL;
static u_int8_t keymgr_buf[2048];
static size_t keymgr_buflen = 0;
static int keymgr_response = 0;
DH *tls_dhparam = NULL;
int tls_version = KORE_TLS_VERSION_BOTH;
static int domain_x509_verify(int, X509_STORE_CTX *);
static X509 *domain_load_certificate_chain(SSL_CTX *, const void *, size_t);
static void keymgr_init(void);
static void keymgr_await_data(void);
static void keymgr_msg_response(struct kore_msg *, const void *);
static int keymgr_rsa_init(RSA *);
static int keymgr_rsa_finish(RSA *);
static int keymgr_rsa_privenc(int, const unsigned char *,
unsigned char *, RSA *, int);
static ECDSA_SIG *keymgr_ecdsa_sign(const unsigned char *, int,
const BIGNUM *, const BIGNUM *, EC_KEY *);
static RSA_METHOD *keymgr_rsa_meth = NULL;
static EC_KEY_METHOD *keymgr_ec_meth = NULL;
static u_int16_t domain_id = 0;
struct kore_domain *primary_dom = NULL;
static struct kore_domain *cached[KORE_DOMAIN_CACHE];
void
@ -75,45 +42,11 @@ kore_domain_init(void)
for (i = 0; i < KORE_DOMAIN_CACHE; i++)
cached[i] = NULL;
if (keymgr_rsa_meth == NULL) {
if ((keymgr_rsa_meth = RSA_meth_new("kore RSA keymgr method",
RSA_METHOD_FLAG_NO_CHECK)) == NULL)
fatal("failed to allocate RSA method");
}
RSA_meth_set_init(keymgr_rsa_meth, keymgr_rsa_init);
RSA_meth_set_finish(keymgr_rsa_meth, keymgr_rsa_finish);
RSA_meth_set_priv_enc(keymgr_rsa_meth, keymgr_rsa_privenc);
if (keymgr_ec_meth == NULL) {
if ((keymgr_ec_meth = EC_KEY_METHOD_new(NULL)) == NULL)
fatal("failed to allocate EC KEY method");
}
EC_KEY_METHOD_set_sign(keymgr_ec_meth, NULL, NULL, keymgr_ecdsa_sign);
#if !defined(TLS1_3_VERSION)
if (!kore_quiet) {
kore_log(LOG_NOTICE,
"%s has no TLS 1.3 - will only use TLS 1.2",
OPENSSL_VERSION_TEXT);
}
#endif
}
void
kore_domain_cleanup(void)
{
if (keymgr_rsa_meth != NULL) {
RSA_meth_free(keymgr_rsa_meth);
keymgr_rsa_meth = NULL;
}
if (keymgr_ec_meth != NULL) {
EC_KEY_METHOD_free(keymgr_ec_meth);
keymgr_ec_meth = NULL;
}
}
struct kore_domain *
@ -125,9 +58,10 @@ kore_domain_new(const char *domain)
dom = kore_calloc(1, sizeof(*dom));
dom->id = domain_id++;
dom->accesslog = -1;
dom->accesslog = -1;
dom->x509_verify_depth = 1;
dom->domain = kore_strdup(domain);
#if !defined(KORE_NO_HTTP)
@ -188,8 +122,7 @@ kore_domain_free(struct kore_domain *dom)
if (dom->domain != NULL)
kore_free(dom->domain);
if (dom->ssl_ctx != NULL)
SSL_CTX_free(dom->ssl_ctx);
kore_tls_domain_cleanup(dom);
kore_free(dom->cafile);
kore_free(dom->certkey);
@ -213,216 +146,6 @@ kore_domain_free(struct kore_domain *dom)
kore_free(dom);
}
void
kore_domain_tlsinit(struct kore_domain *dom, int type,
const void *data, size_t datalen)
{
const u_int8_t *ptr;
RSA *rsa;
X509 *x509;
EVP_PKEY *pkey;
STACK_OF(X509_NAME) *certs;
EC_KEY *eckey;
const SSL_METHOD *method;
kore_debug("kore_domain_tlsinit(%s)", dom->domain);
if (dom->ssl_ctx != NULL)
SSL_CTX_free(dom->ssl_ctx);
if ((method = TLS_method()) == NULL)
fatalx("TLS_method(): %s", ssl_errno_s);
if ((dom->ssl_ctx = SSL_CTX_new(method)) == NULL)
fatalx("SSL_ctx_new(): %s", ssl_errno_s);
if (!SSL_CTX_set_min_proto_version(dom->ssl_ctx, TLS1_2_VERSION))
fatalx("SSL_CTX_set_min_proto_version: %s", ssl_errno_s);
#if defined(TLS1_3_VERSION)
if (!SSL_CTX_set_max_proto_version(dom->ssl_ctx, TLS1_3_VERSION))
fatalx("SSL_CTX_set_max_proto_version: %s", ssl_errno_s);
#else
if (!SSL_CTX_set_max_proto_version(dom->ssl_ctx, TLS1_2_VERSION))
fatalx("SSL_CTX_set_min_proto_version: %s", ssl_errno_s);
#endif
switch (tls_version) {
case KORE_TLS_VERSION_1_3:
#if defined(TLS1_3_VERSION)
if (!SSL_CTX_set_min_proto_version(dom->ssl_ctx,
TLS1_3_VERSION)) {
fatalx("SSL_CTX_set_min_proto_version: %s",
ssl_errno_s);
}
break;
#endif
case KORE_TLS_VERSION_1_2:
if (!SSL_CTX_set_max_proto_version(dom->ssl_ctx,
TLS1_2_VERSION)) {
fatalx("SSL_CTX_set_min_proto_version: %s",
ssl_errno_s);
}
break;
case KORE_TLS_VERSION_BOTH:
break;
default:
fatalx("unknown tls_version: %d", tls_version);
return;
}
switch (type) {
case KORE_PEM_CERT_CHAIN:
x509 = domain_load_certificate_chain(dom->ssl_ctx,
data, datalen);
break;
case KORE_DER_CERT_DATA:
ptr = data;
if ((x509 = d2i_X509(NULL, &ptr, datalen)) == NULL)
fatalx("d2i_X509: %s", ssl_errno_s);
if (SSL_CTX_use_certificate(dom->ssl_ctx, x509) == 0)
fatalx("SSL_CTX_use_certificate: %s", ssl_errno_s);
break;
default:
fatalx("%s: unknown type %d", __func__, type);
}
if (x509 == NULL) {
kore_log(LOG_NOTICE, "failed to load certificate for '%s': %s",
dom->domain, ssl_errno_s);
SSL_CTX_free(dom->ssl_ctx);
dom->ssl_ctx = NULL;
return;
}
if ((pkey = X509_get_pubkey(x509)) == NULL)
fatalx("certificate has no public key");
switch (EVP_PKEY_id(pkey)) {
case EVP_PKEY_RSA:
if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL)
fatalx("no RSA public key present");
RSA_set_app_data(rsa, dom);
RSA_set_method(rsa, keymgr_rsa_meth);
break;
case EVP_PKEY_EC:
if ((eckey = EVP_PKEY_get1_EC_KEY(pkey)) == NULL)
fatalx("no EC public key present");
EC_KEY_set_ex_data(eckey, 0, dom);
EC_KEY_set_method(eckey, keymgr_ec_meth);
break;
default:
fatalx("unknown public key in certificate");
}
if (!SSL_CTX_use_PrivateKey(dom->ssl_ctx, pkey))
fatalx("SSL_CTX_use_PrivateKey(): %s", ssl_errno_s);
if (!SSL_CTX_check_private_key(dom->ssl_ctx)) {
fatalx("Public/Private key for %s do not match (%s)",
dom->domain, ssl_errno_s);
}
if (tls_dhparam == NULL)
fatal("no DH parameters specified");
SSL_CTX_set_tmp_dh(dom->ssl_ctx, tls_dhparam);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_DH_USE);
if (!SSL_CTX_set_ecdh_auto(dom->ssl_ctx, 1))
fatalx("SSL_CTX_set_ecdh_auto: %s", ssl_errno_s);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_SINGLE_ECDH_USE);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_COMPRESSION);
if (dom->cafile != NULL) {
if ((certs = SSL_load_client_CA_file(dom->cafile)) == NULL) {
fatalx("SSL_load_client_CA_file(%s): %s",
dom->cafile, ssl_errno_s);
}
SSL_CTX_load_verify_locations(dom->ssl_ctx, dom->cafile, NULL);
SSL_CTX_set_verify_depth(dom->ssl_ctx, dom->x509_verify_depth);
SSL_CTX_set_client_CA_list(dom->ssl_ctx, certs);
SSL_CTX_set_verify(dom->ssl_ctx, SSL_VERIFY_PEER |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, domain_x509_verify);
}
SSL_CTX_set_session_id_context(dom->ssl_ctx,
(unsigned char *)SSL_SESSION_ID, strlen(SSL_SESSION_ID));
SSL_CTX_set_mode(dom->ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
if (tls_version == KORE_TLS_VERSION_BOTH) {
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_SSLv2);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_SSLv3);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_TLSv1);
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_NO_TLSv1_1);
}
SSL_CTX_set_options(dom->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
SSL_CTX_set_cipher_list(dom->ssl_ctx, kore_tls_cipher_list);
SSL_CTX_set_info_callback(dom->ssl_ctx, kore_tls_info_callback);
SSL_CTX_set_tlsext_servername_callback(dom->ssl_ctx, kore_tls_sni_cb);
#if defined(KORE_USE_ACME)
SSL_CTX_set_alpn_select_cb(dom->ssl_ctx, kore_acme_tls_alpn, dom);
#endif
X509_free(x509);
}
void
kore_domain_crl_add(struct kore_domain *dom, const void *pem, size_t pemlen)
{
int err;
BIO *in;
X509_CRL *crl;
X509_STORE *store;
ERR_clear_error();
in = BIO_new_mem_buf(pem, pemlen);
if ((store = SSL_CTX_get_cert_store(dom->ssl_ctx)) == NULL) {
BIO_free(in);
kore_log(LOG_ERR, "SSL_CTX_get_cert_store(): %s", ssl_errno_s);
return;
}
for (;;) {
crl = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
if (crl == NULL) {
err = ERR_GET_REASON(ERR_peek_last_error());
if (err == PEM_R_NO_START_LINE) {
ERR_clear_error();
break;
}
kore_log(LOG_WARNING, "failed to read CRL %s: %s",
dom->crlfile, ssl_errno_s);
continue;
}
if (!X509_STORE_add_crl(store, crl)) {
err = ERR_GET_REASON(ERR_peek_last_error());
if (err == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
X509_CRL_free(crl);
continue;
}
kore_log(LOG_WARNING, "failed to add CRL %s: %s",
dom->crlfile, ssl_errno_s);
X509_CRL_free(crl);
continue;
}
}
BIO_free(in);
X509_STORE_set_flags(store,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
void
kore_domain_callback(void (*cb)(struct kore_domain *))
{
@ -495,308 +218,3 @@ kore_domain_closelogs(void)
}
}
}
void
kore_domain_keymgr_init(void)
{
keymgr_init();
kore_msg_register(KORE_MSG_KEYMGR_RESP, keymgr_msg_response);
}
static void
keymgr_init(void)
{
const RSA_METHOD *meth;
if ((meth = RSA_get_default_method()) == NULL)
fatal("failed to obtain RSA method");
RSA_meth_set_pub_enc(keymgr_rsa_meth, RSA_meth_get_pub_enc(meth));
RSA_meth_set_pub_dec(keymgr_rsa_meth, RSA_meth_get_pub_dec(meth));
RSA_meth_set_bn_mod_exp(keymgr_rsa_meth, RSA_meth_get_bn_mod_exp(meth));
}
static int
keymgr_rsa_init(RSA *rsa)
{
if (rsa != NULL) {
RSA_set_flags(rsa, RSA_flags(rsa) |
RSA_FLAG_EXT_PKEY | RSA_METHOD_FLAG_NO_CHECK);
return (1);
}
return (0);
}
static int
keymgr_rsa_privenc(int flen, const unsigned char *from, unsigned char *to,
RSA *rsa, int padding)
{
int ret;
size_t len;
struct kore_keyreq *req;
struct kore_domain *dom;
len = sizeof(*req) + flen;
if (len > sizeof(keymgr_buf))
fatal("keymgr_buf too small");
if ((dom = RSA_get_app_data(rsa)) == NULL)
fatal("RSA key has no domain attached");
memset(keymgr_buf, 0, sizeof(keymgr_buf));
req = (struct kore_keyreq *)keymgr_buf;
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
sizeof(req->domain))
fatal("%s: domain truncated", __func__);
req->data_len = flen;
req->padding = padding;
memcpy(&req->data[0], from, req->data_len);
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
keymgr_await_data();
ret = -1;
if (keymgr_response) {
if (keymgr_buflen < INT_MAX &&
(int)keymgr_buflen == RSA_size(rsa)) {
ret = RSA_size(rsa);
memcpy(to, keymgr_buf, RSA_size(rsa));
}
}
keymgr_buflen = 0;
keymgr_response = 0;
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
return (ret);
}
static int
keymgr_rsa_finish(RSA *rsa)
{
return (1);
}
static ECDSA_SIG *
keymgr_ecdsa_sign(const unsigned char *dgst, int dgst_len,
const BIGNUM *in_kinv, const BIGNUM *in_r, EC_KEY *eckey)
{
size_t len;
ECDSA_SIG *sig;
const u_int8_t *ptr;
struct kore_domain *dom;
struct kore_keyreq *req;
if (in_kinv != NULL || in_r != NULL)
return (NULL);
len = sizeof(*req) + dgst_len;
if (len > sizeof(keymgr_buf))
fatal("keymgr_buf too small");
if ((dom = EC_KEY_get_ex_data(eckey, 0)) == NULL)
fatal("EC_KEY has no domain");
memset(keymgr_buf, 0, sizeof(keymgr_buf));
req = (struct kore_keyreq *)keymgr_buf;
if (kore_strlcpy(req->domain, dom->domain, sizeof(req->domain)) >=
sizeof(req->domain))
fatal("%s: domain truncated", __func__);
req->data_len = dgst_len;
memcpy(&req->data[0], dgst, req->data_len);
kore_msg_send(KORE_WORKER_KEYMGR, KORE_MSG_KEYMGR_REQ, keymgr_buf, len);
keymgr_await_data();
if (keymgr_response) {
ptr = keymgr_buf;
sig = d2i_ECDSA_SIG(NULL, &ptr, keymgr_buflen);
} else {
sig = NULL;
}
keymgr_buflen = 0;
keymgr_response = 0;
kore_platform_event_all(worker->msg[1]->fd, worker->msg[1]);
return (sig);
}
static void
keymgr_await_data(void)
{
int ret;
struct pollfd pfd[1];
u_int64_t start, cur;
#if !defined(KORE_NO_HTTP)
int process_requests;
#endif
/*
* We need to wait until the keymgr responds to us, so keep doing
* net_recv_flush() until our callback for KORE_MSG_KEYMGR_RESP
* tells us that we have obtained the response.
*
* This means other internal messages can still be delivered by
* this worker process to the appropriate callbacks but we do not
* drop out until we've either received an answer from the keymgr
* or until the timeout has been reached (1 second currently).
*
* If we end up waiting for the keymgr process we will call
* http_process (if not built with NOHTTP=1) to further existing
* requests so those do not block too much.
*
* This means that all incoming data will stop being processed
* while existing requests will get processed until we return
* from this call.
*/
start = kore_time_ms();
kore_platform_disable_read(worker->msg[1]->fd);
keymgr_response = 0;
memset(keymgr_buf, 0, sizeof(keymgr_buf));
#if !defined(KORE_NO_HTTP)
process_requests = 0;
#endif
for (;;) {
#if !defined(KORE_NO_HTTP)
if (process_requests) {
http_process();
process_requests = 0;
}
#endif
pfd[0].fd = worker->msg[1]->fd;
pfd[0].events = POLLIN;
pfd[0].revents = 0;
ret = poll(pfd, 1, 100);
if (ret == -1) {
if (errno == EINTR)
continue;
fatal("poll: %s", errno_s);
}
cur = kore_time_ms();
if ((cur - start) > 1000)
break;
if (ret == 0) {
#if !defined(KORE_NO_HTTP)
/* No activity on channel, process HTTP requests. */
process_requests = 1;
#endif
continue;
}
if (pfd[0].revents & (POLLERR | POLLHUP))
break;
if (!(pfd[0].revents & POLLIN))
break;
worker->msg[1]->evt.flags |= KORE_EVENT_READ;
if (!net_recv_flush(worker->msg[1]))
break;
if (keymgr_response)
break;
#if !defined(KORE_NO_HTTP)
/* If we've spent 100ms already, process HTTP requests. */
if ((cur - start) > 100) {
process_requests = 1;
}
#endif
}
}
static void
keymgr_msg_response(struct kore_msg *msg, const void *data)
{
keymgr_response = 1;
keymgr_buflen = msg->length;
if (keymgr_buflen > sizeof(keymgr_buf))
return;
memcpy(keymgr_buf, data, keymgr_buflen);
}
static int
domain_x509_verify(int ok, X509_STORE_CTX *ctx)
{
X509 *cert;
const char *text;
int error, depth;
error = X509_STORE_CTX_get_error(ctx);
cert = X509_STORE_CTX_get_current_cert(ctx);
if (ok == 0 && cert != NULL) {
text = X509_verify_cert_error_string(error);
depth = X509_STORE_CTX_get_error_depth(ctx);
kore_log(LOG_WARNING, "X509 verification error depth:%d - %s",
depth, text);
/* Continue on CRL validity errors. */
switch (error) {
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
case X509_V_ERR_UNABLE_TO_GET_CRL:
ok = 1;
break;
}
}
return (ok);
}
/*
* What follows is basically a reimplementation of
* SSL_CTX_use_certificate_chain_file() from OpenSSL but with our
* BIO set to the pem data that we received.
*/
static X509 *
domain_load_certificate_chain(SSL_CTX *ctx, const void *data, size_t len)
{
unsigned long err;
BIO *in;
X509 *x, *ca;
ERR_clear_error();
in = BIO_new_mem_buf(data, len);
if ((x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL)) == NULL)
return (NULL);
/* refcount for x509 will go up one. */
if (SSL_CTX_use_certificate(ctx, x) == 0)
return (NULL);
SSL_CTX_clear_chain_certs(ctx);
ERR_clear_error();
while ((ca = PEM_read_bio_X509(in, NULL, NULL, NULL)) != NULL) {
/* ca its reference count won't be increased. */
if (SSL_CTX_add0_chain_cert(ctx, ca) == 0)
return (NULL);
}
err = ERR_peek_last_error();
if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
ERR_GET_REASON(err) != PEM_R_NO_START_LINE)
return (NULL);
BIO_free(in);
return (x);
}

View File

@ -976,7 +976,7 @@ http_header_recv(struct netbuf *nb)
req->http_body = kore_buf_alloc(req->content_length);
}
SHA256_Init(&req->hashctx);
SHA256Init(&req->hashctx);
c->http_timeout = http_body_timeout * 1000;
if (!http_body_update(req, end_headers, nb->s_off - len)) {
@ -2349,7 +2349,7 @@ http_body_update(struct http_request *req, const void *data, size_t len)
ssize_t ret;
u_int64_t bytes_left;
SHA256_Update(&req->hashctx, data, len);
SHA256Update(&req->hashctx, data, len);
if (req->http_body_fd != -1) {
ret = write(req->http_body_fd, data, len);
@ -2382,7 +2382,7 @@ http_body_update(struct http_request *req, const void *data, size_t len)
HTTP_STATUS_INTERNAL_ERROR);
return (KORE_RESULT_ERROR);
}
SHA256_Final(req->http_body_digest, &req->hashctx);
SHA256Final(req->http_body_digest, &req->hashctx);
} else {
bytes_left = req->content_length;
net_recv_reset(req->owner,

View File

@ -40,9 +40,11 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
@ -166,7 +168,7 @@ struct key {
TAILQ_ENTRY(key) list;
};
char *rand_file = NULL;
char *kore_rand_file = NULL;
static TAILQ_HEAD(, key) keys;
static int initialized = 0;
@ -251,9 +253,6 @@ static void keymgr_rsa_encrypt(struct kore_msg *, const void *,
static void keymgr_ecdsa_sign(struct kore_msg *, const void *,
struct key *);
struct kore_privsep keymgr_privsep;
int keymgr_active = 0;
#if defined(__OpenBSD__)
#if defined(KORE_USE_ACME)
static const char *keymgr_pledges = "stdio rpath wpath cpath";
@ -268,8 +267,8 @@ kore_keymgr_run(void)
int quit;
u_int64_t now, netwait, last_seed;
if (keymgr_active == 0)
fatalx("%s: called with keymgr_active == 0", __func__);
if (kore_keymgr_active == 0)
fatalx("%s: called with kore_keymgr_active == 0", __func__);
quit = 0;
@ -297,7 +296,7 @@ kore_keymgr_run(void)
#endif
kore_worker_privsep();
if (rand_file != NULL) {
if (kore_rand_file != NULL) {
keymgr_load_randfile();
keymgr_save_randfile();
} else if (!kore_quiet) {
@ -463,30 +462,30 @@ keymgr_load_randfile(void)
size_t total;
u_int8_t buf[RAND_FILE_SIZE];
if (rand_file == NULL)
if (kore_rand_file == NULL)
return;
if ((fd = open(rand_file, O_RDONLY)) == -1)
fatalx("open(%s): %s", rand_file, errno_s);
if ((fd = open(kore_rand_file, O_RDONLY)) == -1)
fatalx("open(%s): %s", kore_rand_file, errno_s);
if (fstat(fd, &st) == -1)
fatalx("stat(%s): %s", rand_file, errno_s);
fatalx("stat(%s): %s", kore_rand_file, errno_s);
if (!S_ISREG(st.st_mode))
fatalx("%s is not a file", rand_file);
fatalx("%s is not a file", kore_rand_file);
if (st.st_size != RAND_FILE_SIZE)
fatalx("%s has an invalid size", rand_file);
fatalx("%s has an invalid size", kore_rand_file);
total = 0;
while (total != RAND_FILE_SIZE) {
ret = read(fd, buf, sizeof(buf));
if (ret == 0)
fatalx("EOF on %s", rand_file);
fatalx("EOF on %s", kore_rand_file);
if (ret == -1) {
if (errno == EINTR)
continue;
fatalx("read(%s): %s", rand_file, errno_s);
fatalx("read(%s): %s", kore_rand_file, errno_s);
}
total += (size_t)ret;
@ -495,9 +494,9 @@ keymgr_load_randfile(void)
}
(void)close(fd);
if (unlink(rand_file) == -1) {
if (unlink(kore_rand_file) == -1) {
kore_log(LOG_WARNING, "failed to unlink %s: %s",
rand_file, errno_s);
kore_rand_file, errno_s);
}
}
@ -509,7 +508,7 @@ keymgr_save_randfile(void)
ssize_t ret;
u_int8_t buf[RAND_FILE_SIZE];
if (rand_file == NULL)
if (kore_rand_file == NULL)
return;
if (stat(RAND_TMP_FILE, &st) != -1) {
@ -541,10 +540,10 @@ keymgr_save_randfile(void)
if (close(fd) == -1)
kore_log(LOG_WARNING, "close(%s): %s", RAND_TMP_FILE, errno_s);
if (rename(RAND_TMP_FILE, rand_file) == -1) {
if (rename(RAND_TMP_FILE, kore_rand_file) == -1) {
kore_log(LOG_WARNING, "rename(%s, %s): %s",
RAND_TMP_FILE, rand_file, errno_s);
(void)unlink(rand_file);
RAND_TMP_FILE, kore_rand_file, errno_s);
(void)unlink(kore_rand_file);
(void)unlink(RAND_TMP_FILE);
}
@ -589,7 +588,7 @@ keymgr_load_privatekey(const char *path)
/* Caller should check if pkey was loaded. */
if (path)
key->pkey = kore_rsakey_load(path);
key->pkey = kore_tls_rsakey_load(path);
return (key);
}
@ -787,7 +786,7 @@ keymgr_acme_init(void)
if (key->pkey == NULL) {
kore_log(LOG_INFO, "generating new ACME account key");
key->pkey = kore_rsakey_generate(KORE_ACME_ACCOUNT_KEY);
key->pkey = kore_tls_rsakey_generate(KORE_ACME_ACCOUNT_KEY);
needsreg = 1;
} else {
kore_log(LOG_INFO, "loaded existing ACME account key");
@ -839,7 +838,7 @@ keymgr_acme_domainkey(struct kore_domain *dom, struct key *key)
}
*p = '/';
key->pkey = kore_rsakey_generate(dom->certkey);
key->pkey = kore_tls_rsakey_generate(dom->certkey);
}
static void

View File

@ -67,7 +67,6 @@ int kore_foreground = 0;
char *kore_progname = NULL;
u_int32_t kore_socket_backlog = 5000;
char *kore_pidfile = KORE_PIDFILE_DEFAULT;
char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST;
struct kore_privsep worker_privsep;
@ -80,7 +79,6 @@ static void version(void);
static void kore_write_kore_pid(void);
static void kore_proctitle_setup(void);
static void kore_server_sslstart(void);
static void kore_server_shutdown(void);
static void kore_server_start(int, char *[]);
static void kore_call_parent_configure(int, char **);
@ -150,6 +148,8 @@ version(void)
#if defined(KORE_USE_ACME)
printf("acme ");
#endif
if (!kore_tls_supported())
printf("notls ");
printf("\n");
exit(0);
}
@ -223,7 +223,7 @@ main(int argc, char *argv[])
#endif
kore_domain_init();
kore_module_init();
kore_server_sslstart();
kore_tls_init();
#if !defined(KORE_SINGLE_BINARY) && !defined(KORE_USE_PYTHON)
if (config_file == NULL)
@ -345,74 +345,6 @@ kore_default_getopt(int argc, char **argv)
}
}
int
kore_tls_sni_cb(SSL *ssl, int *ad, void *arg)
{
struct connection *c;
struct kore_domain *dom;
const char *sname;
if ((c = SSL_get_ex_data(ssl, 0)) == NULL)
fatal("no connection data in %s", __func__);
sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
kore_debug("kore_tls_sni_cb(): received host %s", sname);
if (sname != NULL)
c->tls_sni = kore_strdup(sname);
if (sname != NULL &&
(dom = kore_domain_lookup(c->owner->server, sname)) != NULL) {
if (dom->ssl_ctx == NULL) {
kore_log(LOG_NOTICE,
"TLS configuration for %s not complete",
dom->domain);
return (SSL_TLSEXT_ERR_NOACK);
}
kore_debug("kore_ssl_sni_cb(): Using %s CTX", sname);
SSL_set_SSL_CTX(ssl, dom->ssl_ctx);
if (dom->cafile != NULL) {
SSL_set_verify(ssl, SSL_VERIFY_PEER |
SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
c->flags |= CONN_LOG_TLS_FAILURE;
} else {
SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL);
}
#if defined(KORE_USE_ACME)
/*
* If ALPN callback was called before SNI was parsed we
* must make sure we swap to the correct certificate now.
*/
if (c->flags & CONN_TLS_ALPN_ACME_SEEN)
kore_acme_tls_challenge_use_cert(ssl, dom);
c->flags |= CONN_TLS_SNI_SEEN;
#endif
return (SSL_TLSEXT_ERR_OK);
}
return (SSL_TLSEXT_ERR_NOACK);
}
void
kore_tls_info_callback(const SSL *ssl, int flags, int ret)
{
struct connection *c;
if (flags & SSL_CB_HANDSHAKE_START) {
if ((c = SSL_get_app_data(ssl)) == NULL)
fatal("no SSL_get_app_data");
#if defined(TLS1_3_VERSION)
if (SSL_version(ssl) != TLS1_3_VERSION)
#endif
c->tls_reneg++;
}
}
int
kore_server_bind(struct kore_server *srv, const char *ip, const char *port,
const char *ccb)
@ -523,7 +455,11 @@ kore_server_create(const char *name)
srv = kore_calloc(1, sizeof(struct kore_server));
srv->name = kore_strdup(name);
srv->tls = 1;
if (kore_tls_supported())
srv->tls = 1;
else
srv->tls = 0;
TAILQ_INIT(&srv->domains);
LIST_INIT(&srv->listeners);
@ -843,13 +779,6 @@ kore_proctitle_setup(void)
proctitle_maxlen += strlen(kore_argv[i]) + 1;
}
static void
kore_server_sslstart(void)
{
SSL_library_init();
SSL_load_error_strings();
}
static void
kore_server_start(int argc, char *argv[])
{
@ -922,11 +851,15 @@ kore_server_start(int argc, char *argv[])
#endif
/* Check if keymgr will be active. */
LIST_FOREACH(srv, &kore_servers, list) {
if (srv->tls) {
keymgr_active = 1;
break;
if (kore_tls_supported()) {
LIST_FOREACH(srv, &kore_servers, list) {
if (srv->tls) {
kore_keymgr_active = 1;
break;
}
}
} else {
kore_keymgr_active = 0;
}
kore_platform_proctitle("[parent]");
@ -1033,6 +966,7 @@ kore_server_shutdown(void)
kore_platform_event_cleanup();
kore_connection_cleanup();
kore_domain_cleanup();
kore_tls_cleanup();
net_cleanup();
}

View File

@ -237,7 +237,7 @@ msg_recv_data(struct netbuf *nb)
dst = *(u_int16_t *)c->hdlr_extra;
if (destination == KORE_MSG_WORKER_ALL) {
if (keymgr_active && dst == 0)
if (kore_keymgr_active && dst == 0)
deliver = 0;
} else {
if (dst != destination)

View File

@ -340,104 +340,6 @@ net_remove_netbuf(struct connection *c, struct netbuf *nb)
kore_pool_put(&nb_pool, nb);
}
int
net_write_tls(struct connection *c, size_t len, size_t *written)
{
int r;
if (len > INT_MAX)
return (KORE_RESULT_ERROR);
ERR_clear_error();
r = SSL_write(c->ssl, (c->snb->buf + c->snb->s_off), len);
if (c->tls_reneg > 1)
return (KORE_RESULT_ERROR);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
c->evt.flags &= ~KORE_EVENT_WRITE;
c->snb->flags |= NETBUF_MUST_RESEND;
return (KORE_RESULT_OK);
case SSL_ERROR_SYSCALL:
switch (errno) {
case EINTR:
*written = 0;
return (KORE_RESULT_OK);
case EAGAIN:
c->evt.flags &= ~KORE_EVENT_WRITE;
c->snb->flags |= NETBUF_MUST_RESEND;
return (KORE_RESULT_OK);
default:
break;
}
/* FALLTHROUGH */
default:
kore_debug("SSL_write(): %s", ssl_errno_s);
if (c->flags & CONN_LOG_TLS_FAILURE) {
kore_log(LOG_NOTICE,
"SSL_write(): %s", ssl_errno_s);
}
return (KORE_RESULT_ERROR);
}
}
*written = (size_t)r;
return (KORE_RESULT_OK);
}
int
net_read_tls(struct connection *c, size_t *bytes)
{
int r;
ERR_clear_error();
r = SSL_read(c->ssl, (c->rnb->buf + c->rnb->s_off),
(c->rnb->b_len - c->rnb->s_off));
if (c->tls_reneg > 1)
return (KORE_RESULT_ERROR);
if (r <= 0) {
r = SSL_get_error(c->ssl, r);
switch (r) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
c->evt.flags &= ~KORE_EVENT_READ;
return (KORE_RESULT_OK);
case SSL_ERROR_ZERO_RETURN:
return (KORE_RESULT_ERROR);
case SSL_ERROR_SYSCALL:
switch (errno) {
case EINTR:
*bytes = 0;
return (KORE_RESULT_OK);
case EAGAIN:
c->evt.flags &= ~KORE_EVENT_READ;
c->snb->flags |= NETBUF_MUST_RESEND;
return (KORE_RESULT_OK);
default:
break;
}
/* FALLTHROUGH */
default:
kore_debug("SSL_read(): %s", ssl_errno_s);
if (c->flags & CONN_LOG_TLS_FAILURE) {
kore_log(LOG_NOTICE,
"SSL_read(): %s", ssl_errno_s);
}
return (KORE_RESULT_ERROR);
}
}
*bytes = (size_t)r;
return (KORE_RESULT_OK);
}
int
net_write(struct connection *c, size_t len, size_t *written)
{

171
src/sha1.c Normal file
View File

@ -0,0 +1,171 @@
/* $OpenBSD: sha1.c,v 1.27 2019/06/07 22:56:36 dtucker Exp $ */
/*
* SHA-1 in C
* By Steve Reid <steve@edmweb.com>
* 100% Public Domain
*
* Test Vectors (from FIPS PUB 180-1)
* "abc"
* A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
* 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
* A million repetitions of "a"
* 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#include <sys/types.h>
#include <string.h>
#include "sha1.h"
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/*
* blk0() and blk() perform the initial expand.
* I got the idea of expanding during the round function from SSLeay
*/
#if BYTE_ORDER == LITTLE_ENDIAN
# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
# define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/*
* (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
*/
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
typedef union {
u_int8_t c[64];
u_int32_t l[16];
} CHAR64LONG16;
/*
* Hash a single 512-bit block. This is the core of the algorithm.
*/
void
SHA1Transform(u_int32_t state[5], const u_int8_t buffer[SHA1_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, e;
u_int8_t workspace[SHA1_BLOCK_LENGTH];
CHAR64LONG16 *block = (CHAR64LONG16 *)workspace;
(void)memcpy(block, buffer, SHA1_BLOCK_LENGTH);
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/*
* SHA1Init - Initialize new context
*/
void
SHA1Init(SHA1_CTX *context)
{
/* SHA1 initialization constants */
context->count = 0;
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
}
/*
* Run your data through this.
*/
void
SHA1Update(SHA1_CTX *context, const u_int8_t *data, size_t len)
{
size_t i, j;
j = (size_t)((context->count >> 3) & 63);
context->count += ((u_int64_t)len << 3);
if ((j + len) > 63) {
(void)memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64)
SHA1Transform(context->state, &data[i]);
j = 0;
} else {
i = 0;
}
(void)memcpy(&context->buffer[j], &data[i], len - i);
}
/*
* Add padding and return the message digest.
*/
void
SHA1Pad(SHA1_CTX *context)
{
u_int8_t finalcount[8];
u_int i;
for (i = 0; i < 8; i++) {
finalcount[i] = (u_int8_t)((context->count >>
((7 - (i & 7)) * 8)) & 255); /* Endian independent */
}
SHA1Update(context, (u_int8_t *)"\200", 1);
while ((context->count & 504) != 448)
SHA1Update(context, (u_int8_t *)"\0", 1);
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
}
void
SHA1Final(u_int8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)
{
u_int i;
SHA1Pad(context);
for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
digest[i] = (u_int8_t)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
//explicit_bzero(context, sizeof(*context));
}

885
src/sha2.c Normal file
View File

@ -0,0 +1,885 @@
/* $OpenBSD: sha2.c,v 1.28 2019/07/23 12:35:22 dtucker Exp $ */
/*
* FILE: sha2.c
* AUTHOR: Aaron D. Gifford <me@aarongifford.com>
*
* Copyright (c) 2000-2001, Aaron D. Gifford
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
*/
/* OPENBSD ORIGINAL: lib/libc/hash/sha2.c */
#include <sys/types.h>
#include <string.h>
#if defined(__APPLE__)
#include <machine/endian.h>
#else
#include <endian.h>
#endif
#include "sha2.h"
/* no-op out, similar to DEF_WEAK but only needed here */
#define MAKE_CLONE(x, y) void __ssh_compat_make_clone_##x_##y(void)
/*
* UNROLLED TRANSFORM LOOP NOTE:
* You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
* loop version for the hash transform rounds (defined using macros
* later in this file). Either define on the command line, for example:
*
* cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
*
* or define below:
*
* #define SHA2_UNROLL_TRANSFORM
*
*/
#if defined(__amd64__) || defined(__i386__)
#define SHA2_UNROLL_TRANSFORM
#endif
/*** SHA-224/256/384/512 Machine Architecture Definitions *****************/
/*
* BYTE_ORDER NOTE:
*
* Please make sure that your system defines BYTE_ORDER. If your
* architecture is little-endian, make sure it also defines
* LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
* equivalent.
*
* If your system does not define the above, then you can do so by
* hand like this:
*
* #define LITTLE_ENDIAN 1234
* #define BIG_ENDIAN 4321
*
* And for little-endian machines, add:
*
* #define BYTE_ORDER LITTLE_ENDIAN
*
* Or for big-endian machines:
*
* #define BYTE_ORDER BIG_ENDIAN
*
* The FreeBSD machine this was written on defines BYTE_ORDER
* appropriately by including <sys/types.h> (which in turn includes
* <machine/endian.h> where the appropriate definitions are actually
* made).
*/
#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
#endif
/*** SHA-224/256/384/512 Various Length Definitions ***********************/
/* NOTE: Most of these are in sha2.h */
#define SHA224_SHORT_BLOCK_LENGTH (SHA224_BLOCK_LENGTH - 8)
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
/*** ENDIAN SPECIFIC COPY MACROS **************************************/
#define BE_8_TO_32(dst, cp) do { \
(dst) = (u_int32_t)(cp)[3] | ((u_int32_t)(cp)[2] << 8) | \
((u_int32_t)(cp)[1] << 16) | ((u_int32_t)(cp)[0] << 24); \
} while(0)
#define BE_8_TO_64(dst, cp) do { \
(dst) = (u_int64_t)(cp)[7] | ((u_int64_t)(cp)[6] << 8) | \
((u_int64_t)(cp)[5] << 16) | ((u_int64_t)(cp)[4] << 24) | \
((u_int64_t)(cp)[3] << 32) | ((u_int64_t)(cp)[2] << 40) | \
((u_int64_t)(cp)[1] << 48) | ((u_int64_t)(cp)[0] << 56); \
} while (0)
#define BE_64_TO_8(cp, src) do { \
(cp)[0] = (src) >> 56; \
(cp)[1] = (src) >> 48; \
(cp)[2] = (src) >> 40; \
(cp)[3] = (src) >> 32; \
(cp)[4] = (src) >> 24; \
(cp)[5] = (src) >> 16; \
(cp)[6] = (src) >> 8; \
(cp)[7] = (src); \
} while (0)
#define BE_32_TO_8(cp, src) do { \
(cp)[0] = (src) >> 24; \
(cp)[1] = (src) >> 16; \
(cp)[2] = (src) >> 8; \
(cp)[3] = (src); \
} while (0)
/*
* Macro for incrementally adding the unsigned 64-bit integer n to the
* unsigned 128-bit integer (represented using a two-element array of
* 64-bit words):
*/
#define ADDINC128(w,n) do { \
(w)[0] += (u_int64_t)(n); \
if ((w)[0] < (n)) { \
(w)[1]++; \
} \
} while (0)
/*** THE SIX LOGICAL FUNCTIONS ****************************************/
/*
* Bit shifting and rotation (used by the six SHA-XYZ logical functions:
*
* NOTE: The naming of R and S appears backwards here (R is a SHIFT and
* S is a ROTATION) because the SHA-224/256/384/512 description document
* (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
* same "backwards" definition.
*/
/* Shift-right (used in SHA-224, SHA-256, SHA-384, and SHA-512): */
#define R(b,x) ((x) >> (b))
/* 32-bit Rotate-right (used in SHA-224 and SHA-256): */
#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
/* Two of six logical functions used in SHA-224, SHA-256, SHA-384, and SHA-512: */
#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
/* Four of six logical functions used in SHA-224 and SHA-256: */
#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
/* Four of six logical functions used in SHA-384 and SHA-512: */
#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
/* Hash constant words K for SHA-224 and SHA-256: */
static const u_int32_t K256[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
};
/* Initial hash value H for SHA-256: */
static const u_int32_t sha256_initial_hash_value[8] = {
0x6a09e667UL,
0xbb67ae85UL,
0x3c6ef372UL,
0xa54ff53aUL,
0x510e527fUL,
0x9b05688cUL,
0x1f83d9abUL,
0x5be0cd19UL
};
/* Hash constant words K for SHA-384 and SHA-512: */
static const u_int64_t K512[80] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
};
/* Initial hash value H for SHA-512 */
static const u_int64_t sha512_initial_hash_value[8] = {
0x6a09e667f3bcc908ULL,
0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL,
0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL,
0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL,
0x5be0cd19137e2179ULL
};
/* Initial hash value H for SHA-384 */
static const u_int64_t sha384_initial_hash_value[8] = {
0xcbbb9d5dc1059ed8ULL,
0x629a292a367cd507ULL,
0x9159015a3070dd17ULL,
0x152fecd8f70e5939ULL,
0x67332667ffc00b31ULL,
0x8eb44a8768581511ULL,
0xdb0c2e0d64f98fa7ULL,
0x47b5481dbefa4fa4ULL
};
/*** SHA-256: *********************************************************/
void
SHA256Init(SHA2_CTX *context)
{
memcpy(context->state.st32, sha256_initial_hash_value,
sizeof(sha256_initial_hash_value));
memset(context->buffer, 0, sizeof(context->buffer));
context->bitcount[0] = 0;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-256 round macros: */
#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) do { \
BE_8_TO_32(W256[j], data); \
data += 4; \
T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + W256[j]; \
(d) += T1; \
(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \
j++; \
} while(0)
#define ROUND256(a,b,c,d,e,f,g,h) do { \
s0 = W256[(j+1)&0x0f]; \
s0 = sigma0_256(s0); \
s1 = W256[(j+14)&0x0f]; \
s1 = sigma1_256(s1); \
T1 = (h) + Sigma1_256((e)) + Ch((e), (f), (g)) + K256[j] + \
(W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
(d) += T1; \
(h) = T1 + Sigma0_256((a)) + Maj((a), (b), (c)); \
j++; \
} while(0)
void
SHA256Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, e, f, g, h, s0, s1;
u_int32_t T1, W256[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
j = 0;
do {
/* Rounds 0 to 15 (unrolled): */
ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
} while (j < 16);
/* Now for the remaining rounds up to 63: */
do {
ROUND256(a,b,c,d,e,f,g,h);
ROUND256(h,a,b,c,d,e,f,g);
ROUND256(g,h,a,b,c,d,e,f);
ROUND256(f,g,h,a,b,c,d,e);
ROUND256(e,f,g,h,a,b,c,d);
ROUND256(d,e,f,g,h,a,b,c);
ROUND256(c,d,e,f,g,h,a,b);
ROUND256(b,c,d,e,f,g,h,a);
} while (j < 64);
/* Compute the current intermediate hash value */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = 0;
}
#else /* SHA2_UNROLL_TRANSFORM */
void
SHA256Transform(u_int32_t state[8], const u_int8_t data[SHA256_BLOCK_LENGTH])
{
u_int32_t a, b, c, d, e, f, g, h, s0, s1;
u_int32_t T1, T2, W256[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
j = 0;
do {
BE_8_TO_32(W256[j], data);
data += 4;
/* Apply the SHA-256 compression function to update a..h */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 16);
do {
/* Part of the message block expansion: */
s0 = W256[(j+1)&0x0f];
s0 = sigma0_256(s0);
s1 = W256[(j+14)&0x0f];
s1 = sigma1_256(s1);
/* Apply the SHA-256 compression function to update a..h */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
(W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 64);
/* Compute the current intermediate hash value */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0;
}
#endif /* SHA2_UNROLL_TRANSFORM */
void
SHA256Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
{
u_int64_t freespace, usedspace;
/* Calling with no data is valid (we do nothing) */
if (len == 0)
return;
usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA256_BLOCK_LENGTH - usedspace;
if (len >= freespace) {
/* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace);
context->bitcount[0] += freespace << 3;
len -= freespace;
data += freespace;
SHA256Transform(context->state.st32, context->buffer);
} else {
/* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len);
context->bitcount[0] += (u_int64_t)len << 3;
/* Clean up: */
usedspace = freespace = 0;
return;
}
}
while (len >= SHA256_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
SHA256Transform(context->state.st32, data);
context->bitcount[0] += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH;
}
if (len > 0) {
/* There's left-overs, so save 'em */
memcpy(context->buffer, data, len);
context->bitcount[0] += len << 3;
}
/* Clean up: */
usedspace = freespace = 0;
}
void
SHA256Pad(SHA2_CTX *context)
{
unsigned int usedspace;
usedspace = (context->bitcount[0] >> 3) % SHA256_BLOCK_LENGTH;
if (usedspace > 0) {
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0,
SHA256_SHORT_BLOCK_LENGTH - usedspace);
} else {
if (usedspace < SHA256_BLOCK_LENGTH) {
memset(&context->buffer[usedspace], 0,
SHA256_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
SHA256Transform(context->state.st32, context->buffer);
/* Prepare for last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
}
} else {
/* Set-up for the last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
}
/* Store the length of input data (in bits) in big endian format: */
BE_64_TO_8(&context->buffer[SHA256_SHORT_BLOCK_LENGTH],
context->bitcount[0]);
/* Final transform: */
SHA256Transform(context->state.st32, context->buffer);
/* Clean up: */
usedspace = 0;
}
void
SHA256Final(u_int8_t digest[SHA256_DIGEST_LENGTH], SHA2_CTX *context)
{
SHA256Pad(context);
#if BYTE_ORDER == LITTLE_ENDIAN
int i;
/* Convert TO host byte order */
for (i = 0; i < 8; i++)
BE_32_TO_8(digest + i * 4, context->state.st32[i]);
#else
memcpy(digest, context->state.st32, SHA256_DIGEST_LENGTH);
#endif
//explicit_bzero(context, sizeof(*context));
}
/*** SHA-512: *********************************************************/
void
SHA512Init(SHA2_CTX *context)
{
memcpy(context->state.st64, sha512_initial_hash_value,
sizeof(sha512_initial_hash_value));
memset(context->buffer, 0, sizeof(context->buffer));
context->bitcount[0] = context->bitcount[1] = 0;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-512 round macros: */
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) do { \
BE_8_TO_64(W512[j], data); \
data += 8; \
T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + W512[j]; \
(d) += T1; \
(h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \
j++; \
} while(0)
#define ROUND512(a,b,c,d,e,f,g,h) do { \
s0 = W512[(j+1)&0x0f]; \
s0 = sigma0_512(s0); \
s1 = W512[(j+14)&0x0f]; \
s1 = sigma1_512(s1); \
T1 = (h) + Sigma1_512((e)) + Ch((e), (f), (g)) + K512[j] + \
(W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
(d) += T1; \
(h) = T1 + Sigma0_512((a)) + Maj((a), (b), (c)); \
j++; \
} while(0)
void
SHA512Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
{
u_int64_t a, b, c, d, e, f, g, h, s0, s1;
u_int64_t T1, W512[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
j = 0;
do {
/* Rounds 0 to 15 (unrolled): */
ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
} while (j < 16);
/* Now for the remaining rounds up to 79: */
do {
ROUND512(a,b,c,d,e,f,g,h);
ROUND512(h,a,b,c,d,e,f,g);
ROUND512(g,h,a,b,c,d,e,f);
ROUND512(f,g,h,a,b,c,d,e);
ROUND512(e,f,g,h,a,b,c,d);
ROUND512(d,e,f,g,h,a,b,c);
ROUND512(c,d,e,f,g,h,a,b);
ROUND512(b,c,d,e,f,g,h,a);
} while (j < 80);
/* Compute the current intermediate hash value */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = 0;
}
#else /* SHA2_UNROLL_TRANSFORM */
void
SHA512Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
{
u_int64_t a, b, c, d, e, f, g, h, s0, s1;
u_int64_t T1, T2, W512[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
f = state[5];
g = state[6];
h = state[7];
j = 0;
do {
BE_8_TO_64(W512[j], data);
data += 8;
/* Apply the SHA-512 compression function to update a..h */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
T2 = Sigma0_512(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 16);
do {
/* Part of the message block expansion: */
s0 = W512[(j+1)&0x0f];
s0 = sigma0_512(s0);
s1 = W512[(j+14)&0x0f];
s1 = sigma1_512(s1);
/* Apply the SHA-512 compression function to update a..h */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
(W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
T2 = Sigma0_512(a) + Maj(a, b, c);
h = g;
g = f;
f = e;
e = d + T1;
d = c;
c = b;
b = a;
a = T1 + T2;
j++;
} while (j < 80);
/* Compute the current intermediate hash value */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
state[5] += f;
state[6] += g;
state[7] += h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0;
}
#endif /* SHA2_UNROLL_TRANSFORM */
void
SHA512Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
{
size_t freespace, usedspace;
/* Calling with no data is valid (we do nothing) */
if (len == 0)
return;
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA512_BLOCK_LENGTH - usedspace;
if (len >= freespace) {
/* Fill the buffer completely and process it */
memcpy(&context->buffer[usedspace], data, freespace);
ADDINC128(context->bitcount, freespace << 3);
len -= freespace;
data += freespace;
SHA512Transform(context->state.st64, context->buffer);
} else {
/* The buffer is not yet full */
memcpy(&context->buffer[usedspace], data, len);
ADDINC128(context->bitcount, len << 3);
/* Clean up: */
usedspace = freespace = 0;
return;
}
}
while (len >= SHA512_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
SHA512Transform(context->state.st64, data);
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
len -= SHA512_BLOCK_LENGTH;
data += SHA512_BLOCK_LENGTH;
}
if (len > 0) {
/* There's left-overs, so save 'em */
memcpy(context->buffer, data, len);
ADDINC128(context->bitcount, len << 3);
}
/* Clean up: */
usedspace = freespace = 0;
}
void
SHA512Pad(SHA2_CTX *context)
{
unsigned int usedspace;
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
if (usedspace > 0) {
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0, SHA512_SHORT_BLOCK_LENGTH - usedspace);
} else {
if (usedspace < SHA512_BLOCK_LENGTH) {
memset(&context->buffer[usedspace], 0, SHA512_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
SHA512Transform(context->state.st64, context->buffer);
/* And set-up for the last transform: */
memset(context->buffer, 0, SHA512_BLOCK_LENGTH - 2);
}
} else {
/* Prepare for final transform: */
memset(context->buffer, 0, SHA512_SHORT_BLOCK_LENGTH);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
}
/* Store the length of input data (in bits) in big endian format: */
BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH],
context->bitcount[1]);
BE_64_TO_8(&context->buffer[SHA512_SHORT_BLOCK_LENGTH + 8],
context->bitcount[0]);
/* Final transform: */
SHA512Transform(context->state.st64, context->buffer);
/* Clean up: */
usedspace = 0;
}
void
SHA512Final(u_int8_t digest[SHA512_DIGEST_LENGTH], SHA2_CTX *context)
{
SHA512Pad(context);
#if BYTE_ORDER == LITTLE_ENDIAN
int i;
/* Convert TO host byte order */
for (i = 0; i < 8; i++)
BE_64_TO_8(digest + i * 8, context->state.st64[i]);
#else
memcpy(digest, context->state.st64, SHA512_DIGEST_LENGTH);
#endif
//explicit_bzero(context, sizeof(*context));
}
/*** SHA-384: *********************************************************/
void
SHA384Init(SHA2_CTX *context)
{
memcpy(context->state.st64, sha384_initial_hash_value,
sizeof(sha384_initial_hash_value));
memset(context->buffer, 0, sizeof(context->buffer));
context->bitcount[0] = context->bitcount[1] = 0;
}
MAKE_CLONE(SHA384Transform, SHA512Transform);
MAKE_CLONE(SHA384Update, SHA512Update);
MAKE_CLONE(SHA384Pad, SHA512Pad);
/* Equivalent of MAKE_CLONE (which is a no-op) for SHA384 funcs */
void
SHA384Transform(u_int64_t state[8], const u_int8_t data[SHA512_BLOCK_LENGTH])
{
SHA512Transform(state, data);
}
void
SHA384Update(SHA2_CTX *context, const u_int8_t *data, size_t len)
{
SHA512Update(context, data, len);
}
void
SHA384Pad(SHA2_CTX *context)
{
SHA512Pad(context);
}
void
SHA384Final(u_int8_t digest[SHA384_DIGEST_LENGTH], SHA2_CTX *context)
{
SHA384Pad(context);
#if BYTE_ORDER == LITTLE_ENDIAN
int i;
/* Convert TO host byte order */
for (i = 0; i < 6; i++)
BE_64_TO_8(digest + i * 8, context->state.st64[i]);
#else
memcpy(digest, context->state.st64, SHA384_DIGEST_LENGTH);
#endif
/* Zero out state data */
//explicit_bzero(context, sizeof(*context));
}

161
src/tls_none.c Normal file
View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2022 Joris Vink <joris@coders.se>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* An empty TLS backend that does nothing, useful if you do
* not require any TLS stuff in Kore.
*/
#include <sys/types.h>
#include "kore.h"
struct kore_privsep keymgr_privsep;
char *kore_rand_file = NULL;
int kore_keymgr_active = 0;
int
kore_tls_supported(void)
{
return (KORE_RESULT_ERROR);
}
void
kore_keymgr_cleanup(int final)
{
}
void
kore_tls_init(void)
{
kore_log(LOG_ERR, "No compiled in TLS backend");
}
void
kore_tls_cleanup(void)
{
}
void
kore_tls_dh_check(void)
{
}
void
kore_tls_keymgr_init(void)
{
}
void
kore_tls_connection_cleanup(struct connection *c)
{
}
void
kore_tls_domain_cleanup(struct kore_domain *dom)
{
}
void
kore_tls_seed(const void *data, size_t len)
{
}
void
kore_keymgr_run(void)
{
fatal("%s: not supported", __func__);
}
void
kore_tls_version_set(int version)
{
fatal("%s: not supported", __func__);
}
int
kore_tls_dh_load(const char *path)
{
fatal("%s: not supported", __func__);
}
int
kore_tls_ciphersuite_set(const char *list)
{
fatal("%s: not supported", __func__);
}
void
kore_tls_domain_setup(struct kore_domain *dom, int type,
const void *data, size_t datalen)
{
fatal("%s: not supported", __func__);
}
void
kore_tls_domain_crl(struct kore_domain *dom, const void *pem, size_t pemlen)
{
fatal("%s: not supported", __func__);
}
int
kore_tls_connection_accept(struct connection *c)
{
fatal("%s: not supported", __func__);
}
int
kore_tls_read(struct connection *c, size_t *bytes)
{
fatal("%s: not supported", __func__);
}
int
kore_tls_write(struct connection *c, size_t len, size_t *written)
{
fatal("%s: not supported", __func__);
}
void *
kore_tls_rsakey_load(const char *path)
{
fatal("%s: not supported", __func__);
}
void *
kore_tls_rsakey_generate(const char *path)
{
fatal("%s: not supported", __func__);
}
void *
kore_tls_x509_subject_name(struct connection *c)
{
fatal("%s: not supported", __func__);
}
void *
kore_tls_x509_issuer_name(struct connection *c)
{
fatal("%s: not supported", __func__);
}
int
kore_tls_x509name_foreach(void *name, int flags, void *udata,
int (*cb)(void *, int, int, const char *, const void *, size_t, int))
{
fatal("%s: not supported", __func__);
}

1156
src/tls_openssl.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -17,9 +17,6 @@
#include <sys/types.h>
#include <sys/time.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
@ -57,7 +54,6 @@ static int utils_base64_decode(const char *, u_int8_t **,
static int utils_x509name_tobuf(void *, int, int, const char *,
const void *, size_t, int);
static char b64_table[] = \
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@ -475,59 +471,6 @@ kore_read_line(FILE *fp, char *in, size_t len)
return (p);
}
EVP_PKEY *
kore_rsakey_load(const char *path)
{
FILE *fp;
EVP_PKEY *pkey;
if (access(path, R_OK) == -1)
return (NULL);
if ((fp = fopen(path, "r")) == NULL)
fatalx("%s(%s): %s", __func__, path, errno_s);
if ((pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL)
fatalx("PEM_read_PrivateKey: %s", ssl_errno_s);
fclose(fp);
return (pkey);
}
EVP_PKEY *
kore_rsakey_generate(const char *path)
{
FILE *fp;
EVP_PKEY_CTX *ctx;
EVP_PKEY *pkey;
if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL)
fatalx("EVP_PKEY_CTX_new_id: %s", ssl_errno_s);
if (EVP_PKEY_keygen_init(ctx) <= 0)
fatalx("EVP_PKEY_keygen_init: %s", ssl_errno_s);
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, KORE_RSAKEY_BITS) <= 0)
fatalx("EVP_PKEY_CTX_set_rsa_keygen_bits: %s", ssl_errno_s);
pkey = NULL;
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
fatalx("EVP_PKEY_keygen: %s", ssl_errno_s);
if (path != NULL) {
if ((fp = fopen(path, "w")) == NULL)
fatalx("fopen(%s): %s", path, errno_s);
if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL))
fatalx("PEM_write_PrivateKey: %s", ssl_errno_s);
fclose(fp);
}
return (pkey);
}
const char *
kore_worker_name(int id)
{
@ -552,14 +495,15 @@ int
kore_x509_issuer_name(struct connection *c, char **out, int flags)
{
struct kore_buf buf;
X509_NAME *name;
void *name;
if ((name = X509_get_issuer_name(c->cert)) == NULL)
if ((name = kore_tls_x509_issuer_name(c->cert)) == NULL)
return (KORE_RESULT_ERROR);
kore_buf_init(&buf, 1024);
if (!kore_x509name_foreach(name, flags, &buf, utils_x509name_tobuf)) {
if (!kore_tls_x509name_foreach(name, flags, &buf,
utils_x509name_tobuf)) {
kore_buf_cleanup(&buf);
return (KORE_RESULT_ERROR);
}
@ -576,14 +520,15 @@ int
kore_x509_subject_name(struct connection *c, char **out, int flags)
{
struct kore_buf buf;
X509_NAME *name;
void *name;
if ((name = X509_get_subject_name(c->cert)) == NULL)
if ((name = kore_tls_x509_subject_name(c)) == NULL)
return (KORE_RESULT_ERROR);
kore_buf_init(&buf, 1024);
if (!kore_x509name_foreach(name, flags, &buf, utils_x509name_tobuf)) {
if (!kore_tls_x509name_foreach(name, flags, &buf,
utils_x509name_tobuf)) {
kore_buf_cleanup(&buf);
return (KORE_RESULT_ERROR);
}
@ -596,58 +541,6 @@ kore_x509_subject_name(struct connection *c, char **out, int flags)
return (KORE_RESULT_OK);
}
int
kore_x509name_foreach(X509_NAME *name, int flags, void *udata,
int (*cb)(void *, int, int, const char *, const void *, size_t, int))
{
u_int8_t *data;
ASN1_STRING *astr;
X509_NAME_ENTRY *entry;
const char *field;
int islast, ret, idx, namelen, nid, len;
data = NULL;
ret = KORE_RESULT_ERROR;
if ((namelen = X509_NAME_entry_count(name)) == 0)
goto cleanup;
for (idx = 0; idx < namelen; idx++) {
if ((entry = X509_NAME_get_entry(name, idx)) == NULL)
goto cleanup;
nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry));
if ((field = OBJ_nid2sn(nid)) == NULL)
goto cleanup;
if ((astr = X509_NAME_ENTRY_get_data(entry)) == NULL)
goto cleanup;
data = NULL;
if ((len = ASN1_STRING_to_UTF8(&data, astr)) < 0)
goto cleanup;
if (idx != (namelen - 1))
islast = 0;
else
islast = 1;
if (!cb(udata, islast, nid, field, data, len, flags))
goto cleanup;
OPENSSL_free(data);
data = NULL;
}
ret = KORE_RESULT_OK;
cleanup:
if (data != NULL)
OPENSSL_free(data);
return (ret);
}
void
fatal(const char *fmt, ...)
{
@ -695,7 +588,7 @@ utils_x509name_tobuf(void *udata, int islast, int nid, const char *field,
struct kore_buf *buf = udata;
if (flags & KORE_X509_COMMON_NAME_ONLY) {
if (nid == NID_commonName)
if (nid == KORE_X509_NAME_COMMON_NAME)
kore_buf_append(buf, data, len);
} else {
kore_buf_appendf(buf, "%s=", field);

View File

@ -17,13 +17,12 @@
#include <sys/param.h>
#include <sys/types.h>
#include <openssl/sha.h>
#include <limits.h>
#include <string.h>
#include "kore.h"
#include "http.h"
#include "sha1.h"
#define WEBSOCKET_FRAME_HDR 2
#define WEBSOCKET_MASK_LEN 4
@ -53,11 +52,11 @@ void
kore_websocket_handshake(struct http_request *req, const char *onconnect,
const char *onmessage, const char *ondisconnect)
{
SHA_CTX sctx;
SHA1_CTX sctx;
struct kore_buf *buf;
char *base64;
const char *key, *version;
u_int8_t digest[SHA_DIGEST_LENGTH];
u_int8_t digest[SHA1_DIGEST_LENGTH];
if (!http_request_header(req, "sec-websocket-key", &key)) {
http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
@ -79,9 +78,9 @@ kore_websocket_handshake(struct http_request *req, const char *onconnect,
buf = kore_buf_alloc(128);
kore_buf_appendf(buf, "%s%s", key, WEBSOCKET_SERVER_RESPONSE);
(void)SHA1_Init(&sctx);
(void)SHA1_Update(&sctx, buf->data, buf->offset);
(void)SHA1_Final(digest, &sctx);
SHA1Init(&sctx);
SHA1Update(&sctx, buf->data, buf->offset);
SHA1Final(digest, &sctx);
kore_buf_free(buf);

View File

@ -23,8 +23,6 @@
#include <sys/resource.h>
#include <sys/socket.h>
#include <openssl/rand.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
@ -163,7 +161,7 @@ kore_worker_init(void)
return (KORE_RESULT_ERROR);
}
if (keymgr_active) {
if (kore_keymgr_active) {
#if defined(KORE_USE_ACME)
/* The ACME process is only started if we need it. */
if (acme_domains) {
@ -491,7 +489,7 @@ kore_worker_entry(struct kore_worker *kw)
#endif
kore_timer_init();
kore_fileref_init();
kore_domain_keymgr_init();
kore_tls_keymgr_init();
quit = 0;
had_lock = 0;
@ -501,7 +499,7 @@ kore_worker_entry(struct kore_worker *kw)
last_seed = 0;
if (keymgr_active) {
if (kore_keymgr_active) {
kore_msg_register(KORE_MSG_CRL, worker_keymgr_response);
kore_msg_register(KORE_MSG_ENTROPY_RESP, worker_entropy_recv);
kore_msg_register(KORE_MSG_CERTIFICATE, worker_keymgr_response);
@ -536,7 +534,8 @@ kore_worker_entry(struct kore_worker *kw)
for (;;) {
now = kore_time_ms();
if (keymgr_active && (now - last_seed) > KORE_RESEED_TIME) {
if (kore_keymgr_active &&
(now - last_seed) > KORE_RESEED_TIME) {
kore_msg_send(KORE_WORKER_KEYMGR,
KORE_MSG_ENTROPY_REQ, NULL, 0);
last_seed = now;
@ -636,6 +635,7 @@ kore_worker_entry(struct kore_worker *kw)
kore_platform_event_cleanup();
kore_connection_cleanup();
kore_domain_cleanup();
kore_tls_cleanup();
kore_module_cleanup();
#if !defined(KORE_NO_HTTP)
http_cleanup();
@ -1035,8 +1035,7 @@ worker_entropy_recv(struct kore_msg *msg, const void *data)
msg->length);
}
RAND_poll();
RAND_seed(data, msg->length);
kore_tls_seed(data, msg->length);
}
static void
@ -1052,16 +1051,16 @@ worker_keymgr_response(struct kore_msg *msg, const void *data)
switch (msg->id) {
case KORE_MSG_CERTIFICATE:
kore_domain_tlsinit(dom, KORE_PEM_CERT_CHAIN,
kore_tls_domain_setup(dom, KORE_PEM_CERT_CHAIN,
req->data, req->data_len);
break;
case KORE_MSG_CRL:
kore_domain_crl_add(dom, req->data, req->data_len);
kore_tls_domain_crl(dom, req->data, req->data_len);
break;
#if defined(KORE_USE_ACME)
case KORE_ACME_CHALLENGE_SET_CERT:
if (dom->ssl_ctx == NULL) {
kore_domain_tlsinit(dom, KORE_DER_CERT_DATA,
kore_tls_domain_setup(dom, KORE_DER_CERT_DATA,
req->data, req->data_len);
}