RRID port part 1

last commit of this set is 2925843e
This commit is contained in:
NepDisk 2026-03-29 12:52:46 -04:00
parent ca51695870
commit d6eab04a7a
22 changed files with 3586 additions and 4 deletions

View file

@ -276,6 +276,7 @@ add_subdirectory(sdl)
add_subdirectory(objects)
add_subdirectory(core)
add_subdirectory(acs)
add_subdirectory(monocypher)
# OS macros
if (UNIX)

View file

@ -47,6 +47,8 @@
#include "lonesha256.h"
#include "m_perfstats.h"
#include "monocypher/monocypher.h"
// SRB2Kart
#include "k_kart.h"
#include "k_battle.h"
@ -181,9 +183,19 @@ char connectedserverdescription[MAXSERVERDESCRIPTION];
/// \todo WORK!
boolean acceptnewnode = true;
uint8_t lastReceivedKey[MAXNETNODES][32];
uint8_t lastSentChallenge[MAXNETNODES][32];
boolean serverisfull = false; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not
tic_t firstconnectattempttime = 0;
uint8_t awaitingChallenge[32];
#ifdef DEVELOP
consvar_t cv_sigfail = CVAR_INIT ("sigfail", "Off", CV_SAVE, CV_OnOff, NULL);
#endif
// engine
// Must be a power of two
@ -905,10 +917,40 @@ static boolean CL_SendJoin(void)
memcpy(&netbuffer->u.clientcfg.availabilities, R_GetSkinAvailabilities(), MAXAVAILABILITY*sizeof(UINT8));
// Don't leak old signatures from prior sessions.
memset(&netbuffer->u.clientcfg.challengeResponse, 0, sizeof(((clientconfig_pak *)0)->challengeResponse));
uint8_t signature[64];
crypto_eddsa_sign(signature, secret_key, awaitingChallenge, 32);
if (crypto_eddsa_check(signature, public_key, awaitingChallenge, 32) != 0)
I_Error("Couldn't verify own key, may be corrupted?");
#ifdef DEVELOP
if (cv_sigfail.value)
{
CONS_Alert(CONS_WARNING, "SIGFAIL enabled, scrubbing signature from CL_SendJoin\n");
memset(signature, 0, 64);
}
#endif
// Testing
// memset(signature, 0, sizeof(signature));
memcpy(&netbuffer->u.clientcfg.challengeResponse, signature, sizeof(signature));
return HSendPacket(servernode, false, 0, sizeof (clientconfig_pak));
}
static boolean CL_SendKey(void)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
netbuffer->packettype = PT_CLIENTKEY;
memcpy(netbuffer->u.clientkey.key, public_key, sizeof(public_key));
return HSendPacket(servernode, false, 0, sizeof (clientkey_pak) );
}
void
CopyCaretColors (char *p, const char *s, int n)
{
@ -2039,7 +2081,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
{
*asksent = 0; //This ensure the first join ask is right away
firstconnectattempttime = I_GetTime();
cl_mode = CL_ASKJOIN;
cl_mode = CL_SENDKEY;
}
break;
case CL_ASKJOIN:
@ -2075,6 +2117,19 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
cl_mode = CL_ASKJOIN;
}
break;
case CL_SENDKEY:
if (I_GetTime() >= *asksent && CL_SendKey())
{
*asksent = I_GetTime() + NEWTICRATE*3;
cl_mode = CL_WAITCHALLENGE;
}
break;
case CL_WAITCHALLENGE:
if (I_GetTime() >= *asksent)
{
cl_mode = CL_SENDKEY;
}
break;
case CL_DOWNLOADSAVEGAME:
// At this state, the first (and only) needed file is the gamestate
if (fileneeded[0].status == FS_FOUND)
@ -2934,6 +2989,8 @@ static void Command_Nodes(void)
CONS_Printf(" - %s", address);
}
CONS_Printf(" [RRID-%s] ", GetPrettyRRID(players[i].public_key, true));
if (IsPlayerAdmin(i))
CONS_Printf(M_GetText(" (verified admin)"));
@ -3381,6 +3438,11 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
HU_AddChatText(va("\x82*%s left the game (Connection timeout)", player_names[pnum]), false);
kickreason = KR_TIMEOUT;
break;
case KICK_MSG_SIGFAIL:
HU_AddChatText(va("\x82*%s left the game (Invalid signature)", player_names[pnum]), false);
kickreason = KR_TIMEOUT;
break;
case KICK_MSG_PLAYER_QUIT:
if (netgame) // not splitscreen/bots
HU_AddChatText(va("\x82*%s left the game", player_names[pnum]), false);
@ -3933,11 +3995,20 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
D_SendPlayerConfig(splitscreenplayer);
addedtogame = true;
CONS_Printf("It's me, node %d, with ID %s! (This is uninitialized memory because Tyron is a nice person :)!)\n", node, GetPrettyRRID(lastReceivedKey[node], true));
memcpy(lastReceivedKey[node], public_key, 32);
}
players[newplayernum].splitscreenindex = splitscreenplayer;
players[newplayernum].bot = false;
// player_t is the only place in the game that a key is null-terminated, for ease of Lua push.
memset(players[newplayernum].public_key, 0, 32 + 1);
CONS_Printf("Adding player from node %d with ID %s\n", node, GetPrettyRRID(lastReceivedKey[node], true));
memcpy(players[newplayernum].public_key, lastReceivedKey[node], 32);
CONS_Printf("Node %d now has ID %s\n", node, GetPrettyRRID(players[newplayernum].public_key, true));
// Previously called at the top of this function, commented as
// "caused desyncs in this spot :(". But we can't do this in
// G_PlayerReborn, since that only runs for level contexts and
@ -4395,6 +4466,9 @@ static void HandleConnect(SINT8 node)
}
}
// Testing
// memset(netbuffer->u.clientcfg.challengeResponse, 0, sizeof(netbuffer->u.clientcfg.challengeResponse));
if (bannednode && bannednode[node].banid != SIZE_MAX)
{
const char *reason = NULL;
@ -4478,6 +4552,7 @@ static void HandleConnect(SINT8 node)
}
else
{
int sigcheck;
boolean newnode = false;
for (i = 0; i < netbuffer->u.clientcfg.localplayers - playerpernode[node]; i++)
@ -4488,6 +4563,24 @@ static void HandleConnect(SINT8 node)
SV_SendRefuse(node, "Bad player name");
return;
}
if (node == 0) // Server
{
memcpy(lastReceivedKey[node], public_key, sizeof(lastReceivedKey[node]));
CONS_Printf("Adding SERVER. Setting lastReceivedKey on node %d to %s\n", node, GetPrettyRRID(lastReceivedKey[node], true));
}
else
{
CONS_Printf("Adding client. Doing sigcheck for node %d, ID %s\n", node, GetPrettyRRID(lastReceivedKey[node], true));
sigcheck = crypto_eddsa_check(netbuffer->u.clientcfg.challengeResponse, lastReceivedKey[node], lastSentChallenge[node], 32);
if (netgame && sigcheck != 0)
{
SV_SendRefuse(node, M_GetText("Signature verification failed."));
return;
}
}
}
memcpy(availabilitiesbuffer, netbuffer->u.clientcfg.availabilities, sizeof(availabilitiesbuffer));
@ -5576,6 +5669,16 @@ static void HandlePacketFromAwayNode(SINT8 node)
case PT_SERVERTICS : PT_ServerTics (node, -1); break;
case PT_CLIENTCMD : break; // This is not an "unknown packet"
case PT_PLAYERINFO : HandlePlayerInfo (node ); break;
case PT_CLIENTKEY:
if (server)
PT_ClientKey(node);
break;
case PT_SERVERCHALLENGE:
if (cl_mode != CL_WAITCHALLENGE)
break;
memcpy(awaitingChallenge, netbuffer->u.serverchallenge.secret, sizeof(awaitingChallenge));
cl_mode = CL_ASKJOIN;
break;
default:
DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype));
@ -5605,6 +5708,22 @@ static void HandlePacketFromPlayer(SINT8 node)
I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole);
#endif
uint8_t allzero[32];
memset(allzero, 0, sizeof(allzero));
if (IsPacketSigned(netbuffer->packettype))
{
const void* message = &netbuffer->u;
if (crypto_eddsa_check(netbuffer->signature, lastReceivedKey[node], message, doomcom->datalength - BASEPACKETSIZE))
{
//CONS_Alert(CONS_ERROR, "SIGFAIL! Packet type %d from node %d \nkey %s size %d\n",
//netbuffer->packettype, node,
//GetPrettyRRID(lastReceivedKey[node], true), doomcom->datalength - BASEPACKETSIZE);
// SendKick(netconsole, KICK_MSG_CON_FAIL);
return;
}
}
switch (netbuffer->packettype)
{
// SERVER RECEIVE

View file

@ -138,6 +138,9 @@ typedef enum
PT_SAY, // "Hey server, please send this chat message to everyone via XD_SAY"
PT_REQMAPQUEUE, // Client requesting a roundqueue operation
PT_CLIENTKEY, // "Here's my public key"
PT_SERVERCHALLENGE, // "Prove it"
NUMPACKETTYPE
} packettype_t;
@ -291,6 +294,7 @@ struct clientconfig_pak
UINT8 mode;
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME];
UINT8 availabilities[MAXAVAILABILITY];
uint8_t challengeResponse[64];
} ATTRPACK;
#define SV_SPEEDMASK 0x03 // used to send kartspeed
@ -385,6 +389,16 @@ struct reqmapqueue_pak
UINT8 source;
} ATTRPACK;
struct clientkey_pak
{
char key[32];
} ATTRPACK;
struct serverchallenge_pak
{
char secret[32];
} ATTRPACK;
struct netinfo_pak
{
UINT32 pingtable[MAXPLAYERS+1];
@ -410,6 +424,7 @@ struct doomdata_t
UINT8 ackreturn; // The return of the ack number
UINT8 packettype;
uint8_t signature[64];
UINT8 packetindex;
union
{
@ -437,6 +452,8 @@ struct doomdata_t
netinfo_pak netinfo;
say_pak say;
reqmapqueue_pak reqmapqueue; // Formerly XD_REQMAPQUEUE
clientkey_pak clientkey; // TODO: Tyron, does anyone take any of these sizes even remotely seriously
serverchallenge_pak serverchallenge; // Are you even going to update this shit, are you even going to remove this comment
} u; // This is needed to pack diff packet types data together
} ATTRPACK;
@ -478,6 +495,7 @@ extern consvar_t cv_serverinfoscreen;
#define KICK_MSG_GRIEF 7
#define KICK_MSG_CUSTOM_KICK 8
#define KICK_MSG_CUSTOM_BAN 9
#define KICK_MSG_SIGFAIL 10
typedef enum
{
@ -528,6 +546,10 @@ extern consvar_t cv_joinnextround;
extern consvar_t cv_discordinvites;
#ifdef DEVELOP
extern consvar_t cv_sigfail;
#endif
// Used in d_net, the only dependence
tic_t ExpandTics(INT32 low, tic_t basetic);
void D_ClientServerInit(void);
@ -558,6 +580,8 @@ typedef enum
CL_PREPAREHTTPFILES,
CL_DOWNLOADHTTPFILES,
#endif
CL_SENDKEY,
CL_WAITCHALLENGE,
} cl_mode_t;
// Create any new ticcmds and broadcast to other players.
@ -677,6 +701,9 @@ void DoSayPacket(SINT8 target, UINT8 flags, UINT8 source, char *message);
void DoSayPacketFromCommand(SINT8 target, size_t usedargs, UINT8 flags);
void SendServerNotice(SINT8 target, char *message);
extern uint8_t lastReceivedKey[MAXNETNODES][32];
extern uint8_t lastSentChallenge[MAXNETNODES][32];
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -74,6 +74,9 @@
#include "m_perfstats.h"
#include "core/memory.h"
#include "monocypher/monocypher.h"
#include "stun.h"
// SRB2Kart
#include "k_grandprix.h"
#include "k_boss.h"
@ -179,6 +182,10 @@ INT32 eventhead, eventtail;
boolean dedicated = false;
// For identity negotiation with netgame servers
uint8_t public_key[32];
uint8_t secret_key[64];
boolean loaded_config = false;
//
@ -1868,6 +1875,37 @@ void D_SRB2Main(void)
ACS_Init();
CON_SetLoadingProgress(LOADED_ACSINIT);
// TODO: This file should probably give a fuck about command line params,
// or not be stored next to the EXE in a way that allows people to unknowingly send it to others.
// I'm thinking ~/.config on nix and %appdata on windows since we don't have profiles. - Nep
static char keyfile[16] = "rrid.dat";
static uint8_t seed[32];
csprng(seed, 32);
crypto_eddsa_key_pair(secret_key, public_key, seed);
int sk_size = sizeof(secret_key);
int pk_size = sizeof(public_key);
int totalsize = sk_size + pk_size;
if (FIL_ReadFileOK(keyfile))
{
UINT8 *readbuffer = NULL;
UINT16 lengthRead = FIL_ReadFile(keyfile, &readbuffer);
if (readbuffer == NULL || lengthRead != totalsize)
I_Error("Malformed keyfile");
memcpy(secret_key, readbuffer, sk_size);
memcpy(public_key, readbuffer + sk_size, pk_size);
}
else
{
uint8_t keybuffer[totalsize];
memcpy(keybuffer, secret_key, sk_size);
memcpy(keybuffer + sk_size, public_key, pk_size);
if (!FIL_WriteFile(keyfile, keybuffer, totalsize))
I_Error("Couldn't open keyfile");
}
//------------------------------------------------ COMMAND LINE PARAMS
// this must be done after loading gamedata,

