#include "quakedef.h"
#include "crypto.h"
#include "common.h"
+#include "thread.h"
#include "hmac.h"
#include "libcurl.h"
#define qd0_blind_id_util_sha256 d0_blind_id_util_sha256
#define qd0_blind_id_sign_with_private_id_sign d0_blind_id_sign_with_private_id_sign
#define qd0_blind_id_sign_with_private_id_sign_detached d0_blind_id_sign_with_private_id_sign_detached
+#define qd0_blind_id_setmallocfuncs d0_blind_id_setmallocfuncs
+#define qd0_blind_id_setmutexfuncs d0_blind_id_setmutexfuncs
#else
#endif
#define D0_BOOL int
+typedef void *(d0_malloc_t)(size_t len);
+typedef void (d0_free_t)(void *p);
+typedef void *(d0_createmutex_t)(void);
+typedef void (d0_destroymutex_t)(void *);
+typedef int (d0_lockmutex_t)(void *); // zero on success
+typedef int (d0_unlockmutex_t)(void *); // zero on success
+
typedef struct d0_blind_id_s d0_blind_id_t;
typedef D0_BOOL (*d0_fastreject_function) (const d0_blind_id_t *ctx, void *pass);
static D0_EXPORT D0_WARN_UNUSED_RESULT d0_blind_id_t *(*qd0_blind_id_new) (void);
static D0_EXPORT void (*qd0_blind_id_util_sha256) (char *out, const char *in, size_t n);
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);
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 D0_EXPORT void (*qd0_blind_id_setmallocfuncs)(d0_malloc_t *m, d0_free_t *f);
+static D0_EXPORT void (*qd0_blind_id_setmutexfuncs)(d0_createmutex_t *c, d0_destroymutex_t *d, d0_lockmutex_t *l, d0_unlockmutex_t *u);
static dllfunction_t d0_blind_id_funcs[] =
{
{"d0_blind_id_new", (void **) &qd0_blind_id_new},
{"d0_blind_id_util_sha256", (void **) &qd0_blind_id_util_sha256},
{"d0_blind_id_sign_with_private_id_sign", (void **) &qd0_blind_id_sign_with_private_id_sign},
{"d0_blind_id_sign_with_private_id_sign_detached", (void **) &qd0_blind_id_sign_with_private_id_sign_detached},
+ {"d0_blind_id_setmallocfuncs", (void **) &qd0_blind_id_setmallocfuncs},
+ {"d0_blind_id_setmutexfuncs", (void **) &qd0_blind_id_setmutexfuncs},
{NULL, NULL}
};
// end of d0_blind_id interface
qd0_blind_id_util_sha256((char *) out, (const char *) in, n);
}
-static size_t Crypto_LoadFile(const char *path, char *buf, size_t nmax)
+static size_t Crypto_LoadFile(const char *path, char *buf, size_t nmax, qboolean inuserdir)
{
+ char vabuf[1024];
qfile_t *f = NULL;
fs_offset_t n;
- if(*fs_userdir)
- f = FS_SysOpen(va("%s%s", fs_userdir, path), "rb", false);
- if(!f)
- f = FS_SysOpen(va("%s%s", fs_basedir, path), "rb", false);
+ if(inuserdir)
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%s%s", *fs_userdir ? fs_userdir : fs_basedir, path), "rb", false);
+ else
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%s%s", fs_basedir, path), "rb", false);
if(!f)
return 0;
n = FS_Read(f, buf, nmax);
challenge_append_length = p - challenge_append;
}
-static void Crypto_LoadKeys(void)
+void Crypto_LoadKeys(void)
{
char buf[8192];
size_t len, len2;
int i;
+ char vabuf[1024];
+
+ if(!d0_blind_id_dll) // don't if we can't
+ return;
+
+ if(crypto_idstring) // already loaded? then not
+ return;
+
+ Host_LockSession(); // we use the session ID here
// load keys
// note: we are just a CLIENT
memset(pubkeys_fp64[i], 0, sizeof(pubkeys_fp64[i]));
memset(pubkeys_priv_fp64[i], 0, sizeof(pubkeys_fp64[i]));
pubkeys_havepriv[i] = false;
- len = Crypto_LoadFile(va("key_%d.d0pk", i), buf, sizeof(buf));
+ len = Crypto_LoadFile(va(vabuf, sizeof(vabuf), "key_%d.d0pk", i), buf, sizeof(buf), false);
if((pubkeys[i] = Crypto_ReadPublicKey(buf, len)))
{
len2 = FP64_SIZE;
if(qd0_blind_id_fingerprint64_public_key(pubkeys[i], pubkeys_fp64[i], &len2)) // keeps final NUL
{
Con_Printf("Loaded public key key_%d.d0pk (fingerprint: %s)\n", i, pubkeys_fp64[i]);
- len = Crypto_LoadFile(va("key_%d.d0si", i), buf, sizeof(buf));
+ len = Crypto_LoadFile(va(vabuf, sizeof(vabuf), "key_%d.d0si%s", i, sessionid.string), buf, sizeof(buf), true);
if(len)
{
if(Crypto_AddPrivateKey(pubkeys[i], buf, len))
len2 = FP64_SIZE;
if(qd0_blind_id_fingerprint64_public_id(pubkeys[i], pubkeys_priv_fp64[i], &len2)) // keeps final NUL
{
- Con_Printf("Loaded private ID key_%d.d0si for key_%d.d0pk (fingerprint: %s)\n", i, i, pubkeys_priv_fp64[i]);
+ Con_Printf("Loaded private ID key_%d.d0si%s for key_%d.d0pk (public key fingerprint: %s)\n", i, sessionid.string, i, pubkeys_priv_fp64[i]);
pubkeys_havepriv[i] = true;
- strlcat(crypto_idstring_buf, va(" %s@%s", pubkeys_priv_fp64[i], pubkeys_fp64[i]), sizeof(crypto_idstring_buf));
+ strlcat(crypto_idstring_buf, va(vabuf, sizeof(vabuf), " %s@%s", pubkeys_priv_fp64[i], pubkeys_fp64[i]), sizeof(crypto_idstring_buf));
}
else
{
static void Crypto_UnloadKeys(void)
{
int i;
+
keygen_i = -1;
for(i = 0; i < MAX_PUBKEYS; ++i)
{
crypto_idstring = NULL;
}
+static mempool_t *cryptomempool;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+static void *Crypto_d0_malloc(size_t len)
+{
+ return Mem_Alloc(cryptomempool, len);
+}
+
+static void Crypto_d0_free(void *p)
+{
+ Mem_Free(p);
+}
+
+static void *Crypto_d0_createmutex(void)
+{
+ return Thread_CreateMutex();
+}
+
+static void Crypto_d0_destroymutex(void *m)
+{
+ Thread_DestroyMutex(m);
+}
+
+static int Crypto_d0_lockmutex(void *m)
+{
+ return Thread_LockMutex(m);
+}
+
+static int Crypto_d0_unlockmutex(void *m)
+{
+ return Thread_UnlockMutex(m);
+}
+#ifdef __cplusplus
+}
+#endif
+
void Crypto_Shutdown(void)
{
crypto_t *crypto;
Crypto_CloseLibrary();
}
+
+ Mem_FreePool(&cryptomempool);
}
void Crypto_Init(void)
{
+ cryptomempool = Mem_AllocPool("crypto", 0, NULL);
+
if(!Crypto_OpenLibrary())
return;
+ qd0_blind_id_setmallocfuncs(Crypto_d0_malloc, Crypto_d0_free);
+ if (Thread_HasThreads())
+ qd0_blind_id_setmutexfuncs(Crypto_d0_createmutex, Crypto_d0_destroymutex, Crypto_d0_lockmutex, Crypto_d0_unlockmutex);
+
if(!qd0_blind_id_INITIALIZE())
{
Crypto_Rijndael_CloseLibrary();
Crypto_Rijndael_OpenLibrary(); // if this fails, it's uncritical
Crypto_InitHostKeys();
- Crypto_LoadKeys();
}
// end
+qboolean Crypto_Available(void)
+{
+ if(!d0_blind_id_dll)
+ return false;
+ return true;
+}
+
// keygen code
static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned char *buffer, void *cbdata)
{
d0_blind_id_t *ctx, *ctx2;
D0_BOOL status;
size_t len2;
+ char vabuf[1024];
+
+ SV_LockThreadMutex();
if(!d0_blind_id_dll)
{
Con_Print("libd0_blind_id DLL not found, this command is inactive.\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
{
Con_Printf("overflow of keygen_i\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(keygen_i < 0)
{
Con_Printf("Unexpected response from keygen server:\n");
Com_HexDumpToConsole(buffer, length_received);
+ SV_UnlockThreadMutex();
return;
}
if(!Crypto_ParsePack((const char *) buffer, length_received, FOURCC_D0IR, p, l, 1))
Com_HexDumpToConsole(buffer, length_received);
}
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!qd0_blind_id_finish_private_id_request(pubkeys[keygen_i], p[0], l[0]))
{
Con_Printf("d0_blind_id_finish_private_id_request failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
{
Con_Printf("d0_blind_id_new failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
ctx2 = qd0_blind_id_new();
Con_Printf("d0_blind_id_new failed\n");
qd0_blind_id_free(ctx);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!qd0_blind_id_copy(ctx, pubkeys[keygen_i]))
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!qd0_blind_id_copy(ctx2, pubkeys[keygen_i]))
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
bufsize = sizeof(buf);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2size = sizeof(buf2);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
bufsize = sizeof(buf);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2size = sizeof(buf2);
qd0_blind_id_free(ctx);
qd0_blind_id_free(ctx2);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
qd0_blind_id_free(ctx);
len2 = FP64_SIZE;
if(qd0_blind_id_fingerprint64_public_id(pubkeys[keygen_i], pubkeys_priv_fp64[keygen_i], &len2)) // keeps final NUL
{
- Con_Printf("Received private ID key_%d.d0pk (fingerprint: %s)\n", keygen_i, pubkeys_priv_fp64[keygen_i]);
+ Con_Printf("Received private ID key_%d.d0pk (public key fingerprint: %s)\n", keygen_i, pubkeys_priv_fp64[keygen_i]);
pubkeys_havepriv[keygen_i] = true;
- strlcat(crypto_idstring_buf, va(" %s@%s", pubkeys_priv_fp64[keygen_i], pubkeys_fp64[keygen_i]), sizeof(crypto_idstring_buf));
+ strlcat(crypto_idstring_buf, va(vabuf, sizeof(vabuf), " %s@%s", pubkeys_priv_fp64[keygen_i], pubkeys_fp64[keygen_i]), sizeof(crypto_idstring_buf));
crypto_idstring = crypto_idstring_buf;
Crypto_BuildChallengeAppend();
}
{
Con_Printf("d0_blind_id_write_private_id failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!(buf2size = Crypto_UnParsePack(buf2, sizeof(buf2), FOURCC_D0SI, p, l, 1)))
{
Con_Printf("Crypto_UnParsePack failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
- if(*fs_userdir)
- {
- FS_CreatePath(va("%skey_%d.d0si", fs_userdir, keygen_i));
- f = FS_SysOpen(va("%skey_%d.d0si", fs_userdir, keygen_i), "wb", false);
- }
- if(!f)
- {
- FS_CreatePath(va("%skey_%d.d0si", fs_basedir, keygen_i));
- f = FS_SysOpen(va("%skey_%d.d0si", fs_basedir, keygen_i), "wb", false);
- }
+ FS_CreatePath(va(vabuf, sizeof(vabuf), "%skey_%d.d0si%s", *fs_userdir ? fs_userdir : fs_basedir, keygen_i, sessionid.string));
+ f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%skey_%d.d0si%s", *fs_userdir ? fs_userdir : fs_basedir, keygen_i, sessionid.string), "wb", false);
if(!f)
{
- Con_Printf("Cannot open key_%d.d0si\n", keygen_i);
+ Con_Printf("Cannot open key_%d.d0si%s\n", keygen_i, sessionid.string);
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
FS_Write(f, buf2, buf2size);
FS_Close(f);
- Con_Printf("Saved to key_%d.d0si\n", keygen_i);
+ Con_Printf("Saved to key_%d.d0si%s\n", keygen_i, sessionid.string);
keygen_i = -1;
+ SV_UnlockThreadMutex();
}
static void Crypto_KeyGen_f(void)
Con_Printf("usage:\n%s id url\n", Cmd_Argv(0));
return;
}
+ SV_LockThreadMutex();
+ Crypto_LoadKeys();
i = atoi(Cmd_Argv(1));
if(!pubkeys[i])
{
Con_Printf("there is no public key %d\n", i);
+ SV_UnlockThreadMutex();
return;
}
if(pubkeys_havepriv[i])
{
Con_Printf("there is already a private key for %d\n", i);
+ SV_UnlockThreadMutex();
return;
}
if(keygen_i >= 0)
{
Con_Printf("there is already a keygen run on the way\n");
+ SV_UnlockThreadMutex();
return;
}
keygen_i = i;
{
Con_Printf("d0_blind_id_start failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
p[0] = buf;
{
Con_Printf("d0_blind_id_generate_private_id_request failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2pos = strlen(Cmd_Argv(2));
{
Con_Printf("Crypto_UnParsePack failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
if(!(buf2l = base64_encode((unsigned char *) (buf2 + buf2pos), buf2l, sizeof(buf2) - buf2pos - 1)))
{
Con_Printf("base64_encode failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
buf2l += buf2pos;
{
Con_Printf("curl failed\n");
keygen_i = -1;
+ SV_UnlockThreadMutex();
return;
}
Con_Printf("key generation in progress\n");
+ SV_UnlockThreadMutex();
}
// end
{
Con_Printf("%2d: public key key_%d.d0pk (fingerprint: %s)\n", i, i, pubkeys_fp64[i]);
if(pubkeys_havepriv[i])
- Con_Printf(" private key key_%d.d0si (fingerprint: %s)\n", i, pubkeys_priv_fp64[i]);
+ Con_Printf(" private ID key_%d.d0si%s (public key fingerprint: %s)\n", i, sessionid.string, pubkeys_priv_fp64[i]);
}
}
}
}
}
+// NOTE: we MUST avoid the following begins of the packet:
+// 1. 0xFF, 0xFF, 0xFF, 0xFF
+// 2. 0x80, 0x00, length/256, length%256
+// this luckily does NOT affect AES mode, where the first byte always is in the range from 0x00 to 0x0F
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)
{
unsigned char h[32];
+ int i;
if(crypto->authenticated)
{
if(crypto->use_aes)
*len_dst = len_src + 16;
memcpy(data_dst, h, 16);
memcpy(((unsigned char *) data_dst) + 16, (unsigned char *) data_src, len_src);
+
+ // handle the "avoid" conditions:
+ i = BuffBigLong((unsigned char *) data_dst);
+ if(
+ (i == (int)0xFFFFFFFF) // avoid QW control packet
+ ||
+ (i == (int)0x80000000 + (int)*len_dst) // avoid NQ control packet
+ )
+ *(unsigned char *)data_dst ^= 0x80; // this will ALWAYS fix it
}
return data_dst;
}
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)
{
unsigned char h[32];
+ int i;
+
+ // silently handle non-crypto packets
+ i = BuffBigLong((unsigned char *) data_src);
+ if(
+ (i == (int)0xFFFFFFFF) // avoid QW control packet
+ ||
+ (i == (int)0x80000000 + (int)len_src) // avoid NQ control packet
+ )
+ return NULL;
+
if(crypto->authenticated)
{
if(crypto->use_aes)
Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
return NULL;
}
+
if(memcmp((const unsigned char *) data_src, h, 16)) // ignore first byte, used for length
{
- Con_Printf("HMAC mismatch\n");
- Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
- return NULL;
+ // undo the "avoid conditions"
+ if(
+ (i == (int)0x7FFFFFFF) // avoided QW control packet
+ ||
+ (i == (int)0x00000000 + (int)len_src) // avoided NQ control packet
+ )
+ {
+ // do the avoidance on the hash too
+ h[0] ^= 0x80;
+ if(memcmp((const unsigned char *) data_src, h, 16)) // ignore first byte, used for length
+ {
+ Con_Printf("HMAC mismatch\n");
+ Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
+ return NULL;
+ }
+ }
+ else
+ {
+ Con_Printf("HMAC mismatch\n");
+ Com_HexDumpToConsole((const unsigned char *) data_src, len_src);
+ return NULL;
+ }
}
return ((const unsigned char *) data_src) + 16; // no need to copy, so data_dst is not used
}
int aeslevel;
D0_BOOL aes;
D0_BOOL status;
+ char infostringvalue[MAX_INPUTLINE];
+ char vabuf[1024];
if(!d0_blind_id_dll)
return CRYPTO_NOMATCH; // no support
int i;
// sorry, we have to verify the challenge here to not reflect network spam
- if (!(s = SearchInfostring(string + 4, "challenge")))
+ if (!(s = InfoString_GetValue(string + 4, "challenge", infostringvalue, sizeof(infostringvalue))))
return CRYPTO_NOMATCH; // will be later accepted if encryption was set up
// validate the challenge
for (i = 0;i < MAX_CHALLENGES;i++)
const char *cnt, *s, *p;
int id;
int clientid = -1, serverid = -1;
- cnt = SearchInfostring(string + 4, "id");
+ cnt = InfoString_GetValue(string + 4, "id", infostringvalue, sizeof(infostringvalue));
id = (cnt ? atoi(cnt) : -1);
- cnt = SearchInfostring(string + 4, "cnt");
+ cnt = InfoString_GetValue(string + 4, "cnt", infostringvalue, sizeof(infostringvalue));
if(!cnt)
return CRYPTO_DISCARD; // pre-challenge: rather be silent
GetUntilNul(&data_in, &len_in);
if(!strcmp(cnt, "0"))
{
int i;
- if (!(s = SearchInfostring(string + 4, "challenge")))
+ if (!(s = InfoString_GetValue(string + 4, "challenge", infostringvalue, sizeof(infostringvalue))))
return CRYPTO_DISCARD; // pre-challenge: rather be silent
// validate the challenge
for (i = 0;i < MAX_CHALLENGES;i++)
if (i == MAX_CHALLENGES) // challenge mismatch is silent
return CRYPTO_DISCARD; // pre-challenge: rather be silent
- if (!(s = SearchInfostring(string + 4, "aeslevel")))
+ if (!(s = InfoString_GetValue(string + 4, "aeslevel", infostringvalue, sizeof(infostringvalue))))
aeslevel = 0; // not supported
else
aeslevel = bound(0, atoi(s), 3);
CLEAR_CDATA;
return Crypto_ServerError(data_out, len_out, "d0_blind_id_copy failed", "Internal error");
}
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\1\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\1\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
if(!qd0_blind_id_authenticate_with_private_id_start(CDATA->id, true, false, "XONOTIC", 8, data_out_p, len_out)) // len_out receives used size by this op
{
CLEAR_CDATA;
CLEAR_CDATA;
return Crypto_ServerError(data_out, len_out, "d0_blind_id_copy failed", "Internal error");
}
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\5\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\5\\id\\%d\\aes\\%d", CDATA->cdata_id, crypto->use_aes));
if(!qd0_blind_id_authenticate_with_private_id_challenge(CDATA->id, true, false, data_in, len_in, data_out_p, len_out, &status))
{
CLEAR_CDATA;
return CRYPTO_NOMATCH; // pre-challenge, rather be silent
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 2)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\3\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\3\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_response(CDATA->id, data_in, len_in, data_out_p, len_out))
{
CLEAR_CDATA;
return CRYPTO_NOMATCH; // pre-challenge, rather be silent
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 4)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\5\\id\\%d", CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\5\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_challenge(CDATA->id, true, false, data_in, len_in, data_out_p, len_out, &status))
{
CLEAR_CDATA;
return CRYPTO_NOMATCH; // pre-challenge, rather be silent
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 6)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
if(!qd0_blind_id_authenticate_with_private_id_verify(CDATA->id, data_in, len_in, msgbuf, &msgbuflen, &status))
{
const char *cnt;
qboolean do_time = false;
qboolean do_reject = false;
+ char infostringvalue[MAX_INPUTLINE];
if(crypto_servercpupercent.value > 0 || crypto_servercpumaxtime.value > 0)
if(len_in > 5 && !memcmp(data_in, "d0pk\\", 5))
{
do_time = true;
- cnt = SearchInfostring(data_in + 4, "cnt");
+ cnt = InfoString_GetValue(data_in + 4, "cnt", infostringvalue, sizeof(infostringvalue));
if(cnt)
if(!strcmp(cnt, "0"))
do_reject = true;
*len_out = 0;
return CRYPTO_DISCARD;
}
- t = Sys_DoubleTime();
+ t = Sys_DirtyTime();
}
ret = Crypto_ServerParsePacket_Internal(data_in, len_in, data_out, len_out, peeraddress);
if(do_time)
{
- t = Sys_DoubleTime() - t;
+ t = Sys_DirtyTime() - t;if (t < 0.0) t = 0.0; // dirtytime can step backwards
if(crypto_servercpudebug.integer)
Con_Printf("crypto: accumulator was %.1f ms, used %.1f ms for crypto, ", crypto_servercpu_accumulator * 1000, t * 1000);
crypto_servercpu_accumulator -= t;
D0_BOOL aes;
char *data_out_p = data_out;
D0_BOOL status;
+ char infostringvalue[MAX_INPUTLINE];
+ char vabuf[1024];
if(!d0_blind_id_dll)
return CRYPTO_NOMATCH; // no support
}
else if (len_in >= 13 && !memcmp(string, "infoResponse\x0A", 13))
{
- s = SearchInfostring(string + 13, "d0_blind_id");
+ s = InfoString_GetValue(string + 13, "d0_blind_id", infostringvalue, sizeof(infostringvalue));
if(s)
Crypto_StoreHostKey(peeraddress, s, true);
return CRYPTO_NOMATCH;
save = *p;
* (char *) p = 0; // cut off the string there
}
- s = SearchInfostring(string + 15, "d0_blind_id");
+ s = InfoString_GetValue(string + 15, "d0_blind_id", infostringvalue, sizeof(infostringvalue));
if(s)
Crypto_StoreHostKey(peeraddress, s, true);
if(p)
// build outgoing message
// append regular stuff
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\0\\id\\%d\\aeslevel\\%d\\challenge\\%s", CDATA->cdata_id, d0_rijndael_dll ? crypto_aeslevel.integer : 0, challenge));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\0\\id\\%d\\aeslevel\\%d\\challenge\\%s", CDATA->cdata_id, d0_rijndael_dll ? crypto_aeslevel.integer : 0, challenge));
PutWithNul(&data_out_p, len_out, serverid >= 0 ? pubkeys_fp64[serverid] : "");
PutWithNul(&data_out_p, len_out, clientid >= 0 ? pubkeys_fp64[clientid] : "");
{
const char *cnt;
int id;
- cnt = SearchInfostring(string + 4, "id");
+ cnt = InfoString_GetValue(string + 4, "id", infostringvalue, sizeof(infostringvalue));
id = (cnt ? atoi(cnt) : -1);
- cnt = SearchInfostring(string + 4, "cnt");
+ cnt = InfoString_GetValue(string + 4, "cnt", infostringvalue, sizeof(infostringvalue));
if(!cnt)
return Crypto_ClientError(data_out, len_out, "d0pk\\ message without cnt");
GetUntilNul(&data_in, &len_in);
{
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 1)
- return Crypto_SoftClientError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftClientError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
cls.connect_nextsendtime = max(cls.connect_nextsendtime, realtime + 1); // prevent "hammering"
- if((s = SearchInfostring(string + 4, "aes")))
+ if((s = InfoString_GetValue(string + 4, "aes", infostringvalue, sizeof(infostringvalue))))
aes = atoi(s);
else
aes = false;
}
crypto->use_aes = aes != 0;
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\2\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\2\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_challenge(CDATA->id, true, false, data_in, len_in, data_out_p, len_out, &status))
{
CLEAR_CDATA;
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 3)
- return Crypto_SoftClientError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftClientError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
cls.connect_nextsendtime = max(cls.connect_nextsendtime, realtime + 1); // prevent "hammering"
}
// cache the server key
- Crypto_StoreHostKey(&cls.connect_address, va("%d %s@%s", crypto->use_aes ? 1 : 0, crypto->server_idfp, pubkeys_fp64[CDATA->s]), false);
+ Crypto_StoreHostKey(&cls.connect_address, va(vabuf, sizeof(vabuf), "%d %s@%s", crypto->use_aes ? 1 : 0, crypto->server_idfp, pubkeys_fp64[CDATA->s]), false);
if(CDATA->c >= 0)
{
// client will auth next
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\4\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\4\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_copy(CDATA->id, pubkeys[CDATA->c]))
{
CLEAR_CDATA;
if(id >= 0)
if(CDATA->cdata_id != id)
- return Crypto_SoftServerError(data_out, len_out, va("Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
+ return Crypto_SoftServerError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\id\\%d when expecting %d", id, CDATA->cdata_id));
if(CDATA->next_step != 5)
- return Crypto_SoftClientError(data_out, len_out, va("Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
+ return Crypto_SoftClientError(data_out, len_out, va(vabuf, sizeof(vabuf), "Got d0pk\\cnt\\%s when expecting %d", cnt, CDATA->next_step));
cls.connect_nextsendtime = max(cls.connect_nextsendtime, realtime + 1); // prevent "hammering"
if(CDATA->s < 0) // only if server didn't auth
{
- if((s = SearchInfostring(string + 4, "aes")))
+ if((s = InfoString_GetValue(string + 4, "aes", infostringvalue, sizeof(infostringvalue))))
aes = atoi(s);
else
aes = false;
crypto->use_aes = aes != 0;
}
- PutWithNul(&data_out_p, len_out, va("d0pk\\cnt\\6\\id\\%d", CDATA->cdata_id));
+ PutWithNul(&data_out_p, len_out, va(vabuf, sizeof(vabuf), "d0pk\\cnt\\6\\id\\%d", CDATA->cdata_id));
if(!qd0_blind_id_authenticate_with_private_id_response(CDATA->id, data_in, len_in, data_out_p, len_out))
{
CLEAR_CDATA;