2012-04-09 19:12:12 +00:00
|
|
|
/*
|
|
|
|
SHA-1 in C
|
|
|
|
By Steve Reid <steve@edmweb.com>
|
|
|
|
100% Public Domain
|
|
|
|
|
|
|
|
Test Vectors (from FIPS PUB 180-1)
|
|
|
|
"abc"
|
|
|
|
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
|
|
|
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
|
|
|
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
|
|
|
A million repetitions of "a"
|
|
|
|
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
|
|
|
|
|
|
|
This file came to FTE via EzQuake.
|
|
|
|
*/
|
|
|
|
|
2018-10-23 07:09:06 +00:00
|
|
|
#include "quakedef.h"
|
2012-04-20 15:18:01 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
/* #define SHA1HANDSOFF * Copies data before messing with it. */
|
|
|
|
#define SHA1HANDSOFF
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
unsigned int state[5];
|
|
|
|
size_t count[2];
|
|
|
|
unsigned char buffer[64];
|
|
|
|
} SHA1_CTX;
|
|
|
|
#define SHA1_DIGEST_SIZE 20
|
|
|
|
|
2021-05-09 13:00:00 +00:00
|
|
|
#define ShaBigLong(l) (((unsigned char*)&l)[0]<<24) | (((unsigned char*)&l)[1]<<16) | (((unsigned char*)&l)[2]<<8) | (((unsigned char*)&l)[3]<<0)
|
2012-04-09 19:12:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
|
|
|
|
2021-05-09 13:00:00 +00:00
|
|
|
#define blk0(i) (block->l[i] = ShaBigLong(block->l[i]))
|
2012-04-09 19:12:12 +00:00
|
|
|
|
|
|
|
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
|
|
|
|
^block->l[(i+2)&15]^block->l[i&15],1))
|
|
|
|
|
|
|
|
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
|
|
|
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
|
|
|
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
|
|
|
|
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
|
|
|
|
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
|
|
|
|
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
|
|
|
|
|
|
|
|
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
static void SHA1Transform(unsigned int state[5], const unsigned char buffer[64])
|
2012-04-09 19:12:12 +00:00
|
|
|
{
|
|
|
|
unsigned int a, b, c, d, e;
|
|
|
|
typedef union
|
|
|
|
{
|
|
|
|
unsigned char c[64];
|
|
|
|
unsigned int l[16];
|
|
|
|
} CHAR64LONG16;
|
|
|
|
CHAR64LONG16* block;
|
|
|
|
#ifdef SHA1HANDSOFF
|
Too many changes, sorry.
Change revision displays, use the SVN commit date instead of using __DATE__ (when there's no local changes). This should allow reproducible builds.
Added s_al_disable cvar, to block openal and all the various problems people have had with it, without having to name an explicit fallback (which would vary by system).
Add mastervolume cvar (for ss).
Add r_shadows 2 (aka fake shadows - for ss).
Add scr_loadingscreen_aspect -1 setting, to disable levelshots entirely, also disables the progress bar (for ss).
Better support for some effectinfo hacks (for ss).
Added dpcompat_nocsqcwarnings (because of lazy+buggy mods like ss).
Rework the dpcsqc versions of project+unproject builtins for better compat (for ss).
Added dpcompat_csqcinputeventtypes to block unexpected csqc input events (for ss).
Better compat with DP's loadfont console command (for ss).
Added dpcompat_smallerfonts cvar to replicate a DP bug (for ss).
Detect dp's m_draw extension, to work around it (for ss).
Cvar dpcompat_ignoremodificationtimes added. A value of 0 favour the most recently modified file, 1 will use DP-like alphabetically sorted preferences (for ss).
loadfont builtin can now accept outline=1 in the sizes arg for slightly more readable fonts.
Fix bbox calcs for rotated entities, fix needed for r_ignorenetpvs 0.
Hackily parse emoji.json to provide :poop: etc suggestions.
Skip prediction entirely when there's no local entity info. This fixes stair-smoothing in xonotic.
screenshot_cubemap will now capture half-float images when saving to ktx or dds files.
Fix support for xcf files larger than 4gb, mostly to avoid compiler warnings.
Fixed size of gfx/loading.lmp when replacement textures are used.
Added mipmap support for rg8 and l8a8 textures.
r_hdr_framebuffer cvar updated to support format names instead of random negative numbers. Description updated to name some interesting ones.
Perform autoupdate _checks_ ONLY with explicit user confirmation (actual updating already needed user confirmation, but this extra step should reduce the chances of us getting wrongly accused of exfiltrating user data if we're run in a sandbox - we ONLY ever included the updating engine's version in the checks, though there's nothing we can do to avoid sending the user's router's IP).
Removed the 'summon satan all over your harddrive' quit message, in case paranoid security researchers are idiots and don't bother doing actual research.
Removed the triptohell.info and fte.triptohell.info certificates, they really need to stop being self-signed. The updates domain is still self-signed for autoupdates.
Video drivers are now able to report supported video resolutions, visible to menuqc. Currently only works with SDL2 builds.
Added setmousepos builtin. Should work with glx+win32 build.
VF_SKYROOM_CAMERA can now accept an extra two args, setviewprop(VF_SKYROOM_CAMERA, org, axis, degrees).
Removed v_skyroom_origin+v_skyroom_orientation cvars in favour just v_skyroom, which should make it behave more like the 'fog' command (used when csqc isn't overriding).
Added R_EndPolygonRibbon builtin to make it faster+easier to generate textured ribbon/cable/etc wide lines (for TW).
sdl: Fix up sys_sdl.c's file enumeration to support wildcards in directories.
edit command now displays end1.bin/end2.bin correctly, because we can.
Finally add support for f_modified - though ruleset_allow_larger_models and ruleset_allow_overlong_sounds generally make it redundant.
Fix threading race condition in sha1 lookups.
Updated f_ruleset to include the same extra flags reported by ezquake.
A mod's default.fmf file can now contain an eg 'mainconfig config.cfg' line (to explicitly set the main config saved with cfg_save_auto 1 etc).
fmf: basegame steam:GameName/GameDir can be used to try to load a mod directory from an installed steam game. The resulting gamedir will be read-only.
HOMEDIR CHANGE: use homedirs only if the basedir cannot be written or a homedir already exists, which should further reduce the probability of microsoft randomly uploading our data to their cloud (but mostly because its annoying to never know where your data is written).
Fixed buf_cvarlist, should work in xonotic now, and without segfaults.
Added an extra arg to URI_Get_Callback calls - the response size, also changed the tempstring to contain all bytes of the response, you need to be careful about nulls though.
Try to work around nvidia's forced-panning bug on x11 when changing video modes. This might screw with other programs.
sdl: support custom icons.
sdl: support choosing a specific display.
Added some documentation to menuqc builtins.
menusys: use outlines for slightly more readable fonts.
menusys: switch vid_width and vid_height combos into a single video mode combo to set both according to reported video modes.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5581 fc73d0e0-1445-4013-8a0c-d673dee63da5
2019-11-20 03:09:50 +00:00
|
|
|
unsigned char workspace[64];
|
2012-04-09 19:12:12 +00:00
|
|
|
block = (CHAR64LONG16*)workspace;
|
|
|
|
memcpy(block, buffer, 64);
|
|
|
|
#else
|
|
|
|
block = (CHAR64LONG16*)buffer;
|
|
|
|
#endif
|
|
|
|
/* Copy context->state[] to working vars */
|
|
|
|
a = state[0];
|
|
|
|
b = state[1];
|
|
|
|
c = state[2];
|
|
|
|
d = state[3];
|
|
|
|
e = state[4];
|
|
|
|
/* 4 rounds of 20 operations each. Loop unrolled. */
|
|
|
|
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
|
|
|
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
|
|
|
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
|
|
|
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
|
|
|
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
|
|
|
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
|
|
|
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
|
|
|
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
|
|
|
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
|
|
|
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
|
|
|
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
|
|
|
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
|
|
|
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
|
|
|
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
|
|
|
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
|
|
|
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
|
|
|
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
|
|
|
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
|
|
|
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
|
|
|
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
|
|
|
/* Add the working vars back into context.state[] */
|
|
|
|
state[0] += a;
|
|
|
|
state[1] += b;
|
|
|
|
state[2] += c;
|
|
|
|
state[3] += d;
|
|
|
|
state[4] += e;
|
|
|
|
/* Wipe variables */
|
|
|
|
a = b = c = d = e = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* SHA1Init - Initialize new context */
|
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
static void SHA1Init(void *ctx)
|
2012-04-09 19:12:12 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
SHA1_CTX *context = ctx;
|
2012-04-09 19:12:12 +00:00
|
|
|
/* SHA1 initialization constants */
|
|
|
|
context->state[0] = 0x67452301;
|
|
|
|
context->state[1] = 0xEFCDAB89;
|
|
|
|
context->state[2] = 0x98BADCFE;
|
|
|
|
context->state[3] = 0x10325476;
|
|
|
|
context->state[4] = 0xC3D2E1F0;
|
|
|
|
context->count[0] = context->count[1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Run your data through this. */
|
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
static void SHA1Update(void *ctx, const void* data, size_t len)
|
2012-04-09 19:12:12 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
SHA1_CTX *context = ctx;
|
2018-01-23 01:22:29 +00:00
|
|
|
size_t i, j;
|
2012-04-09 19:12:12 +00:00
|
|
|
|
|
|
|
j = (context->count[0] >> 3) & 63;
|
|
|
|
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
|
|
|
|
context->count[1] += (len >> 29);
|
|
|
|
if ((j + len) > 63)
|
|
|
|
{
|
|
|
|
memcpy(&context->buffer[j], data, (i = 64-j));
|
|
|
|
SHA1Transform(context->state, context->buffer);
|
|
|
|
for ( ; i + 63 < len; i += 64)
|
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
SHA1Transform(context->state, (const qbyte*)data + i);
|
2012-04-09 19:12:12 +00:00
|
|
|
}
|
|
|
|
j = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
i = 0;
|
2020-03-25 21:29:30 +00:00
|
|
|
memcpy(&context->buffer[j], (const qbyte*)data + i, len - i);
|
2012-04-09 19:12:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Add padding and return the message digest. */
|
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
static void SHA1Final(unsigned char digest[SHA1_DIGEST_SIZE], void *ctx)
|
2012-04-09 19:12:12 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
SHA1_CTX *context = ctx;
|
2012-04-09 19:12:12 +00:00
|
|
|
unsigned int i, j;
|
|
|
|
unsigned char finalcount[8];
|
|
|
|
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
|
|
|
}
|
|
|
|
SHA1Update(context, (unsigned char *)"\200", 1);
|
|
|
|
while ((context->count[0] & 504) != 448)
|
|
|
|
{
|
|
|
|
SHA1Update(context, (unsigned char *)"\0", 1);
|
|
|
|
}
|
|
|
|
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
|
2020-03-25 21:29:30 +00:00
|
|
|
for (i = 0; i < SHA1_DIGEST_SIZE; i++)
|
2012-04-09 19:12:12 +00:00
|
|
|
{
|
|
|
|
digest[i] = (unsigned char)
|
|
|
|
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
|
|
|
}
|
|
|
|
/* Wipe variables */
|
|
|
|
i = j = 0;
|
|
|
|
memset(context->buffer, 0, 64);
|
|
|
|
memset(context->state, 0, 20);
|
|
|
|
memset(context->count, 0, 8);
|
|
|
|
memset(&finalcount, 0, 8);
|
|
|
|
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
|
|
|
|
SHA1Transform(context->state, context->buffer);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
hashfunc_t hash_sha1 =
|
2012-04-09 19:12:12 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
SHA1_DIGEST_SIZE,
|
|
|
|
sizeof(SHA1_CTX),
|
|
|
|
SHA1Init,
|
|
|
|
SHA1Update,
|
|
|
|
SHA1Final,
|
|
|
|
};
|
2012-04-09 19:12:12 +00:00
|
|
|
|
2021-04-14 05:21:04 +00:00
|
|
|
unsigned int hashfunc_terminate_uint(const hashfunc_t *func, void *context)
|
|
|
|
{
|
|
|
|
unsigned int r = 0, l;
|
|
|
|
unsigned char *digest = alloca(func->digestsize);
|
|
|
|
func->terminate(digest, context);
|
|
|
|
for (l = 0; l < func->digestsize; l++)
|
|
|
|
r ^= digest[l]<<((l%sizeof(r))*8);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
unsigned int CalcHashInt(const hashfunc_t *func, const unsigned char *data, size_t datasize)
|
|
|
|
{
|
|
|
|
void *ctx = alloca(func->contextsize);
|
|
|
|
func->init(ctx);
|
|
|
|
func->process(ctx, data, datasize);
|
|
|
|
return hashfunc_terminate_uint(func, ctx);
|
|
|
|
}
|
|
|
|
size_t CalcHash(const hashfunc_t *func, unsigned char *digest, size_t maxdigestsize, const unsigned char *string, size_t stringlen)
|
2017-09-20 11:27:13 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
void *ctx = alloca(func->contextsize);
|
|
|
|
if (maxdigestsize < func->digestsize)
|
|
|
|
return 0; //panic
|
|
|
|
func->init(ctx);
|
|
|
|
func->process(ctx, string, stringlen);
|
|
|
|
func->terminate(digest, ctx);
|
|
|
|
return func->digestsize;
|
2017-09-20 11:27:13 +00:00
|
|
|
}
|
|
|
|
|
2013-06-29 16:01:07 +00:00
|
|
|
/* hmac-sha1.c -- hashed message authentication codes
|
|
|
|
Copyright (C) 2005, 2006 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software Foundation,
|
|
|
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
|
|
|
|
|
|
|
/* Written by Simon Josefsson.
|
|
|
|
hacked up a bit by someone else...
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define IPAD 0x36
|
|
|
|
#define OPAD 0x5c
|
|
|
|
|
2014-03-30 08:55:06 +00:00
|
|
|
static void memxor(char *dest, const char *src, size_t length)
|
2013-06-29 16:01:07 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
for (i = 0; i < length; i++)
|
|
|
|
{
|
|
|
|
dest[i] ^= src[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-19 06:37:25 +00:00
|
|
|
//typedef size_t hashfunc_t(unsigned char *digest, size_t maxdigestsize, size_t numstrings, const unsigned char **strings, size_t *stringlens);
|
2021-04-14 05:21:04 +00:00
|
|
|
size_t CalcHMAC(const hashfunc_t *hashfunc, unsigned char *digest, size_t maxdigestsize,
|
2017-09-20 11:27:13 +00:00
|
|
|
const unsigned char *data, size_t datalen,
|
|
|
|
const unsigned char *key, size_t keylen)
|
2013-06-29 16:01:07 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
#define HMAC_DIGEST_MAXSIZE 64
|
|
|
|
qbyte optkeybuf[HMAC_DIGEST_MAXSIZE];
|
|
|
|
qbyte innerhash[HMAC_DIGEST_MAXSIZE];
|
|
|
|
|
|
|
|
qbyte block[64];
|
2013-06-29 16:01:07 +00:00
|
|
|
|
2020-03-25 21:29:30 +00:00
|
|
|
if (hashfunc->digestsize > HMAC_DIGEST_MAXSIZE || hashfunc->digestsize > maxdigestsize)
|
|
|
|
return 0;
|
2013-06-29 16:01:07 +00:00
|
|
|
|
2013-07-13 12:14:32 +00:00
|
|
|
/* Reduce the key's size, so that it is never larger than a block. */
|
2013-06-29 16:01:07 +00:00
|
|
|
|
2017-09-20 11:27:13 +00:00
|
|
|
if (keylen > sizeof(block))
|
2013-06-29 16:01:07 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
qbyte *ctx = alloca(hashfunc->contextsize);
|
|
|
|
hashfunc->init(ctx);
|
|
|
|
hashfunc->process(ctx, key, keylen);
|
|
|
|
hashfunc->terminate(optkeybuf, ctx);
|
2017-09-20 11:27:13 +00:00
|
|
|
key=optkeybuf;
|
2013-06-29 16:01:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute INNERHASH from KEY and IN. */
|
|
|
|
|
|
|
|
memset (block, IPAD, sizeof (block));
|
|
|
|
memxor (block, key, keylen);
|
|
|
|
|
2017-09-20 11:27:13 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
qbyte *ctx = alloca(hashfunc->contextsize);
|
|
|
|
hashfunc->init(ctx);
|
|
|
|
hashfunc->process(ctx, block, sizeof(block));
|
|
|
|
hashfunc->process(ctx, data, datalen);
|
|
|
|
hashfunc->terminate(innerhash, ctx);
|
2017-09-20 11:27:13 +00:00
|
|
|
}
|
2013-06-29 16:01:07 +00:00
|
|
|
|
|
|
|
/* Compute result from KEY and INNERHASH. */
|
|
|
|
|
|
|
|
memset (block, OPAD, sizeof (block));
|
|
|
|
memxor (block, key, keylen);
|
|
|
|
|
2017-09-20 11:27:13 +00:00
|
|
|
{
|
2020-03-25 21:29:30 +00:00
|
|
|
qbyte *ctx = alloca(hashfunc->contextsize);
|
|
|
|
hashfunc->init(ctx);
|
|
|
|
hashfunc->process(ctx, block, sizeof(block));
|
|
|
|
hashfunc->process(ctx, innerhash, hashfunc->digestsize);
|
|
|
|
hashfunc->terminate(digest, ctx);
|
|
|
|
return hashfunc->digestsize;
|
2017-09-20 11:27:13 +00:00
|
|
|
}
|
2013-06-29 16:01:07 +00:00
|
|
|
}
|