DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
crypto.h
Go to the documentation of this file.
1/*
2Copyright (C) 2010-2015 Rudolf Polzer (divVerent)
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20
21#ifndef CRYPTO_H
22#define CRYPTO_H
23
24#include <stddef.h>
25#include "qtypes.h"
26struct lhnetaddress_s;
27
28extern struct cvar_s crypto_developer;
29extern struct cvar_s crypto_aeslevel;
30#define ENCRYPTION_REQUIRED (crypto_aeslevel.integer >= 3)
31
32extern int crypto_keyfp_recommended_length; // applies to LOCAL IDs, and to ALL keys
33
34#define CRYPTO_HEADERSIZE 31
35// AES case causes 16 to 31 bytes overhead
36// SHA256 case causes 16 bytes overhead as we truncate to 128bit
37
38#define FP64_SIZE 44
39#define DHKEY_SIZE 16
40
41typedef struct
42{
43 unsigned char dhkey[DHKEY_SIZE]; // shared key, not NUL terminated
44 char client_idfp[FP64_SIZE+1];
45 char client_keyfp[FP64_SIZE+1];
47 char server_idfp[FP64_SIZE+1];
48 char server_keyfp[FP64_SIZE+1];
52 void *data;
53}
55
56void Crypto_Init(void);
57void Crypto_Init_Commands(void);
58void Crypto_LoadKeys(void); // NOTE: when this is called, the SV_LockThreadMutex MUST be active
59void Crypto_Shutdown(void);
61void sha256(unsigned char *out, const unsigned char *in, int n); // may ONLY be called if Crypto_Available()
62const void *Crypto_EncryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len);
63const void *Crypto_DecryptPacket(crypto_t *crypto, const void *data_src, size_t len_src, void *data_dst, size_t *len_dst, size_t len);
64#define CRYPTO_NOMATCH 0 // process as usual (packet was not used)
65#define CRYPTO_MATCH 1 // process as usual (packet was used)
66#define CRYPTO_DISCARD 2 // discard this packet
67#define CRYPTO_REPLACE 3 // make the buffer the current packet
68int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress, const char *peeraddressstring);
69int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress);
70
71// if len_out is nonzero, the packet is to be sent to the client
72
73qbool Crypto_ServerAppendToChallenge(const char *data_in, size_t len_in, char *data_out, size_t *len_out, size_t maxlen);
74crypto_t *Crypto_ServerGetInstance(struct lhnetaddress_s *peeraddress);
75qbool Crypto_FinishInstance(crypto_t *out, crypto_t *in); // also clears allocated memory, and frees the instance received by ServerGetInstance
76const char *Crypto_GetInfoResponseDataString(void);
77
78// retrieves a host key for an address (can be exposed to menuqc, or used by the engine to look up stored keys e.g. for server bookmarking)
79// pointers may be NULL
80qbool Crypto_RetrieveHostKey(struct lhnetaddress_s *peeraddress, int *keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, int *aeslevel, qbool *issigned);
81int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, qbool *issigned); // return value: -1 if more to come, +1 if valid, 0 if end of list
82
83size_t Crypto_SignData(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size);
84size_t Crypto_SignDataDetached(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size);
85
86// netconn protocol:
87// non-crypto:
88// getchallenge >
89// < challenge
90// connect >
91// < accept (or: reject)
92// crypto:
93// getchallenge >
94// < challenge SP <challenge> NUL vlen <size> d0pk <fingerprints I can auth to> NUL NUL <other fingerprints I accept>
95//
96// IF serverfp:
97// d0pk\cnt\0\challenge<challenge>\aeslevel<level> NUL <serverfp> NUL <clientfp>
98// >
99// check if client would get accepted; if not, do "reject" now
100// require non-control packets to be encrypted require non-control packets to be encrypted
101// do not send anything yet do not send anything yet
102// RESET to serverfp RESET to serverfp
103// d0_blind_id_authenticate_with_private_id_start() = 1
104// < d0pk\cnt\1\aes<aesenabled> NUL *startdata*
105// d0_blind_id_authenticate_with_private_id_challenge() = 1
106// d0pk\cnt\2 NUL *challengedata* >
107// d0_blind_id_authenticate_with_private_id_response() = 0
108// < d0pk\cnt\3 NUL *responsedata*
109// d0_blind_id_authenticate_with_private_id_verify() = 1
110// store server's fingerprint NOW
111// d0_blind_id_sessionkey_public_id() = 1 d0_blind_id_sessionkey_public_id() = 1
112//
113// IF clientfp AND NOT serverfp:
114// RESET to clientfp RESET to clientfp
115// d0_blind_id_authenticate_with_private_id_start() = 1
116// d0pk\cnt\0\challenge<challenge>\aeslevel<level> NUL NUL <clientfp> NUL *startdata*
117// >
118// check if client would get accepted; if not, do "reject" now
119// require non-control packets to be encrypted require non-control packets to be encrypted
120// d0_blind_id_authenticate_with_private_id_challenge() = 1
121// < d0pk\cnt\5\aes<aesenabled> NUL *challengedata*
122//
123// IF clientfp AND serverfp:
124// RESET to clientfp RESET to clientfp
125// d0_blind_id_authenticate_with_private_id_start() = 1
126// d0pk\cnt\4 NUL *startdata* >
127// d0_blind_id_authenticate_with_private_id_challenge() = 1
128// < d0pk\cnt\5 NUL *challengedata*
129//
130// IF clientfp:
131// d0_blind_id_authenticate_with_private_id_response() = 0
132// d0pk\cnt\6 NUL *responsedata* >
133// d0_blind_id_authenticate_with_private_id_verify() = 1
134// store client's fingerprint NOW
135// d0_blind_id_sessionkey_public_id() = 1 d0_blind_id_sessionkey_public_id() = 1
136// note: the ... is the "connect" message, except without the challenge. Reinterpret as regular connect message on server side
137//
138// enforce encrypted transmission (key is XOR of the two DH keys)
139//
140// IF clientfp:
141// < challenge (mere sync message)
142//
143// connect\... >
144// < accept (ALWAYS accept if connection is encrypted, ignore challenge as it had been checked before)
145//
146// commence with ingame protocol
147
148// in short:
149// server:
150// getchallenge NUL d0_blind_id: reply with challenge with added fingerprints
151// cnt=0: IF server will auth, cnt=1, ELSE cnt=5
152// cnt=2: cnt=3
153// cnt=4: cnt=5
154// cnt=6: send "challenge"
155// client:
156// challenge with added fingerprints: cnt=0; if client will auth but not server, append client auth start
157// cnt=1: cnt=2
158// cnt=3: IF client will auth, cnt=4, ELSE rewrite as "challenge"
159// cnt=5: cnt=6, server will continue by sending "challenge" (let's avoid sending two packets as response to one)
160// other change:
161// accept empty "challenge", and challenge-less connect in case crypto protocol has executed and finished
162// statusResponse and infoResponse get an added d0_blind_id key that lists
163// the keys the server can auth with and to in key@ca SPACE key@ca notation
164// any d0pk\ message has an appended "id" parameter; messages with an unexpected "id" are ignored to prevent errors from multiple concurrent auth runs
165
166
167// comparison to OTR:
168// - encryption: yes
169// - authentication: yes
170// - deniability: no (attacker requires the temporary session key to prove you
171// have sent a specific message, the private key itself does not suffice), no
172// measures are taken to provide forgeability to even provide deniability
173// against an attacker who knows the temporary session key, as using CTR mode
174// for the encryption - which, together with deriving the MAC key from the
175// encryption key, and MACing the ciphertexts instead of the plaintexts,
176// would provide forgeability and thus deniability - requires longer
177// encrypted packets and deniability was not a goal of this, as we may e.g.
178// reserve the right to capture packet dumps + extra state info to prove a
179// client/server has sent specific packets to prove cheating)
180// - perfect forward secrecy: yes (session key is derived via DH key exchange)
181
182#endif
crypto_t * Crypto_ServerGetInstance(struct lhnetaddress_s *peeraddress)
void Crypto_LoadKeys(void)
Definition crypto.c:855
int crypto_keyfp_recommended_length
Definition crypto.c:41
int Crypto_ClientParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress, const char *peeraddressstring)
Definition crypto.c:2107
void Crypto_Init_Commands(void)
Definition crypto.c:1449
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)
Definition crypto.c:1527
size_t Crypto_SignData(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size)
Definition crypto.c:2634
int Crypto_RetrieveLocalKey(int keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, qbool *issigned)
Definition crypto.c:763
#define FP64_SIZE
Definition crypto.h:38
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)
Definition crypto.c:1584
void sha256(unsigned char *out, const unsigned char *in, int n)
Definition crypto.c:383
qbool Crypto_FinishInstance(crypto_t *out, crypto_t *in)
Definition crypto.c:558
qbool Crypto_ServerAppendToChallenge(const char *data_in, size_t len_in, char *data_out, size_t *len_out, size_t maxlen)
Definition crypto.c:1696
void Crypto_Shutdown(void)
Definition crypto.c:1043
void Crypto_Init(void)
Definition crypto.c:1072
int Crypto_ServerParsePacket(const char *data_in, size_t len_in, char *data_out, size_t *len_out, lhnetaddress_t *peeraddress)
Definition crypto.c:2036
size_t Crypto_SignDataDetached(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size)
Definition crypto.c:2645
#define DHKEY_SIZE
Definition crypto.h:39
qbool Crypto_RetrieveHostKey(struct lhnetaddress_s *peeraddress, int *keyid, char *keyfp, size_t keyfplen, char *idfp, size_t idfplen, int *aeslevel, qbool *issigned)
const char * Crypto_GetInfoResponseDataString(void)
Definition crypto.c:1689
qbool Crypto_Available(void)
Definition crypto.c:1097
struct cvar_s crypto_aeslevel
Definition crypto.c:31
struct cvar_s crypto_developer
Definition crypto.c:30
#define n(x, y)
GLsizeiptr const GLvoid * data
Definition glquake.h:639
bool qbool
Definition qtypes.h:9
qbool server_issigned
Definition crypto.h:49
qbool authenticated
Definition crypto.h:50
qbool client_issigned
Definition crypto.h:46
void * data
Definition crypto.h:52
qbool use_aes
Definition crypto.h:51