X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=crypto.c;h=c0f195eca32136802b308981a6130e3bca082ac4;hb=45bd9ec32061806e659961e6a8a3b133a1352b5d;hp=4b9d3976ab29fbb9851b118f79dffc63405c9f3e;hpb=7b8dccf0a882a1e9cf7856b7cf3d706a55513917;p=xonotic%2Fdarkplaces.git diff --git a/crypto.c b/crypto.c index 4b9d3976..c0f195ec 100644 --- a/crypto.c +++ b/crypto.c @@ -2,6 +2,7 @@ #include "quakedef.h" #include "crypto.h" #include "common.h" +#include "thread.h" #include "hmac.h" #include "libcurl.h" @@ -144,6 +145,10 @@ static size_t Crypto_UnParsePack(char *buf, size_t len, unsigned long header, co #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 +#define qd0_blind_id_verify_public_id d0_blind_id_verify_public_id +#define qd0_blind_id_verify_private_id d0_blind_id_verify_private_id #else @@ -156,6 +161,13 @@ static size_t Crypto_UnParsePack(char *buf, size_t len, unsigned long header, co #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); @@ -193,6 +205,10 @@ static D0_EXPORT void (*qd0_blind_id_SHUTDOWN) (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 D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL (*qd0_blind_id_verify_public_id)(const d0_blind_id_t *ctx, D0_BOOL *status); +static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL (*qd0_blind_id_verify_private_id)(const d0_blind_id_t *ctx); static dllfunction_t d0_blind_id_funcs[] = { {"d0_blind_id_new", (void **) &qd0_blind_id_new}, @@ -230,6 +246,10 @@ static dllfunction_t d0_blind_id_funcs[] = {"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}, + {"d0_blind_id_verify_public_id", (void **) &qd0_blind_id_verify_public_id}, + {"d0_blind_id_verify_private_id", (void **) &qd0_blind_id_verify_private_id}, {NULL, NULL} }; // end of d0_blind_id interface @@ -340,14 +360,15 @@ void sha256(unsigned char *out, const unsigned char *in, int n) 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); @@ -441,6 +462,7 @@ static qboolean Crypto_AddPrivateKey(d0_blind_id_t *pk, char *buf, size_t len) static d0_blind_id_t *pubkeys[MAX_PUBKEYS]; static char pubkeys_fp64[MAX_PUBKEYS][FP64_SIZE+1]; static qboolean pubkeys_havepriv[MAX_PUBKEYS]; +static qboolean pubkeys_havesig[MAX_PUBKEYS]; static char pubkeys_priv_fp64[MAX_PUBKEYS][FP64_SIZE+1]; static char challenge_append[1400]; static size_t challenge_append_length; @@ -523,7 +545,7 @@ qboolean Crypto_ServerFinishInstance(crypto_t *out, crypto_t *crypto) } CLEAR_CDATA; memcpy(out, crypto, sizeof(*out)); - memset(crypto, 0, sizeof(crypto)); + memset(crypto, 0, sizeof(*crypto)); return true; } @@ -699,7 +721,7 @@ qboolean Crypto_RetrieveHostKey(lhnetaddress_t *peeraddress, int *keyid, char *k return true; } -int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen) // return value: -1 if more to come, +1 if valid, 0 if end of list +int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, qboolean *issigned) // return value: -1 if more to come, +1 if valid, 0 if end of list { if(keyid < 0 || keyid >= MAX_PUBKEYS) return 0; @@ -714,6 +736,8 @@ int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, if(idfp) if(pubkeys_havepriv[keyid]) strlcpy(idfp, pubkeys_priv_fp64[keyid], keyfplen); + if(issigned) + *issigned = pubkeys_havesig[keyid]; return 1; } // end @@ -748,11 +772,48 @@ static void Crypto_BuildChallengeAppend(void) challenge_append_length = p - challenge_append; } -static void Crypto_LoadKeys(void) +static qboolean Crypto_SavePubKeyTextFile(int i) +{ + qfile_t *f; + char vabuf[1024]; + + if(!pubkeys_havepriv[i]) + return false; + f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%skey_%d-public-fp%s.txt", *fs_userdir ? fs_userdir : fs_basedir, i, sessionid.string), "w", false); + if(!f) + return false; + + // we ignore errors for this file, as it's not necessary to have + FS_Printf(f, "ID-Fingerprint: %s\n", pubkeys_priv_fp64[i]); + FS_Printf(f, "ID-Is-Signed: %s\n", pubkeys_havesig[i] ? "yes" : "no"); + FS_Printf(f, "ID-Is-For-Key: %s\n", pubkeys_fp64[i]); + FS_Printf(f, "\n"); + FS_Printf(f, "This is a PUBLIC ID file for DarkPlaces.\n"); + FS_Printf(f, "You are free to share this file or its contents.\n"); + FS_Printf(f, "\n"); + FS_Printf(f, "This file will be automatically generated again if deleted.\n"); + FS_Printf(f, "\n"); + FS_Printf(f, "However, NEVER share the accompanying SECRET ID file called\n"); + FS_Printf(f, "key_%d.d0si%s, as doing so would compromise security!\n", i, sessionid.string); + FS_Close(f); + + return true; +} + +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 @@ -767,14 +828,15 @@ static void Crypto_LoadKeys(void) 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)); + pubkeys_havesig[i] = false; + 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)) @@ -782,14 +844,36 @@ static void Crypto_LoadKeys(void) 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]); - pubkeys_havepriv[i] = true; - strlcat(crypto_idstring_buf, va(" %s@%s", pubkeys_priv_fp64[i], pubkeys_fp64[i]), sizeof(crypto_idstring_buf)); + D0_BOOL status = 0; + + 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]); + + // verify the key we just loaded (just in case) + if(qd0_blind_id_verify_private_id(pubkeys[i]) && qd0_blind_id_verify_public_id(pubkeys[i], &status)) + { + pubkeys_havepriv[i] = true; + strlcat(crypto_idstring_buf, va(vabuf, sizeof(vabuf), " %s@%s", pubkeys_priv_fp64[i], pubkeys_fp64[i]), sizeof(crypto_idstring_buf)); + + // verify the key we just got (just in case) + if(status) + pubkeys_havesig[i] = true; + else + Con_Printf("NOTE: this ID has not yet been signed!\n"); + + Crypto_SavePubKeyTextFile(i); + } + else + { + Con_Printf("d0_blind_id_verify_private_id failed, this is not a valid key!\n"); + qd0_blind_id_free(pubkeys[i]); + pubkeys[i] = NULL; + } } else { - // can't really happen - // but nothing leaked here + Con_Printf("d0_blind_id_fingerprint64_public_id failed\n"); + qd0_blind_id_free(pubkeys[i]); + pubkeys[i] = NULL; } } } @@ -853,6 +937,7 @@ static void Crypto_LoadKeys(void) static void Crypto_UnloadKeys(void) { int i; + keygen_i = -1; for(i = 0; i < MAX_PUBKEYS; ++i) { @@ -860,6 +945,7 @@ static void Crypto_UnloadKeys(void) qd0_blind_id_free(pubkeys[i]); pubkeys[i] = NULL; pubkeys_havepriv[i] = false; + pubkeys_havesig[i] = false; memset(pubkeys_fp64[i], 0, sizeof(pubkeys_fp64[i])); memset(pubkeys_priv_fp64[i], 0, sizeof(pubkeys_fp64[i])); challenge_append_length = 0; @@ -867,6 +953,45 @@ static void Crypto_UnloadKeys(void) 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; @@ -892,13 +1017,21 @@ void Crypto_Shutdown(void) 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(); @@ -910,10 +1043,16 @@ void Crypto_Init(void) 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) { @@ -921,16 +1060,18 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch size_t l[1]; static char buf[8192]; static char buf2[8192]; - size_t bufsize, buf2size; + size_t buf2size; qfile_t *f = NULL; - 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; } @@ -938,12 +1079,14 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch { 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)) @@ -958,97 +1101,31 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch 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; } // verify the key we just got (just in case) - ctx = qd0_blind_id_new(); - if(!ctx) - { - Con_Printf("d0_blind_id_new failed\n"); - keygen_i = -1; - return; - } - ctx2 = qd0_blind_id_new(); - if(!ctx2) - { - Con_Printf("d0_blind_id_new failed\n"); - qd0_blind_id_free(ctx); - keygen_i = -1; - return; - } - if(!qd0_blind_id_copy(ctx, pubkeys[keygen_i])) - { - Con_Printf("d0_blind_id_copy failed\n"); - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); - keygen_i = -1; - return; - } - if(!qd0_blind_id_copy(ctx2, pubkeys[keygen_i])) - { - Con_Printf("d0_blind_id_copy failed\n"); - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); - keygen_i = -1; - return; - } - bufsize = sizeof(buf); - if(!qd0_blind_id_authenticate_with_private_id_start(ctx, 1, 1, "hello world", 11, buf, &bufsize)) - { - Con_Printf("d0_blind_id_authenticate_with_private_id_start failed\n"); - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); - keygen_i = -1; - return; - } - buf2size = sizeof(buf2); - if(!qd0_blind_id_authenticate_with_private_id_challenge(ctx2, 1, 1, buf, bufsize, buf2, &buf2size, &status) || !status) - { - Con_Printf("d0_blind_id_authenticate_with_private_id_challenge failed (server does not have the requested private key)\n"); - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); - keygen_i = -1; - return; - } - bufsize = sizeof(buf); - if(!qd0_blind_id_authenticate_with_private_id_response(ctx, buf2, buf2size, buf, &bufsize)) + if(!qd0_blind_id_verify_public_id(pubkeys[keygen_i], &status) || !status) { - Con_Printf("d0_blind_id_authenticate_with_private_id_response failed\n"); - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); + Con_Printf("d0_blind_id_verify_public_id failed\n"); keygen_i = -1; + SV_UnlockThreadMutex(); return; } - buf2size = sizeof(buf2); - if(!qd0_blind_id_authenticate_with_private_id_verify(ctx2, buf, bufsize, buf2, &buf2size, &status) || !status) - { - Con_Printf("d0_blind_id_authenticate_with_private_id_verify failed (server does not have the requested private key)\n"); - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); - keygen_i = -1; - return; - } - qd0_blind_id_free(ctx); - qd0_blind_id_free(ctx2); // we have a valid key now! // make the rest of crypto.c know that - 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]); - 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)); - crypto_idstring = crypto_idstring_buf; - Crypto_BuildChallengeAppend(); - } + Con_Printf("Received signature for private ID key_%d.d0pk (public key fingerprint: %s)\n", keygen_i, pubkeys_priv_fp64[keygen_i]); + pubkeys_havesig[keygen_i] = true; + // write the key to disk p[0] = buf; l[0] = sizeof(buf); @@ -1056,36 +1133,35 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch { 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); + Crypto_SavePubKeyTextFile(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) @@ -1095,7 +1171,12 @@ static void Crypto_KeyGen_f(void) size_t l[1]; static char buf[8192]; static char buf2[8192]; + size_t buf2size; size_t buf2l, buf2pos; + char vabuf[1024]; + size_t len2; + qfile_t *f = NULL; + if(!d0_blind_id_dll) { Con_Print("libd0_blind_id DLL not found, this command is inactive.\n"); @@ -1106,28 +1187,98 @@ 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); - 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; - if(!qd0_blind_id_generate_private_id_start(pubkeys[keygen_i])) + + // how to START the keygenning... + if(pubkeys_havepriv[keygen_i]) { - Con_Printf("d0_blind_id_start failed\n"); - keygen_i = -1; - return; + if(pubkeys_havesig[keygen_i]) + { + Con_Printf("there is already a signed private key for %d\n", i); + keygen_i = -1; + SV_UnlockThreadMutex(); + return; + } + // if we get here, we only need a signature, no new keygen run needed + Con_Printf("Only need a signature for an existing key...\n"); + } + else + { + // we also need a new ID itself + if(!qd0_blind_id_generate_private_id_start(pubkeys[keygen_i])) + { + Con_Printf("d0_blind_id_start failed\n"); + keygen_i = -1; + SV_UnlockThreadMutex(); + return; + } + // verify the key we just got (just in case) + if(!qd0_blind_id_verify_private_id(pubkeys[keygen_i])) + { + Con_Printf("d0_blind_id_verify_private_id failed\n"); + keygen_i = -1; + SV_UnlockThreadMutex(); + return; + } + // we have a valid key now! + // make the rest of crypto.c know that + len2 = FP64_SIZE; + if(qd0_blind_id_fingerprint64_public_id(pubkeys[keygen_i], pubkeys_priv_fp64[keygen_i], &len2)) // keeps final NUL + { + Con_Printf("Generated 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(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(); + } + // write the key to disk + p[0] = buf; + l[0] = sizeof(buf); + if(!qd0_blind_id_write_private_id(pubkeys[keygen_i], buf, &l[0])) + { + 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; + } + + 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%s\n", keygen_i, sessionid.string); + keygen_i = -1; + SV_UnlockThreadMutex(); + return; + } + FS_Write(f, buf2, buf2size); + FS_Close(f); + + Crypto_SavePubKeyTextFile(keygen_i); + + Con_Printf("Saved unsigned key to key_%d.d0si%s\n", keygen_i, sessionid.string); } p[0] = buf; l[0] = sizeof(buf); @@ -1135,6 +1286,7 @@ static void Crypto_KeyGen_f(void) { Con_Printf("d0_blind_id_generate_private_id_request failed\n"); keygen_i = -1; + SV_UnlockThreadMutex(); return; } buf2pos = strlen(Cmd_Argv(2)); @@ -1143,12 +1295,14 @@ static void Crypto_KeyGen_f(void) { 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; @@ -1157,9 +1311,11 @@ static void Crypto_KeyGen_f(void) { Con_Printf("curl failed\n"); keygen_i = -1; + SV_UnlockThreadMutex(); return; } - Con_Printf("key generation in progress\n"); + Con_Printf("Signature generation in progress...\n"); + SV_UnlockThreadMutex(); } // end @@ -1185,7 +1341,11 @@ static void Crypto_Keys_f(void) { Con_Printf("%2d: public key key_%d.d0pk (fingerprint: %s)\n", i, i, pubkeys_fp64[i]); if(pubkeys_havepriv[i]) - Con_Printf(" private ID 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]); + if(!pubkeys_havesig[i]) + Con_Printf(" NOTE: this ID has not yet been signed!\n"); + } } } } @@ -1309,9 +1469,14 @@ static void seacpy(unsigned char *key, const unsigned char *iv, unsigned char *d } } +// 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) @@ -1346,6 +1511,15 @@ const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t *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; } @@ -1359,6 +1533,17 @@ const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t 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) @@ -1413,11 +1598,31 @@ const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t 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 } @@ -1477,6 +1682,8 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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 @@ -1487,7 +1694,7 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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++) @@ -1507,9 +1714,9 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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); @@ -1518,7 +1725,7 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t 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++) @@ -1529,7 +1736,7 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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); @@ -1615,7 +1822,7 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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; @@ -1640,7 +1847,7 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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; @@ -1665,11 +1872,11 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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; @@ -1707,10 +1914,10 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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; @@ -1733,9 +1940,9 @@ static int Crypto_ServerParsePacket_Internal(const char *data_in, size_t len_in, 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)) { @@ -1785,11 +1992,12 @@ int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, 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; @@ -1818,12 +2026,12 @@ int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, *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; @@ -1855,6 +2063,8 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, 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 @@ -1866,7 +2076,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, { int wantserverid = -1; Crypto_RetrieveHostKey(&cls.connect_address, &wantserverid, NULL, 0, NULL, 0, NULL); - if(!crypto || !crypto->authenticated) + if(!crypto || !crypto->authenticated) // we ALSO get here if we are using an encrypted connection, so let's rule this out { if(wantserverid >= 0) return Crypto_ClientError(data_out, len_out, "Server tried an unauthenticated connection even though a host key is present"); @@ -1875,11 +2085,33 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, } return CRYPTO_NOMATCH; } - else if (len_in >= 1 && string[0] == 'j' && cls.connect_trying && d0_rijndael_dll && crypto_aeslevel.integer >= 3) + else if (len_in >= 1 && string[0] == 'j' && cls.connect_trying && d0_rijndael_dll) { int wantserverid = -1; Crypto_RetrieveHostKey(&cls.connect_address, &wantserverid, NULL, 0, NULL, 0, NULL); - if(!crypto || !crypto->authenticated) + //if(!crypto || !crypto->authenticated) + { + if(wantserverid >= 0) + return Crypto_ClientError(data_out, len_out, "Server tried an unauthenticated connection even though a host key is present"); + if(crypto_aeslevel.integer >= 3) + return Crypto_ClientError(data_out, len_out, "This server requires encryption to be not required (crypto_aeslevel <= 2)"); + } + return CRYPTO_NOMATCH; + } + else if (len_in >= 5 && BuffLittleLong((unsigned char *) string) == ((int)NETFLAG_CTL | (int)len_in)) + { + int wantserverid = -1; + + // these three are harmless + if(string[4] == CCREP_SERVER_INFO) + return CRYPTO_NOMATCH; + if(string[4] == CCREP_PLAYER_INFO) + return CRYPTO_NOMATCH; + if(string[4] == CCREP_RULE_INFO) + return CRYPTO_NOMATCH; + + Crypto_RetrieveHostKey(&cls.connect_address, &wantserverid, NULL, 0, NULL, 0, NULL); + //if(!crypto || !crypto->authenticated) { if(wantserverid >= 0) return Crypto_ClientError(data_out, len_out, "Server tried an unauthenticated connection even though a host key is present"); @@ -1890,7 +2122,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, } 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; @@ -1905,7 +2137,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, 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) @@ -1926,7 +2158,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, int clientid = -1, serverid = -1, wantserverid = -1; qboolean server_can_auth = true; char wantserver_idfp[FP64_SIZE+1]; - int wantserver_aeslevel; + int wantserver_aeslevel = 0; // if we have a stored host key for the server, assume serverid to already be selected! // (the loop will refuse to overwrite this one then) @@ -2065,7 +2297,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, // 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] : ""); @@ -2135,9 +2367,9 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, { 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); @@ -2148,13 +2380,13 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, { 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; @@ -2178,7 +2410,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, } 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; @@ -2197,9 +2429,9 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, 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" @@ -2233,12 +2465,12 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, } // 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; @@ -2274,15 +2506,15 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, 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; @@ -2305,7 +2537,7 @@ int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, 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;