[Git][NTPsec/ntpsec][master] 2 commits: Update devel/TODO-NTS
Hal Murray
gitlab at mg.gitlab.com
Sat Mar 9 08:08:10 UTC 2019
Hal Murray pushed to branch master at NTPsec / ntpsec
Commits:
91338767 by Hal Murray at 2019-03-09T08:01:08Z
Update devel/TODO-NTS
- - - - -
f9860502 by Hal Murray at 2019-03-09T08:01:08Z
More NTS: Write cookie key to disk, timer for new key
It's in testing mode, rotating keys every hour.
- - - - -
10 changed files:
- devel/TODO-NTS
- include/ntpd.h
- include/nts.h
- ntpclients/ntpq.py
- ntpd/ntp_control.c
- ntpd/ntp_timer.c
- ntpd/nts.c
- ntpd/nts_cookie.c
- ntpd/nts_extens.c
- ntpd/nts_server.c
Changes:
=====================================
devel/TODO-NTS
=====================================
@@ -1,22 +1,26 @@
-Key rotation and save to disk
-
multithread msyslog
-? thread per instance on NTS-KE server
+Ratchet for new cookie key
documentation:
HOWTO on NTS
HOWTO on certificates
glossary: https://letsencrypt.org/docs/glossary/
--------
+Startup with bad time
-The current code has the NTS-KE and ntpd in the same package.
+? thread per instance on NTS-KE server
-There are opportunities beyond that. TBD.
+Password for certificate's private key and cookie keys file.
+ Need to get it it before daemon mode.
-------
+Save cookie to disk for restart without asking NTS-KE server
+
security level
client certificates
+
+Pool/cluster mode
+
=====================================
include/ntpd.h
=====================================
@@ -448,7 +448,6 @@ void nts_init(void); /* Before sandbox() */
void nts_init2(void); /* After sandbox() */
bool nts_probe(struct peer *peer);
bool nts_check(struct peer *peer);
-
-int nts_daily(struct ntscfg_t *);
+void nts_timer(void);
#endif /* GUARD_NTPD_H */
=====================================
include/nts.h
=====================================
@@ -8,6 +8,13 @@
#include <stdint.h>
#include <openssl/ssl.h>
+/* default file names */
+#define NTS_CERT_FILE "/etc/ntp/cert-chain.pem"
+#define NTS_KEY_FILE "/etc/ntp/key.pem"
+#define NTS_COOKIE_KEY_FILE "/var/lib/ntp/nts-keys"
+
+#define NTS_KE_PORT 123
+
#define NTS_KE_TIMEOUT 3
#define NTS_MAX_KEYLEN 64 /* used in cookies */
@@ -62,6 +69,7 @@ struct ntsconfig_t {
const char *tlsciphersuites;/* allowed TLS 1.3 ciphersuites */
const char *cert; /* server certificate key */
const char *key; /* server private key */
+ const char *KI; /* K/I for making cookies */
const char *ca; /* root cert dir/file */
};
@@ -142,6 +150,7 @@ extern struct ntsconfig_t ntsconfig;
bool nts_server_init(void);
bool nts_client_init(void);
bool nts_cookie_init(void);
+bool nts_cookie_init2(void); /* after sandbox */
void nts_log_ssl_error(void);
bool nts_load_ciphers(SSL_CTX *ctx);
@@ -201,14 +210,18 @@ uint16_t next_bytes(BufCtl* buf, uint8_t *data, int length);
-/* NTS-related system variables visible via ntpq -c nts */
+/* NTS-related statistics visible via ntpq -c nts */
extern uint64_t nts_client_send;
extern uint64_t nts_client_recv;
extern uint64_t nts_client_recv_bad;
extern uint64_t nts_server_send;
extern uint64_t nts_server_recv;
extern uint64_t nts_server_recv_bad;
-extern uint64_t nts_server_recv_bad;
+extern uint64_t nts_cookie_make;
+extern uint64_t nts_cookie_decode;
+extern uint64_t nts_cookie_decode_old;
+extern uint64_t nts_cookie_decode_too_old;
+extern uint64_t nts_cookie_decode_error;
extern uint64_t nts_ke_serves;
extern uint64_t nts_ke_serves_bad;
extern uint64_t nts_ke_probes;
=====================================
ntpclients/ntpq.py
=====================================
@@ -1491,17 +1491,22 @@ usage: authinfo
def do_ntsinfo(self, _line):
"display NTS authentication counters"
ntsinfo = (
- ("nts_client_send", "NTS client sends: ", NTP_INT),
- ("nts_client_recv", "NTS client recvs: ", NTP_INT),
- ("nts_client_recv_bad", "NTS client recvs w error: ", NTP_INT),
- ("nts_server_recv", "NTS server recvs: ", NTP_INT),
- ("nts_server_recv_bad", "NTS server recvs w error: ", NTP_INT),
- ("nts_server_send", "NTS server sends: ", NTP_INT),
- ("nts_ke_probes", "NTS KE probes: ", NTP_INT),
- ("nts_ke_probes_bad", "NTS KE probes_bad: ", NTP_INT),
- ("nts_ke_serves", "NTS KE serves: ", NTP_INT),
- ("nts_ke_serves_bad", "NTS KE serves_bad: ", NTP_INT),
- )
+ ("nts_client_send", "NTS client sends: ", NTP_INT),
+ ("nts_client_recv", "NTS client recvs: ", NTP_INT),
+ ("nts_client_recv_bad", "NTS client recvs w error: ", NTP_INT),
+ ("nts_server_recv", "NTS server recvs: ", NTP_INT),
+ ("nts_server_recv_bad", "NTS server recvs w error: ", NTP_INT),
+ ("nts_server_send", "NTS server sends: ", NTP_INT),
+ ("nts_cookie_make", "NTS make cookies: ", NTP_INT),
+ ("nts_cookie_decode", "NTS decode cookies: ", NTP_INT),
+ ("nts_cookie_decode_old", "NTS decode cookies old: ", NTP_INT),
+ ("nts_cookie_decode_too_old", "NTS decode cookies too old:", NTP_INT),
+ ("nts_cookie_decode_error", "NTS decode cookies error: ", NTP_INT),
+ ("nts_ke_probes", "NTS KE probes: ", NTP_INT),
+ ("nts_ke_probes_bad", "NTS KE probes_bad: ", NTP_INT),
+ ("nts_ke_serves", "NTS KE serves: ", NTP_INT),
+ ("nts_ke_serves_bad", "NTS KE serves_bad: ", NTP_INT),
+ )
self.collect_display(associd=0, variables=ntsinfo, decodestatus=False)
def help_ntsinfo(self):
=====================================
ntpd/ntp_control.c
=====================================
@@ -356,13 +356,25 @@ static const struct ctl_var sys_var[] = {
{ CS_nts_server_recv, RO, "nts_server_recv" },
#define CS_nts_server_recv_bad 111
{ CS_nts_server_recv_bad, RO, "nts_server_recv_bad" },
-#define CS_nts_ke_serves 112
+
+#define CS_nts_cookie_make 112
+ { CS_nts_cookie_make, RO, "nts_cookie_make" },
+#define CS_nts_cookie_decode 113
+ { CS_nts_cookie_decode, RO, "nts_cookie_decode" },
+#define CS_nts_cookie_decode_old 114
+ { CS_nts_cookie_decode_old, RO, "nts_cookie_decode_old" },
+#define CS_nts_cookie_decode_too_old 115
+ { CS_nts_cookie_decode_too_old, RO, "nts_cookie_decode_too_old" },
+#define CS_nts_cookie_decode_error 116
+ { CS_nts_cookie_decode_error, RO, "nts_cookie_decode_error" },
+
+#define CS_nts_ke_serves 117
{ CS_nts_ke_serves, RO, "nts_ke_serves" },
-#define CS_nts_ke_serves_bad 113
+#define CS_nts_ke_serves_bad 118
{ CS_nts_ke_serves_bad, RO, "nts_ke_serves_bad" },
-#define CS_nts_ke_probes 114
+#define CS_nts_ke_probes 119
{ CS_nts_ke_probes, RO, "nts_ke_probes" },
-#define CS_nts_ke_probes_bad 115
+#define CS_nts_ke_probes_bad 120
{ CS_nts_ke_probes_bad, RO, "nts_ke_probes_bad" },
#define CS_MAXCODE ((sizeof(sys_var)/sizeof(sys_var[0])) - 1)
{ 0, EOV, "" }
@@ -1971,6 +1983,26 @@ ctl_putsys(
ctl_putuint(sys_var[varid].text, nts_server_recv_bad);
break;
+ case CS_nts_cookie_make:
+ ctl_putuint(sys_var[varid].text, nts_cookie_make);
+ break;
+
+ case CS_nts_cookie_decode:
+ ctl_putuint(sys_var[varid].text, nts_cookie_decode);
+ break;
+
+ case CS_nts_cookie_decode_old:
+ ctl_putuint(sys_var[varid].text, nts_cookie_decode_old);
+ break;
+
+ case CS_nts_cookie_decode_too_old:
+ ctl_putuint(sys_var[varid].text, nts_cookie_decode_too_old);
+ break;
+
+ case CS_nts_cookie_decode_error:
+ ctl_putuint(sys_var[varid].text, nts_cookie_decode_error);
+ break;
+
case CS_nts_ke_serves:
ctl_putuint(sys_var[varid].text, nts_ke_serves);
break;
=====================================
ntpd/ntp_timer.c
=====================================
@@ -41,7 +41,8 @@ int interface_interval; /* init_io() sets def. 300s */
*/
static uptime_t interface_timer; /* interface update timer */
static uptime_t adjust_timer; /* second timer */
-static uptime_t stats_timer; /* stats timer */
+static uptime_t stats_timer;
+static uptime_t cookie_timer;
static uptime_t leapf_timer; /* Report leapfile problems once/day */
static uptime_t huffpuff_timer; /* huff-n'-puff timer */
static unsigned long leapsec; /* secs to next leap (proximity class) */
@@ -141,6 +142,7 @@ init_timer(void)
alarm_overflow = 0;
adjust_timer = 1;
stats_timer = SECSPERHR;
+ cookie_timer = SECSPERHR;
leapf_timer = SECSPERDAY;
huffpuff_timer = 0;
interface_timer = 0;
@@ -293,6 +295,12 @@ timer(void)
check_leap_file(false, now);
}
}
+
+ /* time for new NTS K/I ? */
+ if (cookie_timer <= current_time) {
+ cookie_timer += 5*60;
+ nts_timer();
+ }
}
=====================================
ntpd/nts.c
=====================================
@@ -28,19 +28,11 @@ struct ntsconfig_t ntsconfig = {
.tlsciphersuites = NULL,
.cert = NULL,
.key = NULL,
+ .KI = NULL,
.ca = NULL
};
-/*
- * Daily rotation of server-side master keys.
- */
-int nts_daily(struct ntscfg_t *cfg)
-{
- UNUSED_ARG(cfg);
- return 0;
-}
-
/*****************************************************/
=====================================
ntpd/nts_cookie.c
=====================================
@@ -15,14 +15,20 @@
#include "config.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
#include <string.h>
#include <pthread.h>
+#include <unistd.h>
#include <openssl/rand.h>
#include <aes_siv.h>
+#include "ntpd.h"
#include "ntp_stdlib.h"
#include "nts.h"
@@ -57,21 +63,31 @@
* 168
*/
-// FIXME - save K/I on disk
-// FIXME - rotate K/I occasionally
+bool nts_read_cookie_keys(void);
+bool nts_make_cookie_key(void);
+bool nts_write_cookie_keys(void);
-/* cookies use same AEAD algorithms as wire */
-uint8_t K[NTS_MAX_KEYLEN];
-uint32_t I;
-
-AES_SIV_CTX* cookie_ctx; /* need one per thread */
-pthread_mutex_t cookie_lock = PTHREAD_MUTEX_INITIALIZER;
+/* cookies use same AEAD algorithms as wire */
/* This determines which algorithm we use.
* Valid choices are 32, 48, and 64
* making this a variable rather than #define
* opens up the opportunity to pick one at run time. */
int K_length = AEAD_AES_SIV_CMAC_256_KEYLEN;
+uint8_t K[NTS_MAX_KEYLEN], K2[NTS_MAX_KEYLEN];
+uint32_t I, I2;
+time_t K_time = 0; /* time K was created, 0 for none */
+
+AES_SIV_CTX* cookie_ctx; /* one per thread ?? */
+pthread_mutex_t cookie_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Statistics for ntpq */
+uint64_t nts_cookie_make = 0;
+uint64_t nts_cookie_decode = 0;
+uint64_t nts_cookie_decode_old = 0;
+uint64_t nts_cookie_decode_too_old = 0;
+uint64_t nts_cookie_decode_error = 0;
+
// FIXME duplicated in ntp_extens
#define NONCE_LENGTH 16
@@ -80,28 +96,139 @@ int K_length = AEAD_AES_SIV_CMAC_256_KEYLEN;
#define AD_LENGTH 20
#define AEAD_LENGTH 4
+/* cookie_ctx needed for client side */
bool nts_cookie_init(void) {
- bool OK = true;
-#if (OPENSSL_VERSION_NUMBER > 0x1010100fL)
- OK &= RAND_priv_bytes(K, sizeof(K));
- OK &= RAND_bytes((uint8_t *)&I, sizeof(I));
-#else
- OK &= RAND_bytes(K, sizeof(K));
- OK &= RAND_bytes((uint8_t *)&I, sizeof(I));
-#endif
cookie_ctx = AES_SIV_CTX_new();
if (NULL == cookie_ctx) {
msyslog(LOG_ERR, "NTS: Can't init cookie_ctx");
exit(1);
}
-// FIXME hack to allow testing
-if (1) {
- I = 13;
- for (unsigned int i=0; i<sizeof(K); i++) K[i] = i;
+ return true;
+}
+
+/* cookie key needed for server side */
+bool nts_cookie_init2(void) {
+ bool OK = true;
+ if (!nts_read_cookie_keys()) {
+ nts_make_cookie_key(); /* make new cookie key */
+ nts_make_cookie_key(); /* push new to old, make new */
+ K_time = time(NULL);
+ nts_write_cookie_keys();
+ }
+ return OK;
+}
+
+/* Rotate key -- 24 hours after last rotate
+ * That allows a cluster NTS-KE server to keep in sync
+ * if we use ratchet rather than random.
+ */
+// #define SecondsPerDay 86400 FIXME
+// Shorter for debugging
+#define SecondsPerDay 3600
+void nts_timer(void) {
+ time_t now;
+ long int steps;
+ if (0 == K_time)
+ return;
+ now = time(NULL);
+ if (SecondsPerDay > (now-K_time))
+ return;
+ nts_make_cookie_key();
+ /* In case we were off for many days. */
+ steps = (now-K_time) % SecondsPerDay;
+ K_time += steps*SecondsPerDay;
+ if (nts_write_cookie_keys() )
+ msyslog(LOG_INFO, "NTS: Wrote new cookie key.");
+ else
+ msyslog(LOG_INFO, "NTS: Trouble writing new cookie key.");
+ return;
+}
+
+
+bool nts_read_cookie_keys(void) {
+ const char *cookie_filename = NTS_COOKIE_KEY_FILE;
+ FILE *in;
+ unsigned long templ;
+ if (NULL != ntsconfig.KI)
+ cookie_filename = ntsconfig.KI;
+ in = fopen(cookie_filename, "r");
+ if (NULL == in)
+ // FIXME check errno - crash if exists but can't read
+ return false;
+ if (1 != fscanf(in, "T: %lu\n", &templ)) goto bail;
+ K_time = templ;
+ if (1 != fscanf(in, "L: %d\n", &K_length)) goto bail;
+ if (1 != fscanf(in, "I: %u\n", &I)) goto bail;
+ if (0 != fscanf(in, "K: ")) goto bail;
+ for (int i=0; i< K_length; i++) {
+ unsigned int temp;
+ if (1 != fscanf(in, "%02x", &temp)) goto bail;
+ K[i] = temp;
+ }
+ if (0 != fscanf(in, "\n")) goto bail;
+ if (1 != fscanf(in, "I: %u\n", &I2)) goto bail;
+ if (0 != fscanf(in, "K: ")) goto bail;
+ for (int i=0; i< K_length; i++) {
+ unsigned int temp;
+ if (1 != fscanf(in, "%02x", &temp)) goto bail;
+ K2[i] = temp;
+ }
+ if (0 != fscanf(in, "\n")) goto bail;
+ fclose(in);
+ return true;
+
+bail:
+ msyslog(LOG_ERR, "ERR: Error parsing cookie keys file");
+ fclose(in);
+ return false;
}
+
+// FIXME need ratchet mode to make new keys
+bool nts_make_cookie_key(void) {
+ bool OK = true;
+ memcpy(&K2, &K, sizeof(K2)); /* Push current cookie to old */
+ I2 = I;
+#if (OPENSSL_VERSION_NUMBER > 0x1010100fL)
+ OK &= RAND_priv_bytes(K, sizeof(K));
+#else
+ OK &= RAND_bytes(K, sizeof(K));
+#endif
+ OK &= RAND_bytes((uint8_t *)&I, sizeof(I));
return OK;
}
+bool nts_write_cookie_keys(void) {
+ const char *cookie_filename = NTS_COOKIE_KEY_FILE;
+ int fd;
+ FILE *out;
+ if (NULL != ntsconfig.KI)
+ cookie_filename = ntsconfig.KI;
+ fd = open(cookie_filename, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
+ if (-1 == fd) {
+ msyslog(LOG_ERR, "ERR: can't open %s: %s", cookie_filename, strerror(errno));
+ return false;
+ }
+ out = fdopen(fd, "w");
+ if (NULL == out) {
+ msyslog(LOG_ERR, "ERR: can't fdopen %s: %s", cookie_filename, strerror(errno));
+ close(fd);
+ return false;
+ }
+ // FIXME check return values
+ fprintf(out, "T: %lu\n", (unsigned long)K_time);
+ fprintf(out, "L: %d\n", K_length);
+ fprintf(out, "I: %u\n", I);
+ fprintf(out, "K: ");
+ for (int i=0; i< K_length; i++) fprintf(out, "%02x", K[i]);
+ fprintf(out, "\n");
+ fprintf(out, "I: %u\n", I2);
+ fprintf(out, "K: ");
+ for (int i=0; i< K_length; i++) fprintf(out, "%02x", K2[i]);
+ fprintf(out, "\n");
+ fclose(out);
+ return true;
+}
+
/* returns actual length */
int nts_make_cookie(uint8_t *cookie,
uint16_t aead,
@@ -111,15 +238,16 @@ int nts_make_cookie(uint8_t *cookie,
int used, plainlength;
bool ok;
int err;
+ uint8_t * finger;
+ uint32_t temp; /* keep 4 byte alignment */
+ size_t left;
if (NULL == cookie_ctx)
return 0; /* We aren't initialized yet. */
- // ASSERT(keylen<NTS_MAX_KEYLEN);
+ nts_cookie_make++;
- uint8_t * finger;
- uint32_t temp; /* keep 4 byte alignment */
- size_t left;
+ // ASSERT(keylen<NTS_MAX_KEYLEN);
err = pthread_mutex_lock(&cookie_lock);
if (0 != err) {
@@ -172,7 +300,6 @@ int nts_make_cookie(uint8_t *cookie,
used += left;
// ASSERT(length < NTS_MAX_COOKIELEN);
- // Need to encrypt
err = pthread_mutex_unlock(&cookie_lock);
if (0 != err) {
@@ -189,6 +316,7 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
uint8_t *finger;
uint8_t plaintext[NTS_MAX_COOKIELEN];
+ uint8_t *key;
uint8_t *nonce;
uint32_t temp;
size_t plainlength;
@@ -198,14 +326,21 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
if (NULL == cookie_ctx)
return false; /* We aren't initialized yet. */
-// FIXME - these are our cookies. We should know the exact length
+ /* We may get garbage from the net */
if (cookielen > NTS_MAX_COOKIELEN)
return false;
finger = cookie;
- // FIXME should call routine to return key
- if (0 != memcmp(finger, &I, sizeof(I)))
+ if (0 == memcmp(finger, &I, sizeof(I))) {
+ key = K;
+ nts_cookie_decode++;
+ } else if (0 == memcmp(finger, &I2, sizeof(I2))) {
+ key = K2;
+ nts_cookie_decode_old++;
+ } else {
+ nts_cookie_decode_too_old++;
return false;
+ }
finger += sizeof(I);
nonce = finger;
finger += NONCE_LENGTH;
@@ -217,12 +352,14 @@ bool nts_unpack_cookie(uint8_t *cookie, int cookielen,
ok = AES_SIV_Decrypt(cookie_ctx,
plaintext, &plainlength,
- K, K_length,
+ key, K_length,
nonce, NONCE_LENGTH,
finger, cipherlength,
cookie, AD_LENGTH);
- if (!ok)
+ if (!ok) {
+ nts_cookie_decode_error++;
return false;
+ }
*keylen = (plainlength-AEAD_LENGTH)/2;
finger = plaintext;
=====================================
ntpd/nts_extens.c
=====================================
@@ -29,17 +29,13 @@
#define NTP_EX_HDR_LNG 4
#define NTP_EX_U16_LNG 2
-/* Statistics */
+/* Statistics for ntpq */
uint64_t nts_client_send = 0;
uint64_t nts_client_recv = 0;
uint64_t nts_client_recv_bad = 0;
uint64_t nts_server_send = 0;
uint64_t nts_server_recv = 0;
uint64_t nts_server_recv_bad = 0;
-uint64_t nts_ke_serves = 0;
-uint64_t nts_ke_serves_bad = 0;
-uint64_t nts_ke_probes = 0;
-uint64_t nts_ke_probes_bad = 0;
enum NtpExtFieldType {
Unique_Identifier = 0x104,
=====================================
ntpd/nts_server.c
=====================================
@@ -20,11 +20,6 @@
#include "ntp_stdlib.h"
#include "nts.h"
-/* default file names */
-#define NTS_CERT_FILE "/etc/ntp/cert-chain.pem"
-#define NTS_KEY_FILE "/etc/ntp/key.pem"
-
-int nts_ke_port = 123;
static bool nts_load_certificate(SSL_CTX *ctx);
static int create_listener(int port, int family);
@@ -37,12 +32,20 @@ static SSL_CTX *server_ctx = NULL;
static int listner4_sock = -1;
static int listner6_sock = -1;
+/* Statistics for ntpq */
+uint64_t nts_ke_serves = 0;
+uint64_t nts_ke_serves_bad = 0;
+uint64_t nts_ke_probes = 0;
+uint64_t nts_ke_probes_bad = 0;
+
+
void nts_init(void) {
bool ok = true;
- ok &= nts_cookie_init();
- if (ntsconfig.ntsenable)
+ if (ntsconfig.ntsenable) {
ok &= nts_server_init();
+ }
ok &= nts_client_init();
+ ok &= nts_cookie_init();
ok &= extens_init();
if (!ok) {
msyslog(LOG_ERR, "NTS: troubles during init. Bailing.");
@@ -52,8 +55,10 @@ void nts_init(void) {
void nts_init2(void) {
bool ok = true;
- if (ntsconfig.ntsenable)
+ if (ntsconfig.ntsenable) {
ok &= nts_server_init2();
+ ok &= nts_cookie_init2();
+ }
if (!ok) {
msyslog(LOG_ERR, "NTS: troubles during init2. Bailing.");
exit(1);
@@ -64,7 +69,7 @@ bool nts_server_init(void) {
bool ok = true;
msyslog(LOG_INFO, "NTSs: starting NTS-KE server listening on port %d",
- nts_ke_port);
+ NTS_KE_PORT);
#if (OPENSSL_VERSION_NUMBER > 0x1010000fL)
server_ctx = SSL_CTX_new(TLS_server_method());
@@ -98,9 +103,9 @@ bool nts_server_init(void) {
#endif
- listner4_sock = create_listener(nts_ke_port, AF_INET);
+ listner4_sock = create_listener(NTS_KE_PORT, AF_INET);
if (listner4_sock < 0) return false;
- listner6_sock = create_listener(nts_ke_port, AF_INET6);
+ listner6_sock = create_listener(NTS_KE_PORT, AF_INET6);
if (listner6_sock < 0) return false;
return true;
@@ -159,7 +164,7 @@ void* nts_ke_listener(void* arg) {
nts_ke_serves_bad++;
continue;
}
- msyslog(LOG_INFO, "NTSs: Using %s, %s (%d)",
+ msyslog(LOG_INFO, "NTSs: Using %s, %s (%d)",
SSL_get_version(ssl),
SSL_get_cipher_name(ssl),
SSL_get_cipher_bits(ssl, NULL));
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/407979f7c3e22b6bdf0f6523930e9bae699c362b...f9860502a52a133c4ef0bb8a4651a6e254cb434c
--
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/407979f7c3e22b6bdf0f6523930e9bae699c362b...f9860502a52a133c4ef0bb8a4651a6e254cb434c
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20190309/862d04e5/attachment-0001.html>
More information about the vc
mailing list