46#define PROTOCOL_D0_BLIND_ID FOURCC_D0PK
47#define PROTOCOL_VLEN (('v' << 0) | ('l' << 8) | ('e' << 16) | ('n' << 24))
50#define FOURCC_D0PK (('d' << 0) | ('0' << 8) | ('p' << 16) | ('k' << 24))
51#define FOURCC_D0SK (('d' << 0) | ('0' << 8) | ('s' << 16) | ('k' << 24))
52#define FOURCC_D0PI (('d' << 0) | ('0' << 8) | ('p' << 16) | ('i' << 24))
53#define FOURCC_D0SI (('d' << 0) | ('0' << 8) | ('s' << 16) | ('i' << 24))
54#define FOURCC_D0IQ (('d' << 0) | ('0' << 8) | ('i' << 16) | ('q' << 24))
55#define FOURCC_D0IR (('d' << 0) | ('0' << 8) | ('i' << 16) | ('r' << 24))
56#define FOURCC_D0ER (('d' << 0) | ('0' << 8) | ('e' << 16) | ('r' << 24))
57#define FOURCC_D0IC (('d' << 0) | ('0' << 8) | ('i' << 16) | ('c' << 24))
62 ((
unsigned char)
data[0]) |
63 (((
unsigned char)
data[1]) << 8) |
64 (((
unsigned char)
data[2]) << 16) |
65 (((
unsigned char)
data[3]) << 24);
71 data[1] = (l >> 8) & 0xFF;
72 data[2] = (l >> 16) & 0xFF;
73 data[3] = (l >> 24) & 0xFF;
76static size_t Crypto_ParsePack(
const char *
buf,
size_t len,
unsigned long header,
const char **lumps,
size_t *lumpsize,
size_t nlumps)
89 for(
i = 0;
i < nlumps; ++
i)
95 if(pos + lumpsize[
i] > len)
103static size_t Crypto_UnParsePack(
char *
buf,
size_t len,
unsigned long header,
const char *
const *lumps,
const size_t *lumpsize,
size_t nlumps)
115 for(
i = 0;
i < nlumps; ++
i)
117 if(pos + 4 + lumpsize[
i] > len)
121 memcpy(&
buf[pos], lumps[
i], lumpsize[
i]);
132#include <d0_blind_id/d0_blind_id.h>
134#define d0_blind_id_dll 1
135#define Crypto_OpenLibrary() true
136#define Crypto_CloseLibrary()
138#define qd0_blind_id_new d0_blind_id_new
139#define qd0_blind_id_free d0_blind_id_free
141#define qd0_blind_id_copy d0_blind_id_copy
145#define qd0_blind_id_read_public_key d0_blind_id_read_public_key
148#define qd0_blind_id_fingerprint64_public_key d0_blind_id_fingerprint64_public_key
150#define qd0_blind_id_read_private_id_modulus d0_blind_id_read_private_id_modulus
152#define qd0_blind_id_generate_private_id_start d0_blind_id_generate_private_id_start
153#define qd0_blind_id_generate_private_id_request d0_blind_id_generate_private_id_request
155#define qd0_blind_id_finish_private_id_request d0_blind_id_finish_private_id_request
158#define qd0_blind_id_read_private_id d0_blind_id_read_private_id
160#define qd0_blind_id_write_private_id d0_blind_id_write_private_id
162#define qd0_blind_id_authenticate_with_private_id_start d0_blind_id_authenticate_with_private_id_start
163#define qd0_blind_id_authenticate_with_private_id_challenge d0_blind_id_authenticate_with_private_id_challenge
164#define qd0_blind_id_authenticate_with_private_id_response d0_blind_id_authenticate_with_private_id_response
165#define qd0_blind_id_authenticate_with_private_id_verify d0_blind_id_authenticate_with_private_id_verify
166#define qd0_blind_id_fingerprint64_public_id d0_blind_id_fingerprint64_public_id
167#define qd0_blind_id_sessionkey_public_id d0_blind_id_sessionkey_public_id
168#define qd0_blind_id_INITIALIZE d0_blind_id_INITIALIZE
169#define qd0_blind_id_SHUTDOWN d0_blind_id_SHUTDOWN
170#define qd0_blind_id_util_sha256 d0_blind_id_util_sha256
171#define qd0_blind_id_sign_with_private_id_sign d0_blind_id_sign_with_private_id_sign
172#define qd0_blind_id_sign_with_private_id_sign_detached d0_blind_id_sign_with_private_id_sign_detached
173#define qd0_blind_id_setmallocfuncs d0_blind_id_setmallocfuncs
174#define qd0_blind_id_setmutexfuncs d0_blind_id_setmutexfuncs
175#define qd0_blind_id_verify_public_id d0_blind_id_verify_public_id
176#define qd0_blind_id_verify_private_id d0_blind_id_verify_private_id
182#if defined (__GNUC__) || (__clang__) || (__TINYC__)
183#define D0_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
185#define D0_WARN_UNUSED_RESULT
285 const char* dllnames [] =
288 "libd0_blind_id-0.dll",
290 "libd0_blind_id.0.dylib",
292 "libd0_blind_id.so.0",
313#ifdef LINK_TO_CRYPTO_RIJNDAEL
315#include <d0_blind_id/d0_rijndael.h>
317#define d0_rijndael_dll 1
318#define Crypto_Rijndael_OpenLibrary() true
319#define Crypto_Rijndael_CloseLibrary()
321#define qd0_rijndael_setup_encrypt d0_rijndael_setup_encrypt
322#define qd0_rijndael_setup_decrypt d0_rijndael_setup_decrypt
323#define qd0_rijndael_encrypt d0_rijndael_encrypt
324#define qd0_rijndael_decrypt d0_rijndael_decrypt
335 const unsigned char plaintext[16],
unsigned char ciphertext[16]);
337 const unsigned char ciphertext[16],
unsigned char plaintext[16]);
338#define D0_RIJNDAEL_KEYLENGTH(keybits) ((keybits)/8)
339#define D0_RIJNDAEL_RKLENGTH(keybits) ((keybits)/8+28)
340#define D0_RIJNDAEL_NROUNDS(keybits) ((keybits)/32+6)
354 const char* dllnames [] =
357 "libd0_rijndael-0.dll",
359 "libd0_rijndael.0.dylib",
361 "libd0_rijndael.so.0",
383void sha256(
unsigned char *out,
const unsigned char *in,
int n)
412 memcpy(*
data, str, l+1);
421 const char *data_save = *
data;
434 p = (
const char *) memchr(*
data, 0, *len);
446 return (
const char *) data_save;
481#define MAX_PUBKEYS 16
493#define MAX_CRYPTOCONNECTS 16
494#define CRYPTOCONNECT_NONE 0
495#define CRYPTOCONNECT_PRECONNECT 1
496#define CRYPTOCONNECT_CONNECT 2
497#define CRYPTOCONNECT_RECONNECT 3
498#define CRYPTOCONNECT_DUPLICATE 4
499typedef struct server_cryptoconnect_s
515 char challenge[2048];
524#define CDATA ((crypto_data_t *) crypto->data)
525#define MAKE_CDATA if(!crypto->data) crypto->data = Z_Malloc(sizeof(crypto_data_t))
526#define CLEAR_CDATA if(crypto->data) { if(CDATA->id) qd0_blind_id_free(CDATA->id); Z_Free(crypto->data); } crypto->data = NULL
563 Con_Printf(
"Passed an invalid crypto connect instance\n");
564 memset(out, 0,
sizeof(*out));
568 memcpy(out, crypto,
sizeof(*out));
569 memset(crypto, 0,
sizeof(*crypto));
579typedef struct crypto_storedhostkey_s
581 struct crypto_storedhostkey_s *
next;
653 aeslevel =
bound(0, *keystring -
'0', 3);
654 while(*keystring && *keystring !=
' ')
659 while(*keystring && keyid < 0)
662 const char *idstart, *idend, *keystart, *keyend;
663 qbool thisissigned =
true;
666 while(*keystring && *keystring !=
' ' && *keystring !=
'@')
672 keystart = keystring;
673 while(*keystring && *keystring !=
' ')
677 if (keystart[0] ==
'~')
679 thisissigned =
false;
686 for(thiskeyid =
MAX_PUBKEYS - 1; thiskeyid >= 0; --thiskeyid)
693 issigned = thisissigned;
712 Con_Printf(
"Server %s tried to change the host key to a value not in the host cache. Connecting to it will fail. To accept the new host key, do crypto_hostkey_clear %s\n",
buf,
buf);
714 Con_Printf(
"Server %s tried to reduce encryption status, not accepted. Connecting to it will fail. To accept, do crypto_hostkey_clear %s\n",
buf,
buf);
716 Con_Printf(
"Server %s tried to reduce signature status, not accepted. Connecting to it will fail. To accept, do crypto_hostkey_clear %s\n",
buf,
buf);
725 memcpy(&hk->
addr, peeraddress,
sizeof(hk->
addr));
787 char *p, *lengthptr, *startptr;
830 FS_Printf(
f,
"This is a PUBLIC ID file for DarkPlaces.\n");
831 FS_Printf(
f,
"You are free to share this file or its contents.\n");
833 FS_Printf(
f,
"This file will be automatically generated again if deleted.\n");
835 FS_Printf(
f,
"However, NEVER share the accompanying SECRET ID file called\n");
909 Con_Printf(
"NOTE: this ID has not yet been signed!\n");
915 Con_Printf(
"d0_blind_id_verify_private_id failed, this is not a valid key!\n");
922 Con_Printf(
"d0_blind_id_fingerprint64_public_id failed\n");
1087 Con_Printf(
"libd0_blind_id initialization FAILED, cryptography support has been disabled\n");
1109 static char buf[8192];
1110 static char buf2[8192];
1120 Con_Print(
"libd0_blind_id DLL not found, this command is inactive.\n");
1128 Con_Printf(
"Unexpected response from keygen server:\n");
1157 Con_Printf(
"d0_blind_id_finish_private_id_request failed\n");
1166 Con_Printf(
"d0_blind_id_verify_public_id failed\n");
1182 Con_Printf(
"d0_blind_id_write_private_id failed\n");
1222 static char buf[8192];
1223 static char buf2[8192];
1225 size_t buf2l, buf2pos;
1232 Con_Print(
"libd0_blind_id DLL not found, this command is inactive.\n");
1251 Con_Printf(
"there is already a keygen run on the way\n");
1262 Con_Printf(
"there is already a signed private key for %d\n",
i);
1268 Con_Printf(
"Only need a signature for an existing key...\n");
1283 Con_Printf(
"d0_blind_id_verify_private_id failed\n");
1304 Con_Printf(
"d0_blind_id_write_private_id failed\n");
1337 Con_Printf(
"d0_blind_id_generate_private_id_request failed\n");
1351 if(!(buf2l =
base64_encode((
unsigned char *) (buf2 + buf2pos), buf2l,
sizeof(buf2) - buf2pos - 1)))
1367 Con_Printf(
"Signature generation in progress...\n");
1385 Con_Print(
"libd0_blind_id DLL not found, this command is inactive.\n");
1397 Con_Printf(
" NOTE: this ID has not yet been signed!\n");
1411 Con_Print(
"libd0_blind_id DLL not found, this command is inactive.\n");
1435 Con_Print(
"libd0_blind_id DLL not found, this command is inactive.\n");
1472static void aescpy(
unsigned char *key,
const unsigned char *iv,
unsigned char *dst,
const unsigned char *
src,
size_t len)
1474 const unsigned char *xorpos = iv;
1475 unsigned char xorbuf[16];
1481 for(
i = 0;
i < 16; ++
i)
1482 xorbuf[
i] =
src[
i] ^ xorpos[
i];
1491 for(
i = 0;
i < len; ++
i)
1492 xorbuf[
i] =
src[
i] ^ xorpos[
i];
1494 xorbuf[
i] = xorpos[
i];
1498static void seacpy(
unsigned char *key,
const unsigned char *iv,
unsigned char *dst,
const unsigned char *
src,
size_t len)
1500 const unsigned char *xorpos = iv;
1501 unsigned char xorbuf[16];
1508 for(
i = 0;
i < 16; ++
i)
1509 dst[
i] = xorbuf[
i] ^ xorpos[
i];
1518 for(
i = 0;
i < len; ++
i)
1519 dst[
i] = xorbuf[
i] ^ xorpos[
i];
1529 unsigned char h[32];
1545 Con_Printf(
"Crypto_EncryptPacket failed (not enough space: %d bytes in, %d bytes out)\n", (
int) len_src, (
int) len);
1548 *len_dst = ((len_src + 15) / 16) * 16 + 16;
1549 ((
unsigned char *) data_dst)[0] = (
unsigned char)(*len_dst - len_src);
1550 memcpy(((
unsigned char *) data_dst)+1, h, 15);
1551 aescpy(crypto->
dhkey, (
const unsigned char *) data_dst, ((
unsigned char *) data_dst) + 16, (
const unsigned char *) data_src, len_src);
1559 Con_Printf(
"Crypto_EncryptPacket failed (not enough space: %d bytes in, %d bytes out)\n", (
int) len_src, (
int) len);
1562 *len_dst = len_src + 16;
1563 memcpy(data_dst, h, 16);
1564 memcpy(((
unsigned char *) data_dst) + 16, (
unsigned char *) data_src, len_src);
1569 (
i == (
int)0xFFFFFFFF)
1571 (
i == (
int)0x80000000 + (
int)*len_dst)
1573 *(
unsigned char *)data_dst ^= 0x80;
1586 unsigned char h[32];
1592 (
i == (
int)0xFFFFFFFF)
1594 (
i == (
int)0x80000000 + (
int)len_src)
1602 if(len_src < 16 || ((len_src - 16) % 16))
1604 Con_Printf(
"Crypto_DecryptPacket failed (not enough space: %d bytes in, %d bytes out)\n", (
int) len_src, (
int) len);
1607 *len_dst = len_src - ((
unsigned char *) data_src)[0];
1608 if(len < *len_dst || *len_dst > len_src - 16)
1610 Con_Printf(
"Crypto_DecryptPacket failed (not enough space: %d bytes in, %d->%d bytes out)\n", (
int) len_src, (
int) *len_dst, (
int) len);
1613 seacpy(crypto->
dhkey, (
unsigned char *) data_src, (
unsigned char *) data_dst, ((
const unsigned char *) data_src) + 16, *len_dst);
1620 if(memcmp(((
const unsigned char *) data_src)+1, h, 15))
1636 Con_Printf(
"Crypto_DecryptPacket failed (not enough space: %d bytes in, %d bytes out)\n", (
int) len_src, (
int) len);
1639 *len_dst = len_src - 16;
1642 Con_Printf(
"Crypto_DecryptPacket failed (not enough space: %d bytes in, %d->%d bytes out)\n", (
int) len_src, (
int) *len_dst, (
int) len);
1653 if(memcmp((
const unsigned char *) data_src, h, 16))
1657 (
i == (
int)0x7FFFFFFF)
1659 (
i == (
int)0x00000000 + (
int)len_src)
1664 if(memcmp((
const unsigned char *) data_src, h, 16))
1678 return ((
const unsigned char *) data_src) + 16;
1715 dpsnprintf(data_out, *len_out,
"reject %s", msg_client);
1716 *len_out =
strlen(data_out);
1731 char *data_out_p = data_out;
1732 const char *
string = data_in;
1747 if (!
InfoString_GetValue(
string + 4,
"challenge", infostringvalue,
sizeof(infostringvalue)))
1760 return Crypto_ServerError(data_out, len_out,
"This server requires authentication and encryption to be supported by your client",
NULL);
1764 const char *cnt, *p;
1766 int clientid = -1, serverid = -1;
1767 id = (
InfoString_GetValue(
string + 4,
"id", infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : -1);
1768 cnt = (
InfoString_GetValue(
string + 4,
"cnt", infostringvalue,
sizeof(infostringvalue)) ? infostringvalue :
NULL);
1774 if(!strcmp(cnt,
"0"))
1777 if (!
InfoString_GetValue(
string + 4,
"challenge", infostringvalue,
sizeof(infostringvalue)))
1788 if (!
InfoString_GetValue(
string + 4,
"aeslevel", infostringvalue,
sizeof(infostringvalue)))
1791 aeslevel =
bound(0, atoi(infostringvalue), 3);
1797 return Crypto_ServerError(data_out, len_out,
"This server requires encryption to be not required (crypto_aeslevel <= 2)",
NULL);
1801 aes = (aeslevel >= 2);
1804 aes = (aeslevel >= 1);
1808 return Crypto_ServerError(data_out, len_out,
"This server requires encryption to be supported (crypto_aeslevel >= 1, and d0_rijndael library must be present)",
NULL);
1846 CDATA->s = serverid;
1847 CDATA->c = clientid;
1848 memset(crypto->
dhkey, 0,
sizeof(crypto->
dhkey));
1849 CDATA->challenge[0] = 0;
1868 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_new failed",
"Internal error");
1873 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_copy failed",
"Internal error");
1875 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\1\\id\\%d\\aes\\%d",
CDATA->cdata_id, crypto->
use_aes));
1879 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_start failed",
"Internal error");
1881 CDATA->next_step = 2;
1882 data_out_p += *len_out;
1883 *len_out = data_out_p - data_out;
1886 else if(
CDATA->c >= 0)
1893 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_new failed",
"Internal error");
1898 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_copy failed",
"Internal error");
1900 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\5\\id\\%d\\aes\\%d",
CDATA->cdata_id, crypto->
use_aes));
1904 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_challenge failed",
"Internal error");
1906 CDATA->next_step = 6;
1907 data_out_p += *len_out;
1908 *len_out = data_out_p - data_out;
1917 else if(!strcmp(cnt,
"2"))
1924 if(
CDATA->cdata_id !=
id)
1926 if(
CDATA->next_step != 2)
1929 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\3\\id\\%d",
CDATA->cdata_id));
1933 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_response failed",
"Internal error");
1939 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_sessionkey_public_id failed",
"Internal error");
1946 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_copy failed",
"Internal error");
1948 CDATA->next_step = 4;
1954 CDATA->next_step = 0;
1956 data_out_p += *len_out;
1957 *len_out = data_out_p - data_out;
1960 else if(!strcmp(cnt,
"4"))
1966 if(
CDATA->cdata_id !=
id)
1968 if(
CDATA->next_step != 4)
1970 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\5\\id\\%d",
CDATA->cdata_id));
1974 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_challenge failed",
"Internal error");
1976 CDATA->next_step = 6;
1977 data_out_p += *len_out;
1978 *len_out = data_out_p - data_out;
1981 else if(!strcmp(cnt,
"6"))
1983 static char msgbuf[32];
1984 size_t msgbuflen =
sizeof(msgbuf);
1992 if(
CDATA->cdata_id !=
id)
1994 if(
CDATA->next_step != 6)
2000 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_verify failed (authentication error)",
"Authentication error");
2010 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_fingerprint64_public_id failed",
"Internal error");
2016 return Crypto_ServerError(data_out, len_out,
"d0_blind_id_sessionkey_public_id failed",
"Internal error");
2024 CDATA->next_step = 0;
2026 PutWithNul(&data_out_p, len_out,
"challenge ");
2027 *len_out = data_out_p - data_out;
2040 static double complain_time = 0;
2042 qbool do_time =
false;
2043 qbool do_reject =
false;
2046 if(len_in > 5 && !memcmp(data_in,
"d0pk\\", 5))
2049 cnt = (
InfoString_GetValue(data_in + 4,
"cnt", infostringvalue,
sizeof(infostringvalue)) ? infostringvalue :
NULL);
2051 if(!strcmp(cnt,
"0"))
2074 Con_Printf(
"crypto: cannot perform requested crypto operations; denial service attack or crypto_servercpupercent/crypto_servercpumaxtime are too low\n");
2095 dpsnprintf(data_out, *len_out,
"reject %s", msg);
2096 *len_out =
strlen(data_out);
2110 const char *
string = data_in;
2112 char *data_out_p = data_out;
2125 int wantserverid = -1;
2129 if(wantserverid >= 0)
2130 return Crypto_ClientError(data_out, len_out,
"Server tried an unauthenticated connection even though a host key is present");
2132 return Crypto_ClientError(data_out, len_out,
"This server requires encryption to be not required (crypto_aeslevel <= 2)");
2138 int wantserverid = -1;
2142 if(wantserverid >= 0)
2143 return Crypto_ClientError(data_out, len_out,
"Server tried an unauthenticated connection even though a host key is present");
2145 return Crypto_ClientError(data_out, len_out,
"This server requires encryption to be not required (crypto_aeslevel <= 2)");
2151 int wantserverid = -1;
2164 if(wantserverid >= 0)
2165 return Crypto_ClientError(data_out, len_out,
"Server tried an unauthenticated connection even though a host key is present");
2167 return Crypto_ClientError(data_out, len_out,
"This server requires encryption to be not required (crypto_aeslevel <= 2)");
2171 else if (len_in >= 13 && !memcmp(
string,
"infoResponse\x0A", 13))
2173 if(
InfoString_GetValue(
string + 13,
"d0_blind_id", infostringvalue,
sizeof(infostringvalue)))
2177 else if (len_in >= 15 && !memcmp(
string,
"statusResponse\x0A", 15))
2181 p = strchr(
string + 15,
'\n');
2187 if(
InfoString_GetValue(
string + 15,
"d0_blind_id", infostringvalue,
sizeof(infostringvalue)))
2191 * (
char *) p = save;
2198 const char *vlen_blind_id_ptr =
NULL;
2199 size_t len_blind_id_ptr = 0;
2201 const char *challenge = data_in + 10;
2204 int clientid = -1, serverid = -1, wantserverid = -1;
2205 qbool server_can_auth =
true;
2207 int wantserver_aeslevel = 0;
2208 qbool wantserver_issigned =
false;
2215 dpsnprintf(warn_msg,
sizeof(warn_msg),
"ignoring challenge message from wrong server %s", peeraddressstring);
2221 wantserver_idfp[0] = 0;
2234 return (wantserverid >= 0) ?
Crypto_ClientError(data_out, len_out,
"Server tried an unauthenticated connection even though a host key is present") :
2256 vlen_blind_id_ptr = data_in;
2257 len_blind_id_ptr =
v;
2269 if(!vlen_blind_id_ptr)
2270 return (wantserverid >= 0) ?
Crypto_ClientError(data_out, len_out,
"Server tried an unauthenticated connection even though authentication is required") :
2274 data_in = vlen_blind_id_ptr;
2275 len_in = len_blind_id_ptr;
2288 if(!server_can_auth)
2290 server_can_auth =
false;
2304 if(wantserverid < 0 ||
i == wantserverid)
2312 if(wantserverid >= 0 && serverid < 0)
2313 return Crypto_ClientError(data_out, len_out,
"Server CA does not match stored host key, refusing to connect");
2315 if(serverid >= 0 || clientid >= 0)
2319 CDATA->s = serverid;
2320 CDATA->c = clientid;
2321 memset(crypto->
dhkey, 0,
sizeof(crypto->
dhkey));
2327 memcpy(
CDATA->wantserver_idfp, wantserver_idfp,
sizeof(crypto->
server_idfp));
2328 CDATA->wantserver_issigned = wantserver_issigned;
2330 if(
CDATA->wantserver_idfp[0])
2335 if(wantserver_aeslevel >= 3)
2336 return Crypto_ClientError(data_out, len_out,
"This server requires encryption to be not required (crypto_aeslevel <= 2)");
2337 CDATA->wantserver_aes =
false;
2340 CDATA->wantserver_aes = (wantserver_aeslevel >= 2);
2343 CDATA->wantserver_aes = (wantserver_aeslevel >= 1);
2346 if(wantserver_aeslevel <= 0)
2347 return Crypto_ClientError(data_out, len_out,
"This server requires encryption to be supported (crypto_aeslevel >= 1, and d0_rijndael library must be present)");
2348 CDATA->wantserver_aes =
true;
2380 CDATA->next_step = 1;
2381 *len_out = data_out_p - data_out;
2401 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_start failed");
2403 CDATA->next_step = 5;
2404 data_out_p += *len_out;
2405 *len_out = data_out_p - data_out;
2411 if(wantserver_idfp[0])
2412 if(wantserver_aeslevel >= 3)
2413 return Crypto_ClientError(data_out, len_out,
"Server insists on encryption, but neither can authenticate to the other");
2428 dpsnprintf(warn_msg,
sizeof(warn_msg),
"ignoring d0pk\\ message from wrong server %s", peeraddressstring);
2432 id = (
InfoString_GetValue(
string + 4,
"id", infostringvalue,
sizeof(infostringvalue)) ? atoi(infostringvalue) : -1);
2433 cnt = (
InfoString_GetValue(
string + 4,
"cnt", infostringvalue,
sizeof(infostringvalue)) ? infostringvalue :
NULL);
2440 if(!strcmp(cnt,
"1"))
2443 if(
CDATA->cdata_id !=
id)
2445 if(
CDATA->next_step != 1)
2451 aes = atoi(infostringvalue);
2456 if(
CDATA->wantserver_idfp[0])
2457 if(!aes &&
CDATA->wantserver_aes)
2460 return Crypto_ClientError(data_out, len_out,
"Stored host key requires encryption, but server did not enable encryption");
2465 return Crypto_ClientError(data_out, len_out,
"Server insists on encryption too hard");
2470 return Crypto_ClientError(data_out, len_out,
"Server insists on plaintext too hard");
2474 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\2\\id\\%d",
CDATA->cdata_id));
2478 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_challenge failed");
2480 CDATA->next_step = 3;
2481 data_out_p += *len_out;
2482 *len_out = data_out_p - data_out;
2485 else if(!strcmp(cnt,
"3"))
2487 static char msgbuf[32];
2488 size_t msgbuflen =
sizeof(msgbuf);
2492 if(
CDATA->cdata_id !=
id)
2494 if(
CDATA->next_step != 3)
2502 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_verify failed (server authentication error)");
2506 if (!status &&
CDATA->wantserver_issigned)
2509 return Crypto_ClientError(data_out, len_out,
"Stored host key requires a valid signature, but server did not provide any");
2518 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_fingerprint64_public_id failed");
2520 if(
CDATA->wantserver_idfp[0])
2524 return Crypto_ClientError(data_out, len_out,
"Server ID does not match stored host key, refusing to connect");
2530 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_sessionkey_public_id failed");
2539 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\4\\id\\%d",
CDATA->cdata_id));
2548 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_start failed");
2550 CDATA->next_step = 5;
2551 data_out_p += *len_out;
2552 *len_out = data_out_p - data_out;
2559 CDATA->next_step = 0;
2561 PutWithNul(&data_out_p, len_out,
"challenge ");
2562 *len_out = data_out_p - data_out;
2567 else if(!strcmp(cnt,
"5"))
2574 if(
CDATA->cdata_id !=
id)
2576 if(
CDATA->next_step != 5)
2584 aes = atoi(infostringvalue);
2587 if(
CDATA->wantserver_idfp[0])
2588 if(!aes &&
CDATA->wantserver_aes)
2591 return Crypto_ClientError(data_out, len_out,
"Stored host key requires encryption, but server did not enable encryption");
2596 return Crypto_ClientError(data_out, len_out,
"Server insists on encryption too hard");
2601 return Crypto_ClientError(data_out, len_out,
"Server insists on plaintext too hard");
2606 PutWithNul(&data_out_p, len_out,
va(vabuf,
sizeof(vabuf),
"d0pk\\cnt\\6\\id\\%d",
CDATA->cdata_id));
2610 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_authenticate_with_private_id_response failed");
2616 return Crypto_ClientError(data_out, len_out,
"d0_blind_id_sessionkey_public_id failed");
2623 CDATA->next_step = 0;
2624 data_out_p += *len_out;
2625 *len_out = data_out_p - data_out;
void Cmd_AddCommand(unsigned flags, const char *cmd_name, xcommand_t function, const char *description)
called by the init functions of other parts of the program to register commands and functions to call...
#define CF_SERVER
cvar/command that only the server can change/execute
static int Cmd_Argc(cmd_state_t *cmd)
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
#define CF_CLIENT
cvar/command that only the client can change/execute
#define CF_ARCHIVE
cvar should have its set value saved to config.cfg and persist across sessions
unsigned short CRC_Block(const unsigned char *data, size_t size)
size_t InfoString_GetValue(const char *buffer, const char *key, char *value, size_t valuesize)
Returns the number of bytes written to *value excluding the \0 terminator.
int BuffLittleLong(const unsigned char *buffer)
Extract a little endian 32bit int from the given buffer.
int BuffBigLong(const unsigned char *buffer)
Extract a big endian 32bit int from the given buffer.
char * va(char *buf, size_t buflen, const char *format,...)
void Com_HexDumpToConsole(const unsigned char *data, int size)
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen)
#define dp_strlcat(dst, src, dsize)
#define dp_strlcpy(dst, src, dsize)
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
#define MAX_CRYPTOCONNECTS
static void Crypto_d0_free(void *p)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_sign_with_private_id_sign)(d0_blind_id_t *ctx, D0_BOOL is_first, D0_BOOL send_modulus, const char *message, size_t msglen, char *outbuf, size_t *outbuflen)
crypto_t * Crypto_ServerGetInstance(lhnetaddress_t *peeraddress)
#define D0_WARN_UNUSED_RESULT
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_verify_public_id)(const d0_blind_id_t *ctx, D0_BOOL *status)
static char challenge_append[1400]
int d0_lockmutex_t(void *)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_read_public_key)(d0_blind_id_t *ctx, const char *inbuf, size_t inbuflen)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_generate_private_id_request)(d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen)
static double crypto_servercpu_accumulator
void Crypto_LoadKeys(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_authenticate_with_private_id_challenge)(d0_blind_id_t *ctx, D0_BOOL is_first, D0_BOOL recv_modulus, const char *inbuf, size_t inbuflen, char *outbuf, size_t *outbuflen, D0_BOOL *status)
static void Crypto_ClearHostKeys(void)
void d0_destroymutex_t(void *)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_read_private_id)(d0_blind_id_t *ctx, const char *inbuf, size_t inbuflen)
int crypto_keyfp_recommended_length
int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress, const char *peeraddressstring)
static void Crypto_d0_destroymutex(void *m)
void Crypto_Init_Commands(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_fingerprint64_public_key)(const d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen)
static void Crypto_Reload_f(cmd_state_t *cmd)
void * d0_createmutex_t(void)
const void * Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
static D0_EXPORT D0_WARN_UNUSED_RESULT d0_blind_id_t *(* qd0_blind_id_new)(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_write_private_id)(const d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen)
size_t Crypto_SignData(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size)
#define PROTOCOL_D0_BLIND_ID
static dllfunction_t d0_blind_id_funcs[]
D0_EXPORT int(* qd0_rijndael_setup_encrypt)(unsigned long *rk, const unsigned char *key, int keybits)
static int Crypto_d0_lockmutex(void *m)
static mempool_t * cryptomempool
static int Crypto_ServerError(char *data_out, size_t *len_out, const char *msg, const char *msg_client)
static double crypto_servercpu_lastrealtime
static char pubkeys_priv_fp64[MAX_PUBKEYS][FP64_SIZE+1]
qbool Crypto_RetrieveHostKey(lhnetaddress_t *peeraddress, int *keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, int *aeslevel, qbool *issigned)
static void Crypto_InitHostKeys(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_sessionkey_public_id)(const d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen)
int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, qbool *issigned)
static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress)
static qbool PutWithNul(char **data, size_t *len, const char *str)
D0_EXPORT int(* qd0_rijndael_setup_decrypt)(unsigned long *rk, const unsigned char *key, int keybits)
static d0_blind_id_t * Crypto_ReadPublicKey(char *buf, size_t len)
static size_t challenge_append_length
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_verify_private_id)(const d0_blind_id_t *ctx)
const void * Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len)
cvar_t crypto_servercpupercent
void sha256(unsigned char *out, const unsigned char *in, int n)
static D0_EXPORT void(* qd0_blind_id_util_sha256)(char *out, const char *in, size_t n)
static dllhandle_t d0_blind_id_dll
static char crypto_idstring_buf[512]
static void seacpy(unsigned char *key, const unsigned char *iv, unsigned char *dst, const unsigned char *src, size_t len)
static D0_EXPORT void(* qd0_blind_id_setmallocfuncs)(d0_malloc_t *m, d0_free_t *f)
static D0_EXPORT void(* qd0_blind_id_free)(d0_blind_id_t *a)
static size_t Crypto_LoadFile(const char *path, char *buf, size_t nmax, qbool inuserdir)
static qbool Crypto_OpenLibrary(void)
static D0_EXPORT void(* qd0_blind_id_SHUTDOWN)(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_INITIALIZE)(void)
static void Crypto_BuildIdString(void)
cvar_t crypto_servercpumaxtime
static size_t Crypto_UnParsePack(char *buf, size_t len, unsigned long header, const char *const *lumps, const size_t *lumpsize, size_t nlumps)
static int Crypto_ClientError(char *data_out, size_t *len_out, const char *msg)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_generate_private_id_start)(d0_blind_id_t *ctx)
D0_EXPORT void(* qd0_rijndael_encrypt)(const unsigned long *rk, int nrounds, const unsigned char plaintext[16], unsigned char ciphertext[16])
cvar_t crypto_servercpudebug
static int Crypto_SoftServerError(char *data_out, size_t *len_out, const char *msg)
static qbool pubkeys_havesig[MAX_PUBKEYS]
static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned char *buffer, void *cbdata)
static qbool pubkeys_havepriv[MAX_PUBKEYS]
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_fingerprint64_public_id)(const d0_blind_id_t *ctx, char *outbuf, size_t *outbuflen)
static const char * crypto_idstring
static void Crypto_HostKeys_f(cmd_state_t *cmd)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_authenticate_with_private_id_start)(d0_blind_id_t *ctx, D0_BOOL is_first, D0_BOOL send_modulus, const char *message, size_t msglen, char *outbuf, size_t *outbuflen)
static dllfunction_t d0_rijndael_funcs[]
static qbool Crypto_Rijndael_OpenLibrary(void)
static server_cryptoconnect_t cryptoconnects[MAX_CRYPTOCONNECTS]
void Crypto_Shutdown(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_sign_with_private_id_sign_detached)(d0_blind_id_t *ctx, D0_BOOL is_first, D0_BOOL send_modulus, const char *message, size_t msglen, char *outbuf, size_t *outbuflen)
static char pubkeys_fp64[MAX_PUBKEYS][FP64_SIZE+1]
static size_t Crypto_ParsePack(const char *buf, size_t len, unsigned long header, const char **lumps, size_t *lumpsize, size_t nlumps)
static void Crypto_Rijndael_CloseLibrary(void)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_read_private_id_modulus)(d0_blind_id_t *ctx, const char *inbuf, size_t inbuflen)
#define D0_RIJNDAEL_NROUNDS(keybits)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_authenticate_with_private_id_response)(d0_blind_id_t *ctx, const char *inbuf, size_t inbuflen, char *outbuf, size_t *outbuflen)
static void Crypto_StoreHostKey(lhnetaddress_t *peeraddress, const char *keystring, qbool complain)
struct d0_blind_id_s d0_blind_id_t
static unsigned long Crypto_LittleLong(const char *data)
static void Crypto_UnloadKeys(void)
static crypto_storedhostkey_t * crypto_storedhostkey_hashtable[CRYPTO_HOSTKEY_HASHSIZE]
static qbool Crypto_ClearHostKey(lhnetaddress_t *peeraddress)
static int Crypto_d0_unlockmutex(void *m)
int d0_unlockmutex_t(void *)
D0_EXPORT void(* qd0_rijndael_decrypt)(const unsigned long *rk, int nrounds, const unsigned char ciphertext[16], unsigned char plaintext[16])
static qbool Crypto_SavePubKeyTextFile(int i)
static dllhandle_t d0_rijndael_dll
static int Crypto_SoftClientError(char *data_out, size_t *len_out, const char *msg)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_copy)(d0_blind_id_t *ctx, const d0_blind_id_t *src)
D0_BOOL(* d0_fastreject_function)(const d0_blind_id_t *ctx, void *pass)
static void Crypto_CloseLibrary(void)
int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress)
static char keygen_buf[8192]
static d0_blind_id_t * pubkeys[MAX_PUBKEYS]
size_t Crypto_SignDataDetached(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_finish_private_id_request)(d0_blind_id_t *ctx, const char *inbuf, size_t inbuflen)
static void * Crypto_d0_malloc(size_t len)
static void Crypto_KeyGen_f(cmd_state_t *cmd)
static void Crypto_HostKey_Clear_f(cmd_state_t *cmd)
static void Crypto_Keys_f(cmd_state_t *cmd)
static void aescpy(unsigned char *key, const unsigned char *iv, unsigned char *dst, const unsigned char *src, size_t len)
const char * Crypto_GetInfoResponseDataString(void)
static crypto_t * Crypto_ServerFindInstance(lhnetaddress_t *peeraddress, qbool allow_create)
#define D0_RIJNDAEL_RKLENGTH(keybits)
static qbool Crypto_AddPrivateKey(d0_blind_id_t *pk, char *buf, size_t len)
cvar_t net_sourceaddresscheck
static void Crypto_UnLittleLong(char *data, unsigned long l)
static const char * GetUntilNul(const char **data, size_t *len)
static void * Crypto_d0_createmutex(void)
qbool Crypto_Available(void)
qbool Crypto_ServerAppendToChallenge(const char *data_in, size_t len_in, char *data_out, size_t *len_out, size_t maxlen_out)
static void Crypto_BuildChallengeAppend(void)
qbool Crypto_FinishInstance(crypto_t *out, crypto_t *crypto)
static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL(* qd0_blind_id_authenticate_with_private_id_verify)(d0_blind_id_t *ctx, const char *inbuf, size_t inbuflen, char *msg, size_t *msglen, D0_BOOL *status)
void * d0_malloc_t(size_t len)
static D0_EXPORT void(* qd0_blind_id_setmutexfuncs)(d0_createmutex_t *c, d0_destroymutex_t *d, d0_lockmutex_t *l, d0_unlockmutex_t *u)
void Cvar_RegisterVariable(cvar_t *variable)
registers a cvar that already has the name, string, and optionally the archive elements set.
fs_offset_t FS_Read(qfile_t *file, void *buffer, size_t buffersize)
fs_offset_t FS_Write(qfile_t *file, const void *data, size_t datasize)
qfile_t * FS_SysOpen(const char *filepath, const char *mode, qbool nonblocking)
static int(ZEXPORT *qz_inflate)(z_stream *strm
int FS_Close(qfile_t *file)
int FS_Printf(qfile_t *file, const char *format,...)
void FS_CreatePath(char *path)
char fs_basedir[MAX_OSPATH]
char fs_userdir[MAX_OSPATH]
GLsizeiptr const GLvoid * data
GLenum GLuint GLenum GLsizei const GLchar * buf
#define HMAC_SHA256_32BYTES(out, in, n, key, k)
void Host_LockSession(void)
int LHNETADDRESS_ToString(const lhnetaddress_t *vaddress, char *string, int stringbuffersize, int includeport)
Returns the number of bytes written to *string excluding the \0 terminator.
int LHNETADDRESS_FromString(lhnetaddress_t *vaddress, const char *string, int defaultport)
int LHNETADDRESS_Compare(const lhnetaddress_t *vaddress1, const lhnetaddress_t *vaddress2)
static lhnetaddresstype_t LHNETADDRESS_GetAddressType(const lhnetaddress_t *address)
qbool Curl_Begin_ToMemory(const char *URL, double maxspeed, unsigned char *buf, size_t bufsize, curl_callback_t callback, void *cbdata)
#define bound(min, num, max)
challenge_t challenges[MAX_CHALLENGES]
cvar_t developer_networking
#define CCREP_SERVER_INFO
#define CCREP_PLAYER_INFO
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
#define CRYPTO_HOSTKEY_HASHSIZE
number of hash buckets for accelerating host key lookups
#define SV_LockThreadMutex()
#define SV_UnlockThreadMutex()
double connect_nextsendtime
lhnetaddress_t connect_address
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
qbool wantserver_issigned
struct crypto_storedhostkey_s * next
char server_keyfp[FP64_SIZE+1]
char client_idfp[FP64_SIZE+1]
unsigned char dhkey[DHKEY_SIZE]
char client_keyfp[FP64_SIZE+1]
char server_idfp[FP64_SIZE+1]
double realtime
the accumulated mainloop time since application started (with filtering), without any slowmo or clamp...
qbool Sys_LoadDependency(const char **dllnames, dllhandle_t *handle, const dllfunction_t *fcts)
double Sys_DirtyTime(void)
void Sys_FreeLibrary(dllhandle_t *handle)
#define Thread_DestroyMutex(m)
qbool Thread_HasThreads(void)
#define Thread_CreateMutex()
#define Thread_LockMutex(m)
#define Thread_UnlockMutex(m)
#define Mem_FreePool(pool)
#define Mem_Alloc(pool, size)
#define Mem_AllocPool(name, flags, parent)