/* ================================================== */
NAU_Instance
-NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, uint16_t ntp_port)
+NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, uint32_t cert_set,
+ uint16_t ntp_port)
{
NAU_Instance instance = create_instance(NTP_AUTH_NTS);
- instance->nts = NNC_CreateInstance(nts_address, name, ntp_port);
+ instance->nts = NNC_CreateInstance(nts_address, name, cert_set, ntp_port);
return instance;
}
extern NAU_Instance NAU_CreateNoneInstance(void);
extern NAU_Instance NAU_CreateSymmetricInstance(uint32_t key_id);
extern NAU_Instance NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name,
- uint16_t ntp_port);
+ uint32_t cert_set, uint16_t ntp_port);
/* Destroy an instance */
extern void NAU_DestroyInstance(NAU_Instance instance);
nts_address.ip_addr = remote_addr->ip_addr;
nts_address.port = params->nts_port;
- result->auth = NAU_CreateNtsInstance(&nts_address, name, result->remote_addr.port);
+ result->auth = NAU_CreateNtsInstance(&nts_address, name, 0,
+ result->remote_addr.port);
} else if (params->authkey != INACTIVE_AUTHKEY) {
result->auth = NAU_CreateSymmetricInstance(params->authkey);
} else {
struct NKC_Instance_Record {
char *name;
IPSockAddr address;
+ NKSN_Credentials credentials;
NKSN_Instance session;
int destroying;
int got_response;
/* ================================================== */
-static NKSN_Credentials client_credentials = NULL;
-static int client_credentials_refs = 0;
+static NKSN_Credentials default_credentials = NULL;
+static int default_credentials_refs = 0;
/* ================================================== */
/* ================================================== */
NKC_Instance
-NKC_CreateInstance(IPSockAddr *address, const char *name)
+NKC_CreateInstance(IPSockAddr *address, const char *name, uint32_t cert_set)
{
const char **trusted_certs;
+ uint32_t *certs_ids;
NKC_Instance inst;
int n_certs;
inst->got_response = 0;
n_certs = CNF_GetNtsTrustedCertsPaths(&trusted_certs);
+ certs_ids = MallocArray(uint32_t, n_certs);
+ memset(certs_ids, 0, sizeof (uint32_t) * n_certs);
+
+ /* Share the credentials among clients using the default set of trusted
+ certificates, which likely contains most certificates */
+ if (cert_set == 0) {
+ if (!default_credentials)
+ default_credentials = NKSN_CreateClientCertCredentials(trusted_certs, certs_ids,
+ n_certs, cert_set);
+ inst->credentials = default_credentials;
+ if (default_credentials)
+ default_credentials_refs++;
+ } else {
+ inst->credentials = NKSN_CreateClientCertCredentials(trusted_certs, certs_ids,
+ n_certs, cert_set);
+ }
- /* Share the credentials with other client instances */
- if (!client_credentials)
- client_credentials = NKSN_CreateClientCertCredentials(trusted_certs, n_certs);
- client_credentials_refs++;
+ Free(certs_ids);
return inst;
}
Free(inst->name);
- client_credentials_refs--;
- if (client_credentials_refs <= 0 && client_credentials) {
- NKSN_DestroyCertCredentials(client_credentials);
- client_credentials = NULL;
+ if (inst->credentials) {
+ if (inst->credentials == default_credentials) {
+ default_credentials_refs--;
+ if (default_credentials_refs <= 0) {
+ NKSN_DestroyCertCredentials(default_credentials);
+ default_credentials = NULL;
+ }
+ } else {
+ NKSN_DestroyCertCredentials(inst->credentials);
+ }
}
/* If the asynchronous resolver is running, let the handler free
inst->got_response = 0;
- if (!client_credentials) {
+ if (!inst->credentials) {
DEBUG_LOG("Missing client credentials");
return 0;
}
}
/* Start an NTS-KE session */
- if (!NKSN_StartSession(inst->session, sock_fd, label, client_credentials, CLIENT_TIMEOUT)) {
+ if (!NKSN_StartSession(inst->session, sock_fd, label, inst->credentials, CLIENT_TIMEOUT)) {
SCK_CloseSocket(sock_fd);
return 0;
}
typedef struct NKC_Instance_Record *NKC_Instance;
/* Create a client NTS-KE instance */
-extern NKC_Instance NKC_CreateInstance(IPSockAddr *address, const char *name);
+extern NKC_Instance NKC_CreateInstance(IPSockAddr *address, const char *name, uint32_t cert_set);
/* Destroy an instance */
extern void NKC_DestroyInstance(NKC_Instance inst);
static NKSN_Credentials
create_credentials(const char **certs, const char **keys, int n_certs_keys,
- const char **trusted_certs, int n_trusted_certs)
+ const char **trusted_certs, uint32_t *trusted_certs_ids,
+ int n_trusted_certs, uint32_t trusted_cert_set)
{
gnutls_certificate_credentials_t credentials = NULL;
int i, r;
goto error;
if (certs && keys) {
- assert(!trusted_certs);
+ if (trusted_certs || trusted_certs_ids)
+ assert(0);
for (i = 0; i < n_certs_keys; i++) {
r = gnutls_certificate_set_x509_key_file(credentials, certs[i], keys[i],
if (certs || keys || n_certs_keys > 0)
assert(0);
- if (!CNF_GetNoSystemCert()) {
+ if (trusted_cert_set == 0 && !CNF_GetNoSystemCert()) {
r = gnutls_certificate_set_x509_system_trust(credentials);
if (r < 0)
goto error;
}
- if (trusted_certs) {
+ if (trusted_certs && trusted_certs_ids) {
for (i = 0; i < n_trusted_certs; i++) {
struct stat buf;
+ if (trusted_certs_ids[i] != trusted_cert_set)
+ continue;
+
if (stat(trusted_certs[i], &buf) == 0 && S_ISDIR(buf.st_mode))
r = gnutls_certificate_set_x509_trust_dir(credentials, trusted_certs[i],
GNUTLS_X509_FMT_PEM);
NKSN_Credentials
NKSN_CreateServerCertCredentials(const char **certs, const char **keys, int n_certs_keys)
{
- return create_credentials(certs, keys, n_certs_keys, NULL, 0);
+ return create_credentials(certs, keys, n_certs_keys, NULL, NULL, 0, 0);
}
/* ================================================== */
NKSN_Credentials
-NKSN_CreateClientCertCredentials(const char **trusted_certs, int n_certs)
+NKSN_CreateClientCertCredentials(const char **certs, uint32_t *ids,
+ int n_certs_ids, uint32_t trusted_cert_set)
{
- return create_credentials(NULL, NULL, 0, trusted_certs, n_certs);
+ return create_credentials(NULL, NULL, 0, certs, ids, n_certs_ids, trusted_cert_set);
}
/* ================================================== */
different clients or servers. */
extern NKSN_Credentials NKSN_CreateServerCertCredentials(const char **certs, const char **keys,
int n_certs_keys);
-extern NKSN_Credentials NKSN_CreateClientCertCredentials(const char **trusted_certs,
- int n_certs);
+extern NKSN_Credentials NKSN_CreateClientCertCredentials(const char **certs, uint32_t *ids,
+ int n_certs_ids,
+ uint32_t trusted_cert_set);
/* Destroy the credentials */
extern void NKSN_DestroyCertCredentials(NKSN_Credentials credentials);
IPSockAddr nts_address;
/* Hostname or IP address for certificate verification */
char *name;
+ /* ID of trusted certificates */
+ uint32_t cert_set;
/* Configured NTP port */
uint16_t default_ntp_port;
/* Address of NTP server (can be negotiated in NTS-KE) */
/* ================================================== */
NNC_Instance
-NNC_CreateInstance(IPSockAddr *nts_address, const char *name, uint16_t ntp_port)
+NNC_CreateInstance(IPSockAddr *nts_address, const char *name, uint32_t cert_set, uint16_t ntp_port)
{
NNC_Instance inst;
inst->nts_address = *nts_address;
inst->name = Strdup(name);
+ inst->cert_set = cert_set;
inst->default_ntp_port = ntp_port;
inst->ntp_address.ip_addr = nts_address->ip_addr;
inst->ntp_address.port = ntp_port;
return 0;
}
- inst->nke = NKC_CreateInstance(&inst->nts_address, inst->name);
+ inst->nke = NKC_CreateInstance(&inst->nts_address, inst->name, inst->cert_set);
inst->nke_attempts++;
update_next_nke_attempt(inst, now);
typedef struct NNC_Instance_Record *NNC_Instance;
extern NNC_Instance NNC_CreateInstance(IPSockAddr *nts_address, const char *name,
- uint16_t ntp_port);
+ uint32_t cert_set, uint16_t ntp_port);
extern void NNC_DestroyInstance(NNC_Instance inst);
extern int NNC_PrepareForAuth(NNC_Instance inst);
extern int NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
}
NNC_Instance
-NNC_CreateInstance(IPSockAddr *nts_address, const char *name, uint16_t ntp_port)
+NNC_CreateInstance(IPSockAddr *nts_address, const char *name, uint32_t cert_set,
+ uint16_t ntp_port)
{
return NULL;
}
can_auth_res = can_auth_req;
break;
case 2:
- inst = NAU_CreateNtsInstance(&nts_addr, "test", 0);
+ inst = NAU_CreateNtsInstance(&nts_addr, "test", 0, 0);
TEST_CHECK(NAU_IsAuthEnabled(inst));
TEST_CHECK(NAU_GetSuggestedNtpVersion(inst) == 4);
mode = NTP_AUTH_NTS;
SCK_GetLoopbackIPAddress(AF_INET, &addr.ip_addr);
addr.port = 0;
- inst = NKC_CreateInstance(&addr, "test");
+ inst = NKC_CreateInstance(&addr, "test", 0);
TEST_CHECK(inst);
for (i = 0; i < 10000; i++) {
NKSN_Credentials client_cred, server_cred;
const char *cert, *key;
int sock_fds[2], i;
+ uint32_t cert_id;
LCL_Initialise();
TST_RegisterDummyDrivers();
cert = "nts_ke.crt";
key = "nts_ke.key";
+ cert_id = 0;
for (i = 0; i < 50; i++) {
SCH_Initialise();
client = NKSN_CreateInstance(0, "test", handle_response, NULL);
server_cred = NKSN_CreateServerCertCredentials(&cert, &key, 1);
- client_cred = NKSN_CreateClientCertCredentials(&cert, 1);
+ client_cred = NKSN_CreateClientCertCredentials(&cert, &cert_id, 1, 0);
TEST_CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds) == 0);
TEST_CHECK(fcntl(sock_fds[0], F_SETFL, O_NONBLOCK) == 0);
#include "ntp.h"
#include "nts_ke_client.h"
-#define NKC_CreateInstance(address, name) Malloc(1)
+#define NKC_CreateInstance(address, name, cert_set) Malloc(1)
#define NKC_DestroyInstance(inst) Free(inst)
#define NKC_Start(inst) (random() % 2)
#define NKC_IsActive(inst) (random() % 2)
SCK_GetLoopbackIPAddress(AF_INET, &addr.ip_addr);
addr.port = 0;
- inst = NNC_CreateInstance(&addr, "test", 0);
+ inst = NNC_CreateInstance(&addr, "test", 0, 0);
TEST_CHECK(inst);
for (i = 0; i < 100000; i++) {