View file

@ -64,6 +64,9 @@ extern char srb2path[256]; //Alam: SRB2's Home
const char *D_GetFancyBranchName(void);
extern uint8_t public_key[32];
extern uint8_t secret_key[64];
// the infinite loop of D_SRB2Loop() called from win_main for windows version
void D_SRB2Loop(void) FUNCNORETURN;

View file

@ -31,6 +31,7 @@
#include "d_main.h" // srb2home
#include "stun.h"
#include "byteptr.h"
#include "monocypher/monocypher.h"
#include "qs22j.h"
@ -470,7 +471,12 @@ static void InitAck(void)
ackpak[i].acknum = 0;
for (i = 0; i < MAXNETNODES; i++)
{
InitNode(&nodes[i]);
csprng(lastSentChallenge[i], sizeof(lastSentChallenge[i]));
csprng(lastReceivedKey[i], sizeof(lastReceivedKey[i]));
}
}
/** Removes all acks of a given packet type
@ -547,6 +553,9 @@ void Net_CloseConnection(INT32 node)
if (server)
SV_AbortLuaFileTransfer(node);
I_NetFreeNodenum(node);
csprng(lastSentChallenge[node], sizeof(lastSentChallenge[node]));
csprng(lastReceivedKey[node], sizeof(lastReceivedKey[node]));
}
//
@ -835,6 +844,31 @@ static boolean ShouldDropPacket(void)
}
#endif
boolean IsPacketSigned(int packettype)
{
switch (packettype)
{
case PT_CLIENTCMD:
case PT_CLIENT2CMD:
case PT_CLIENT3CMD:
case PT_CLIENT4CMD:
case PT_CLIENTMIS:
case PT_CLIENT2MIS:
case PT_CLIENT3MIS:
case PT_CLIENT4MIS:
case PT_TEXTCMD:
case PT_TEXTCMD2:
case PT_TEXTCMD3:
case PT_TEXTCMD4:
case PT_LOGIN:
case PT_ASKLUAFILE:
case PT_SENDINGLUAFILE:
return true;
default:
return false;
}
}
//
// HSendPacket
//
@ -842,6 +876,27 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE);
if (IsPacketSigned(netbuffer->packettype))
{
const void* message = &netbuffer->u;
//CONS_Printf("Signing packet type %d of length %d\n", netbuffer->packettype, packetlength);
crypto_eddsa_sign(netbuffer->signature, secret_key, message, packetlength);
#ifdef DEVELOP
if (cv_sigfail.value)
{
CONS_Alert(CONS_WARNING, "SIGFAIL enabled, scrubbing signature from HSendPacket\n");
memset(netbuffer->signature, 0, sizeof(netbuffer->signature));
}
#endif
}
else
{
//CONS_Printf("NOT signing PT_%d of length %d, it doesn't need to be\n", netbuffer->packettype, packetlength);
memset(netbuffer->signature, 0, sizeof(netbuffer->signature));
}
if (node == 0) // Packet is to go back to us
{
if ((rebound_head+1) % MAXREBOUND == rebound_tail)

View file

@ -72,6 +72,8 @@ void Net_AbortPacketType(UINT8 packettype);
void Net_SendAcks(INT32 node);
void Net_WaitAllAckReceived(UINT32 timeout);
boolean IsPacketSigned(int packettype);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -1347,6 +1347,10 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_netticbuffer);
CV_RegisterVar(&cv_mindelay);
#ifdef DEVELOP
CV_RegisterVar(&cv_sigfail);
#endif
// HUD
CV_RegisterVar(&cv_itemfinder);

View file

@ -52,6 +52,8 @@
#include "m_misc.h"
#include "m_menu.h"
#include "filesrch.h"
#include "stun.h"
#include <errno.h>
@ -1339,6 +1341,22 @@ void PT_FileReceived(SINT8 node)
SV_EndFileSend(doomcom->remotenode);
}
void PT_ClientKey(INT32 node)
{
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
clientkey_pak *packet = (void*)&netbuffer->u.clientkey;
memcpy(lastReceivedKey[node], packet->key, sizeof(lastReceivedKey[node]));
CONS_Printf("Got keys from node %d, %s\n", node, GetPrettyRRID(lastReceivedKey[node], true));
netbuffer->packettype = PT_SERVERCHALLENGE;
csprng(lastSentChallenge[node], sizeof(serverchallenge_pak));
memcpy(&netbuffer->u.serverchallenge, lastSentChallenge[node], sizeof(serverchallenge_pak));
HSendPacket(node, false, 0, sizeof (serverchallenge_pak));
}
static void SendAckPacket(fileack_pak *packet, UINT8 fileid)
{
size_t packetsize;

View file

@ -116,6 +116,8 @@ boolean CL_CheckDownloadable(void);
boolean CL_SendFileRequest(void);
void PT_RequestFile(INT32 node);
void PT_ClientKey(INT32 node);
typedef enum
{
LFTNS_NONE, // This node is not connected

View file

@ -890,6 +890,8 @@ struct player_t
boolean walltransfered;
UINT8 walltransferboost;
uint8_t public_key[32 + 1];
#ifdef HWRENDER
fixed_t fovadd; // adjust FOV for hw rendering
#endif

View file

@ -3174,6 +3174,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
SINT8 xtralife;
uint8_t public_key[32];
// SRB2kart
INT32 itemtype;
INT32 itemamount;
@ -3255,6 +3257,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE|PF_FLIPCAM));
memcpy(&public_key, &players[player].public_key, sizeof(public_key));
// SRB2kart
if (betweenmaps || leveltime <= starttime || spectator == true)
{
@ -3531,6 +3535,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
K_BotReborn(p);
memcpy(&p->public_key, &public_key, sizeof(p->public_key));
if (follower)
P_RemoveMobj(follower);

View file

@ -465,7 +465,8 @@ static int lib_lenLocalplayers(lua_State *L)
X(recoverydashcharge) \
X(recoverydash) \
X(tripwireunstuck) \
X(bumpunstuck)
X(bumpunstuck) \
X(public_key)
enum player_e
{
@ -1194,6 +1195,9 @@ static int player_get(lua_State *L)
case player_ping:
lua_pushinteger(L, playerpingtable[( plr - players )]);
break;
case player_public_key:
lua_pushstring(L, plr->public_key);
break;
case player_packetloss:
lua_pushinteger(L, playerpacketlosstable[plr - players]);
break;

View file

@ -2589,3 +2589,29 @@ int M_RoundUp(double number)
return (int)number;
}
char *GetPrettyRRID(const unsigned char *bin, boolean brief)
{
char *out;
size_t i;
size_t len = 32;
if (brief)
len = 8;
if (bin == NULL || len == 0)
return NULL;
out = (char *)malloc(len*2 + 1);
for (i=0; i<len; i++)
{
out[i*2] = "0123456789ABCDEF"[bin[i] >> 4];
out[i*2+1] = "0123456789ABCDEF"[bin[i] & 0x0F];
}
out[len*2] = '\0';
return out;
}

View file

@ -130,6 +130,8 @@ boolean M_IsStringEmpty(const char *s);
int M_RoundUp(double number);
char *GetPrettyRRID(const unsigned char *bin, boolean brief);
#include "w_wad.h"
extern char configfile[MAX_WADPATH];

View file

@ -0,0 +1,4 @@
target_sources(BLANKART PRIVATE
monocypher.c
monocypher.h
)

2938
src/monocypher/monocypher.c Normal file

File diff suppressed because it is too large Load diff

321
src/monocypher/monocypher.h Normal file
View file

@ -0,0 +1,321 @@
// Monocypher version 4.0.0
//
// This file is dual-licensed. Choose whichever licence you want from
// the two licences listed below.
//
// The first licence is a regular 2-clause BSD licence. The second licence
// is the CC-0 from Creative Commons. It is intended to release Monocypher
// to the public domain. The BSD licence serves as a fallback option.
//
// SPDX-License-Identifier: BSD-2-Clause OR CC0-1.0
//
// ------------------------------------------------------------------------
//
// Copyright (c) 2017-2019, Loup Vaillant
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ------------------------------------------------------------------------
//
// Written in 2017-2019 by Loup Vaillant
//
// To the extent possible under law, the author(s) have dedicated all copyright
// and related neighboring rights to this software to the public domain
// worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along
// with this software. If not, see
// <https://creativecommons.org/publicdomain/zero/1.0/>
#ifndef MONOCYPHER_H
#define MONOCYPHER_H
#include <stddef.h>
#include <stdint.h>
#ifdef MONOCYPHER_CPP_NAMESPACE
namespace MONOCYPHER_CPP_NAMESPACE {
#elif defined(__cplusplus)
extern "C" {
#endif
// Constant time comparisons
// -------------------------
// Return 0 if a and b are equal, -1 otherwise
int crypto_verify16(const uint8_t a[16], const uint8_t b[16]);
int crypto_verify32(const uint8_t a[32], const uint8_t b[32]);
int crypto_verify64(const uint8_t a[64], const uint8_t b[64]);
// Erase sensitive data
// --------------------
void crypto_wipe(void *secret, size_t size);
// Authenticated encryption
// ------------------------
void crypto_aead_lock(uint8_t *cipher_text,
uint8_t mac [16],
const uint8_t key [32],
const uint8_t nonce[24],
const uint8_t *ad, size_t ad_size,
const uint8_t *plain_text, size_t text_size);
int crypto_aead_unlock(uint8_t *plain_text,
const uint8_t mac [16],
const uint8_t key [32],
const uint8_t nonce[24],
const uint8_t *ad, size_t ad_size,
const uint8_t *cipher_text, size_t text_size);
// Authenticated stream
// --------------------
typedef struct {
uint64_t counter;
uint8_t key[32];
uint8_t nonce[8];
} crypto_aead_ctx;
void crypto_aead_init_x(crypto_aead_ctx *ctx,
const uint8_t key[32], const uint8_t nonce[24]);
void crypto_aead_init_djb(crypto_aead_ctx *ctx,
const uint8_t key[32], const uint8_t nonce[8]);
void crypto_aead_init_ietf(crypto_aead_ctx *ctx,
const uint8_t key[32], const uint8_t nonce[12]);
void crypto_aead_write(crypto_aead_ctx *ctx,
uint8_t *cipher_text,
uint8_t mac[16],
const uint8_t *ad , size_t ad_size,
const uint8_t *plain_text, size_t text_size);
int crypto_aead_read(crypto_aead_ctx *ctx,
uint8_t *plain_text,
const uint8_t mac[16],
const uint8_t *ad , size_t ad_size,
const uint8_t *cipher_text, size_t text_size);
// General purpose hash (BLAKE2b)
// ------------------------------
// Direct interface
void crypto_blake2b(uint8_t *hash, size_t hash_size,
const uint8_t *message, size_t message_size);
void crypto_blake2b_keyed(uint8_t *hash, size_t hash_size,
const uint8_t *key, size_t key_size,
const uint8_t *message, size_t message_size);
// Incremental interface
typedef struct {
// Do not rely on the size or contents of this type,
// for they may change without notice.
uint64_t hash[8];
uint64_t input_offset[2];
uint64_t input[16];
size_t input_idx;
size_t hash_size;
} crypto_blake2b_ctx;
void crypto_blake2b_init(crypto_blake2b_ctx *ctx, size_t hash_size);
void crypto_blake2b_keyed_init(crypto_blake2b_ctx *ctx, size_t hash_size,
const uint8_t *key, size_t key_size);
void crypto_blake2b_update(crypto_blake2b_ctx *ctx,
const uint8_t *message, size_t message_size);
void crypto_blake2b_final(crypto_blake2b_ctx *ctx, uint8_t *hash);
// Password key derivation (Argon2)
// --------------------------------
#define CRYPTO_ARGON2_D 0
#define CRYPTO_ARGON2_I 1
#define CRYPTO_ARGON2_ID 2
typedef struct {
uint32_t algorithm; // Argon2d, Argon2i, Argon2id
uint32_t nb_blocks; // memory hardness, >= 8 * nb_lanes
uint32_t nb_passes; // CPU hardness, >= 1 (>= 3 recommended for Argon2i)
uint32_t nb_lanes; // parallelism level (single threaded anyway)
} crypto_argon2_config;
typedef struct {
const uint8_t *pass;
const uint8_t *salt;
uint32_t pass_size;
uint32_t salt_size; // 16 bytes recommended
} crypto_argon2_inputs;
typedef struct {
const uint8_t *key; // may be NULL if no key
const uint8_t *ad; // may be NULL if no additional data
uint32_t key_size; // 0 if no key (32 bytes recommended otherwise)
uint32_t ad_size; // 0 if no additional data
} crypto_argon2_extras;
extern const crypto_argon2_extras crypto_argon2_no_extras;
void crypto_argon2(uint8_t *hash, uint32_t hash_size, void *work_area,
crypto_argon2_config config,
crypto_argon2_inputs inputs,
crypto_argon2_extras extras);
// Key exchange (X-25519)
// ----------------------
// Shared secrets are not quite random.
// Hash them to derive an actual shared key.
void crypto_x25519_public_key(uint8_t public_key[32],
const uint8_t secret_key[32]);
void crypto_x25519(uint8_t raw_shared_secret[32],
const uint8_t your_secret_key [32],
const uint8_t their_public_key [32]);
// Conversion to EdDSA
void crypto_x25519_to_eddsa(uint8_t eddsa[32], const uint8_t x25519[32]);
// scalar "division"
// Used for OPRF. Be aware that exponential blinding is less secure
// than Diffie-Hellman key exchange.
void crypto_x25519_inverse(uint8_t blind_salt [32],
const uint8_t private_key[32],
const uint8_t curve_point[32]);
// "Dirty" versions of x25519_public_key().
// Use with crypto_elligator_rev().
// Leaks 3 bits of the private key.
void crypto_x25519_dirty_small(uint8_t pk[32], const uint8_t sk[32]);
void crypto_x25519_dirty_fast (uint8_t pk[32], const uint8_t sk[32]);
// Signatures
// ----------
// EdDSA with curve25519 + BLAKE2b
void crypto_eddsa_key_pair(uint8_t secret_key[64],
uint8_t public_key[32],
uint8_t seed[32]);
void crypto_eddsa_sign(uint8_t signature [64],
const uint8_t secret_key[64],
const uint8_t *message, size_t message_size);
int crypto_eddsa_check(const uint8_t signature [64],
const uint8_t public_key[32],
const uint8_t *message, size_t message_size);
// Conversion to X25519
void crypto_eddsa_to_x25519(uint8_t x25519[32], const uint8_t eddsa[32]);
// EdDSA building blocks
void crypto_eddsa_trim_scalar(uint8_t out[32], const uint8_t in[32]);
void crypto_eddsa_reduce(uint8_t reduced[32], const uint8_t expanded[64]);
void crypto_eddsa_mul_add(uint8_t r[32],
const uint8_t a[32],
const uint8_t b[32],
const uint8_t c[32]);
void crypto_eddsa_scalarbase(uint8_t point[32], const uint8_t scalar[32]);
int crypto_eddsa_check_equation(const uint8_t signature[64],
const uint8_t public_key[32],
const uint8_t h_ram[32]);
// Chacha20
// --------
// Specialised hash.
// Used to hash X25519 shared secrets.
void crypto_chacha20_h(uint8_t out[32],
const uint8_t key[32],
const uint8_t in [16]);
// Unauthenticated stream cipher.
// Don't forget to add authentication.
uint64_t crypto_chacha20_djb(uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size,
const uint8_t key[32],
const uint8_t nonce[8],
uint64_t ctr);
uint32_t crypto_chacha20_ietf(uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size,
const uint8_t key[32],
const uint8_t nonce[12],
uint32_t ctr);
uint64_t crypto_chacha20_x(uint8_t *cipher_text,
const uint8_t *plain_text,
size_t text_size,
const uint8_t key[32],
const uint8_t nonce[24],
uint64_t ctr);
// Poly 1305
// ---------
// This is a *one time* authenticator.
// Disclosing the mac reveals the key.
// See crypto_lock() on how to use it properly.
// Direct interface
void crypto_poly1305(uint8_t mac[16],
const uint8_t *message, size_t message_size,
const uint8_t key[32]);
// Incremental interface
typedef struct {
// Do not rely on the size or contents of this type,
// for they may change without notice.
uint8_t c[16]; // chunk of the message
size_t c_idx; // How many bytes are there in the chunk.
uint32_t r [4]; // constant multiplier (from the secret key)
uint32_t pad[4]; // random number added at the end (from the secret key)
uint32_t h [5]; // accumulated hash
} crypto_poly1305_ctx;
void crypto_poly1305_init (crypto_poly1305_ctx *ctx, const uint8_t key[32]);
void crypto_poly1305_update(crypto_poly1305_ctx *ctx,
const uint8_t *message, size_t message_size);
void crypto_poly1305_final (crypto_poly1305_ctx *ctx, uint8_t mac[16]);
// Elligator 2
// -----------
// Elligator mappings proper
void crypto_elligator_map(uint8_t curve [32], const uint8_t hidden[32]);
int crypto_elligator_rev(uint8_t hidden[32], const uint8_t curve [32],
uint8_t tweak);
// Easy to use key pair generation
void crypto_elligator_key_pair(uint8_t hidden[32], uint8_t secret_key[32],
uint8_t seed[32]);
#ifdef __cplusplus
}
#endif
#endif // MONOCYPHER_H

View file

@ -860,6 +860,12 @@ static void P_NetSyncPlayers(savebuffer_t *save)
SYNC(players[i].itemusecooldown);
SYNC(players[i].itemusecooldownmax);
if (save->write)
WRITESTRINGN(save->p, players[i].public_key, 32 + 1);
else
READSTRINGN(save->p, players[i].public_key, 32 + 1);
}
TracyCZoneEnd(__zone);
}

View file

@ -84,7 +84,7 @@ STUN_node (void)
return node;
}
static void
void
csprng
(
void * const buffer,

View file

@ -18,6 +18,8 @@ extern "C" {
typedef void (*stun_callback_t)(UINT32 address);
void csprng (void * const buffer, const size_t size);
void STUN_bind (stun_callback_t);
boolean STUN_got_response (const char * const buffer, const size_t size);

View file

@ -73,6 +73,8 @@ TYPEDEF (rewind_t);
TYPEDEF (netinfo_pak);
TYPEDEF (say_pak);
TYPEDEF (reqmapqueue_pak);
TYPEDEF (clientkey_pak);
TYPEDEF (serverchallenge_pak);
// d_event.h
TYPEDEF (event_t);