X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=crypto.c;h=7bd36d12b2704c093602c0c2a795ad5a8f0c17d2;hb=db154618b001c5ec3403f09b5a2142d6f972785e;hp=cf83ed1be75a0156822f0ded7e61d7ca11f91ae2;hpb=acd8646648b6a54d5e0c2aac2e51eeb2572def11;p=xonotic%2Fdarkplaces.git diff --git a/crypto.c b/crypto.c index cf83ed1b..7bd36d12 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 @@ -779,7 +782,7 @@ 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]); + Con_Printf("Loaded private ID key_%d.d0si for key_%d.d0pk (public key 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)); } @@ -911,6 +914,13 @@ void Crypto_Init(void) } // 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) { @@ -1040,7 +1050,7 @@ static void Crypto_KeyGen_Finished(int code, size_t length_received, unsigned ch 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]); + Con_Printf("Received 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(" %s@%s", pubkeys_priv_fp64[keygen_i], pubkeys_fp64[keygen_i]), sizeof(crypto_idstring_buf)); crypto_idstring = crypto_idstring_buf; @@ -1182,7 +1192,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 (public key fingerprint: %s)\n", i, pubkeys_priv_fp64[i]); } } } @@ -1306,9 +1316,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) @@ -1343,6 +1358,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; } @@ -1356,6 +1380,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) @@ -1410,11 +1445,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 } @@ -2340,3 +2395,14 @@ size_t Crypto_SignData(const void *data, size_t datasize, int keyid, void *signe 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; +}