new code - sha512 internal

This commit is contained in:
joonicks
2025-11-16 14:51:46 +01:00
parent 3eb9ec6f45
commit b6dce82e2d

View File

@@ -16,13 +16,15 @@
/* public domain sha512 implementation based on fips180-3 */ /* public domain sha512 implementation based on fips180-3 */
/* >=2^64 bits messages are not supported (about 2000 peta bytes) */ /* >=2^64 bits messages are not supported (about 2000 peta bytes) */
struct sha512 { struct sha512
uint64_t len; /* processed message length */ {
uint64_t h[8]; /* hash state */ uint64_t len; /* processed message length */
uint8_t buf[128]; /* message block buffer */ uint64_t h[8]; /* hash state */
uint8_t buf[128]; /* message block buffer */
}; };
static uint64_t ror(uint64_t n, int k) { return (n >> k) | (n << (64-k)); } static uint64_t ror(uint64_t n, int k) { return (n >> k) | (n << (64-k)); }
#define Ch(x,y,z) (z ^ (x & (y ^ z))) #define Ch(x,y,z) (z ^ (x & (y ^ z)))
#define Maj(x,y,z) ((x & y) | (z & (x | y))) #define Maj(x,y,z) ((x & y) | (z & (x | y)))
#define S0(x) (ror(x,28) ^ ror(x,34) ^ ror(x,39)) #define S0(x) (ror(x,28) ^ ror(x,34) ^ ror(x,39))
@@ -30,7 +32,8 @@ static uint64_t ror(uint64_t n, int k) { return (n >> k) | (n << (64-k)); }
#define R0(x) (ror(x,1) ^ ror(x,8) ^ (x>>7)) #define R0(x) (ror(x,1) ^ ror(x,8) ^ (x>>7))
#define R1(x) (ror(x,19) ^ ror(x,61) ^ (x>>6)) #define R1(x) (ror(x,19) ^ ror(x,61) ^ (x>>6))
static const uint64_t K[80] = { static const uint64_t K[80] =
{
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
@@ -56,10 +59,11 @@ static const uint64_t K[80] = {
static void processblock(struct sha512 *s, const uint8_t *buf) static void processblock(struct sha512 *s, const uint8_t *buf)
{ {
uint64_t W[80], t1, t2, a, b, c, d, e, f, g, h; uint64_t W[80], t1, t2, a, b, c, d, e, f, g, h;
int i; int i;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++)
W[i] = (uint64_t)buf[8*i]<<56; {
W[i] = (uint64_t)buf[8*i]<<56;
W[i] |= (uint64_t)buf[8*i+1]<<48; W[i] |= (uint64_t)buf[8*i+1]<<48;
W[i] |= (uint64_t)buf[8*i+2]<<40; W[i] |= (uint64_t)buf[8*i+2]<<40;
W[i] |= (uint64_t)buf[8*i+3]<<32; W[i] |= (uint64_t)buf[8*i+3]<<32;
@@ -78,7 +82,8 @@ static void processblock(struct sha512 *s, const uint8_t *buf)
f = s->h[5]; f = s->h[5];
g = s->h[6]; g = s->h[6];
h = s->h[7]; h = s->h[7];
for (i = 0; i < 80; i++) { for (i = 0; i < 80; i++)
{
t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i]; t1 = h + S1(e) + Ch(e,f,g) + K[i] + W[i];
t2 = S0(a) + Maj(a,b,c); t2 = S0(a) + Maj(a,b,c);
h = g; h = g;
@@ -105,7 +110,8 @@ static void pad(struct sha512 *s)
unsigned r = s->len % 128; unsigned r = s->len % 128;
s->buf[r++] = 0x80; s->buf[r++] = 0x80;
if (r > 112) { if (r > 112)
{
memset(s->buf + r, 0, 128 - r); memset(s->buf + r, 0, 128 - r);
r = 0; r = 0;
processblock(s, s->buf); processblock(s, s->buf);
@@ -141,8 +147,9 @@ static void sha512_sum(struct sha512 *s, uint8_t *md)
int i; int i;
pad(s); pad(s);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++)
md[8*i] = s->h[i] >> 56; {
md[8*i] = s->h[i] >> 56;
md[8*i+1] = s->h[i] >> 48; md[8*i+1] = s->h[i] >> 48;
md[8*i+2] = s->h[i] >> 40; md[8*i+2] = s->h[i] >> 40;
md[8*i+3] = s->h[i] >> 32; md[8*i+3] = s->h[i] >> 32;
@@ -159,8 +166,10 @@ static void sha512_update(struct sha512 *s, const void *m, unsigned long len)
unsigned r = s->len % 128; unsigned r = s->len % 128;
s->len += len; s->len += len;
if (r) { if (r)
if (len < 128 - r) { {
if (len < 128 - r)
{
memcpy(s->buf + r, p, len); memcpy(s->buf + r, p, len);
return; return;
} }
@@ -179,7 +188,8 @@ static const unsigned char b64[] =
static char *to64(char *s, unsigned int u, int n) static char *to64(char *s, unsigned int u, int n)
{ {
while (--n >= 0) { while (--n >= 0)
{
*s++ = b64[u % 64]; *s++ = b64[u % 64];
u /= 64; u /= 64;
} }
@@ -210,7 +220,6 @@ static char *sha512crypt(const char *key, const char *setting, char *output)
struct sha512 ctx; struct sha512 ctx;
unsigned char md[64], kmd[64], smd[64]; unsigned char md[64], kmd[64], smd[64];
unsigned int i, r, klen, slen; unsigned int i, r, klen, slen;
char rounds[20] = "";
const char *salt; const char *salt;
char *p; char *p;
@@ -226,38 +235,6 @@ static char *sha512crypt(const char *key, const char *setting, char *output)
salt = setting + 3; salt = setting + 3;
r = ROUNDS_DEFAULT; r = ROUNDS_DEFAULT;
if (strncmp(salt, "rounds=", sizeof "rounds=" - 1) == 0) {
unsigned long u;
char *end;
/*
* this is a deviation from the reference:
* bad rounds setting is rejected if it is
* - empty
* - unterminated (missing '$')
* - begins with anything but a decimal digit
* the reference implementation treats these bad
* rounds as part of the salt or parse them with
* strtoul semantics which may cause problems
* including non-portable hashes that depend on
* the host's value of ULONG_MAX.
*/
salt += sizeof "rounds=" - 1;
if (!isdigit(*salt))
return 0;
u = strtoul(salt, &end, 10);
if (*end != '$')
return 0;
salt = end+1;
if (u < ROUNDS_MIN)
r = ROUNDS_MIN;
else if (u > ROUNDS_MAX)
return 0;
else
r = u;
/* needed when rounds is zero prefixed or out of bounds */
sprintf(rounds, "rounds=%u$", r);
}
for (i = 0; i < SALT_MAX && salt[i] && salt[i] != '$'; i++) for (i = 0; i < SALT_MAX && salt[i] && salt[i] != '$'; i++)
/* reject characters that interfere with /etc/shadow parsing */ /* reject characters that interfere with /etc/shadow parsing */
@@ -297,27 +274,31 @@ static char *sha512crypt(const char *key, const char *setting, char *output)
sha512_sum(&ctx, smd); sha512_sum(&ctx, smd);
/* iterate A = f(A,DP,DS), this step takes O(rounds*klen) time */ /* iterate A = f(A,DP,DS), this step takes O(rounds*klen) time */
for (i = 0; i < r; i++) { for (i = 0; i < r; i++)
{
sha512_init(&ctx); sha512_init(&ctx);
if (i % 2) if (i % 2)
hashmd(&ctx, klen, kmd); hashmd(&ctx, klen, kmd);
else else
sha512_update(&ctx, md, sizeof md); sha512_update(&ctx, md, sizeof md);
if (i % 3) if (i % 3)
sha512_update(&ctx, smd, slen); sha512_update(&ctx, smd, slen);
if (i % 7) if (i % 7)
hashmd(&ctx, klen, kmd); hashmd(&ctx, klen, kmd);
if (i % 2) if (i % 2)
sha512_update(&ctx, md, sizeof md); sha512_update(&ctx, md, sizeof md);
else else
hashmd(&ctx, klen, kmd); hashmd(&ctx, klen, kmd);
sha512_sum(&ctx, md); sha512_sum(&ctx, md);
} }
/* output is $6$rounds=n$salt$hash */ /* output is $6$salt$hash */
p = output; p = output;
p += sprintf(p, "$6$%s%.*s$", rounds, slen, salt); p += sprintf(p, "$6$%.*s$", slen, salt);
#if 1 #if 0
static const unsigned char perm[][3] = { static const unsigned char perm[][3] = {
0,21,42,22,43,1,44,2,23,3,24,45,25,46,4, 0,21,42,22,43,1,44,2,23,3,24,45,25,46,4,
47,5,26,6,27,48,28,49,7,50,8,29,9,30,51, 47,5,26,6,27,48,28,49,7,50,8,29,9,30,51,
@@ -354,18 +335,36 @@ static char *sha512crypt(const char *key, const char *setting, char *output)
return output; return output;
} }
char *__crypt_sha512(const char *key, const char *setting, char *output) char sha512_buffer[128];
{
static const char testkey[] = "Xy01@#\x01\x02\x80\x7f\xff\r\n\x81\t !";
static const char testsetting[] = "$6$rounds=1234$abc0123456789$";
static const char testhash[] = "$6$rounds=1234$abc0123456789$BCpt8zLrc/RcyuXmCDOE1ALqMXB2MH6n1g891HhFj8.w7LxGv.FTkqq6Vxc/km3Y0jE0j24jY5PIv/oOu6reg1";
char testbuf[128];
char *p, *q;
p = sha512crypt(key, setting, output); char *crypt_sha512(const char *key, const char *salt)
/* self test and stack cleanup */ {
q = sha512crypt(testkey, testsetting, testbuf); return(sha512crypt(key,salt,sha512_buffer));
if (!p || q != testbuf || memcmp(testbuf, testhash, sizeof testhash))
return "*";
return p;
} }
#ifdef TEST
const char thash1[] = "$6$5c05$WlQbKv/GYeXzSPNsn9bzpfqlDjOCbt8JlhSa2uALujoq6tWn3utZ3jE428lxBAfcJYHfecF59s6Dxg0fLIX7a/";
int main(int argc, char **argv, char **envp)
{
const char mytest[] = "mytestpassword";
const char mysalt[] = "$6$5c05$";
char *s;
int r;
s = crypt_sha512(mytest,mysalt);
r = strcmp(thash1,s);
if (r == 0)
{
printf("SHA512\n");
}
else
{
printf("FAIL\n");
printf("%i\n%s\%s\n",r,thash1,s);
}
}
#endif /* TEST */