X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=crypto.c;h=6a40df4c7233b4c259c9e1c14ed839cc3caa486e;hb=1b6062f6c60a2525501e1133052d87307ee02e36;hp=751116965b62a85d8777ea4a3aef9e378c2601ca;hpb=1dfae27462dba735f317cac38f3b7deb415ed154;p=xonotic%2Fdarkplaces.git diff --git a/crypto.c b/crypto.c index 75111696..6a40df4c 100644 --- a/crypto.c +++ b/crypto.c @@ -143,6 +143,7 @@ static size_t Crypto_UnParsePack(char *buf, size_t len, unsigned long header, co #define qd0_blind_id_SHUTDOWN d0_blind_id_SHUTDOWN #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 #else @@ -191,6 +192,7 @@ static D0_EXPORT D0_WARN_UNUSED_RESULT D0_BOOL (*qd0_blind_id_INITIALIZE) (void) 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 dllfunction_t d0_blind_id_funcs[] = { {"d0_blind_id_new", (void **) &qd0_blind_id_new}, @@ -227,6 +229,7 @@ static dllfunction_t d0_blind_id_funcs[] = {"d0_blind_id_SHUTDOWN", (void **) &qd0_blind_id_SHUTDOWN}, {"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}, {NULL, NULL} }; // end of d0_blind_id interface @@ -354,37 +357,6 @@ static size_t Crypto_LoadFile(const char *path, char *buf, size_t nmax) return (size_t) n; } -static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static void base64_3to4(const unsigned char *in, unsigned char *out, int bytes) -{ - unsigned char i0 = (bytes > 0) ? in[0] : 0; - unsigned char i1 = (bytes > 1) ? in[1] : 0; - unsigned char i2 = (bytes > 2) ? in[2] : 0; - unsigned char o0 = base64[i0 >> 2]; - unsigned char o1 = base64[((i0 << 4) | (i1 >> 4)) & 077]; - unsigned char o2 = base64[((i1 << 2) | (i2 >> 6)) & 077]; - unsigned char o3 = base64[i2 & 077]; - out[0] = (bytes > 0) ? o0 : '?'; - out[1] = (bytes > 0) ? o1 : '?'; - out[2] = (bytes > 1) ? o2 : '='; - out[3] = (bytes > 2) ? o3 : '='; -} - -size_t base64_encode(unsigned char *buf, size_t buflen, size_t outbuflen) -{ - size_t blocks, i; - // expand the out-buffer - blocks = (buflen + 2) / 3; - if(blocks*4 > outbuflen) - return 0; - for(i = blocks; i > 0; ) - { - --i; - base64_3to4(buf + 3*i, buf + 4*i, buflen - 3*i); - } - return blocks * 4; -} - static qboolean PutWithNul(char **data, size_t *len, const char *str) { // invariant: data points to insertion point @@ -1213,7 +1185,7 @@ 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 key key_%d.d0si (fingerprint: %s)\n", i, pubkeys_priv_fp64[i]); + Con_Printf(" private ID key_%d.d0si (fingerprint: %s)\n", i, pubkeys_priv_fp64[i]); } } } @@ -1337,9 +1309,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) @@ -1374,6 +1351,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; } @@ -1387,6 +1373,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) @@ -1441,11 +1438,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 } @@ -2367,7 +2384,18 @@ size_t Crypto_SignData(const void *data, size_t datasize, int keyid, void *signe return 0; if(!pubkeys_havepriv[keyid]) return 0; - if(qd0_blind_id_sign_with_private_id_sign(pubkeys[keyid], true, false, data, datasize, signed_data, &signed_size)) + if(qd0_blind_id_sign_with_private_id_sign(pubkeys[keyid], true, false, (const char *)data, datasize, (char *)signed_data, &signed_size)) + return signed_size; + return 0; +} + +size_t Crypto_SignDataDetached(const void *data, size_t datasize, int keyid, void *signed_data, size_t signed_size) +{ + if(keyid < 0 || keyid >= MAX_PUBKEYS) + return 0; + if(!pubkeys_havepriv[keyid]) + return 0; + if(qd0_blind_id_sign_with_private_id_sign_detached(pubkeys[keyid], true, false, (const char *)data, datasize, (char *)signed_data, &signed_size)) return signed_size; return 0; }