#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
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},
{"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
{
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]);
}
}
}
}
}
+// 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)
*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(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;
}
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(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)
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
}
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;
+}