-// TODO key loading, generating, saving
#include "quakedef.h"
#include "crypto.h"
#include "common.h"
#define USE_AES
-#ifdef CRYPTO_STATIC
+#ifdef LINK_TO_CRYPTO
#include <d0_blind_id/d0_blind_id.h>
#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_bind_id_verify_public_id
-#define qd0_blind_id_verify_private_id d0_bind_id_verify_private_id
+#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
#endif
-#ifdef CRYPTO_RIJNDAEL_STATIC
+#ifdef LINK_TO_CRYPTO_RIJNDAEL
#include <d0_blind_id/d0_rijndael.h>
return crypto;
}
-qboolean Crypto_ServerFinishInstance(crypto_t *out, crypto_t *crypto)
+qboolean Crypto_FinishInstance(crypto_t *out, crypto_t *crypto)
{
// no check needed here (returned pointers are only used in prefilled fields)
if(!crypto || !crypto->authenticated)
}
CLEAR_CDATA;
memcpy(out, crypto, sizeof(*out));
- memset(crypto, 0, sizeof(crypto));
+ memset(crypto, 0, sizeof(*crypto));
return true;
}
if(idend - idstart == FP64_SIZE && keyend - keystart == FP64_SIZE)
{
- for(keyid = 0; keyid < MAX_PUBKEYS; ++keyid)
+ for(keyid = MAX_PUBKEYS - 1; keyid >= 0; --keyid)
if(pubkeys[keyid])
if(!memcmp(pubkeys_fp64[keyid], keystart, FP64_SIZE))
{
idfp[FP64_SIZE] = 0;
break;
}
- if(keyid >= MAX_PUBKEYS)
- keyid = -1;
+ // If this failed, keyid will be -1.
}
}
strlcpy(keyfp, pubkeys_fp64[keyid], keyfplen);
if(idfp)
if(pubkeys_havepriv[keyid])
- strlcpy(idfp, pubkeys_priv_fp64[keyid], keyfplen);
+ strlcpy(idfp, pubkeys_priv_fp64[keyid], idfplen);
if(issigned)
*issigned = pubkeys_havesig[keyid];
return 1;
challenge_append_length = p - challenge_append;
}
+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];
if(qd0_blind_id_fingerprint64_public_id(pubkeys[i], pubkeys_priv_fp64[i], &len2)) // keeps final NUL
{
D0_BOOL status = 0;
- qfile_t *f;
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]);
- 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)
- {
- // we ignore errors for this file, as it's not necessary to have
- FS_Write(f, pubkeys_priv_fp64[i], FP64_SIZE);
- FS_Write(f, "\n", 1);
- FS_Close(f);
- }
-
// 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_havesig[i] = true;
else
Con_Printf("NOTE: this ID has not yet been signed!\n");
+
+ Crypto_SavePubKeyTextFile(i);
}
else
{
return;
}
- Crypto_Rijndael_OpenLibrary(); // if this fails, it's uncritical
+ (void) Crypto_Rijndael_OpenLibrary(); // if this fails, it's uncritical
Crypto_InitHostKeys();
}
FS_Write(f, buf2, buf2size);
FS_Close(f);
+ Crypto_SavePubKeyTextFile(keygen_i);
+
Con_Printf("Saved to key_%d.d0si%s\n", keygen_i, sessionid.string);
+
keygen_i = -1;
SV_UnlockThreadMutex();
}
FS_Write(f, buf2, buf2size);
FS_Close(f);
- f = FS_SysOpen(va(vabuf, sizeof(vabuf), "%skey_%d-public-fp%s.txt", *fs_userdir ? fs_userdir : fs_basedir, keygen_i, sessionid.string), "w", false);
- if(f)
- {
- // we ignore errors for this file, as it's not necessary to have
- FS_Write(f, pubkeys_priv_fp64[keygen_i], FP64_SIZE);
- FS_Write(f, "\n", 1);
- FS_Close(f);
- }
+ Crypto_SavePubKeyTextFile(keygen_i);
Con_Printf("Saved unsigned key to key_%d.d0si%s\n", keygen_i, sessionid.string);
}
return;
}
buf2l += buf2pos;
- buf[buf2l] = 0;
+ buf2[buf2l] = 0;
if(!Curl_Begin_ToMemory(buf2, 0, (unsigned char *) keygen_buf, sizeof(keygen_buf), Crypto_KeyGen_Finished, NULL))
{
Con_Printf("curl failed\n");
p = GetUntilNul(&data_in, &len_in);
if(p && *p)
{
+ // Find the highest numbered matching key for p.
for(i = 0; i < MAX_PUBKEYS; ++i)
{
if(pubkeys[i])
if(!strcmp(p, pubkeys_fp64[i]))
if(pubkeys_havepriv[i])
- if(serverid < 0)
- serverid = i;
+ serverid = i;
}
if(serverid < 0)
return Crypto_ServerError(data_out, len_out, "Invalid server key", NULL);
p = GetUntilNul(&data_in, &len_in);
if(p && *p)
{
+ // Find the highest numbered matching key for p.
for(i = 0; i < MAX_PUBKEYS; ++i)
{
if(pubkeys[i])
if(!strcmp(p, pubkeys_fp64[i]))
- if(clientid < 0)
- clientid = i;
+ clientid = i;
}
if(clientid < 0)
return Crypto_ServerError(data_out, len_out, "Invalid client key", NULL);
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)
break;
continue;
}
+ // Find the highest numbered matching key for p.
for(i = 0; i < MAX_PUBKEYS; ++i)
{
if(pubkeys[i])
if(!strcmp(p, pubkeys_fp64[i]))
{
if(pubkeys_havepriv[i])
- if(clientid < 0)
- clientid = i;
+ clientid = i;
if(server_can_auth)
- if(serverid < 0)
- if(wantserverid < 0 || i == wantserverid)
- serverid = i;
+ if(wantserverid < 0 || i == wantserverid)
+ serverid = i;
}
}
- if(clientid >= 0 && serverid >= 0)
- break;
+ // Not breaking, as higher keys in the list always have priority.
}
// if stored host key is not found:
if(serverid >= 0 || clientid >= 0)
{
- // TODO at this point, fill clientside crypto struct!
MAKE_CDATA;
CDATA->cdata_id = ++cdata_id;
CDATA->s = serverid;