1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-05 13:16:09 +03:00
Files
mariadb/plugin/auth_mysql_sha2/sha256crypt.c
Sergei Golubchik 63583b0824 MDEV-9804 Implement a caching_sha2_password plugin
but without caching
2025-07-27 13:57:06 +02:00

121 lines
4.5 KiB
C

/*
Copyright (c) 2025, MariaDB plc
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; version 2 of the License.
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-1335 USA */
#include <my_alloca.h>
#include "mysql_sha2.h"
/* based on https://www.akkadia.org/drepper/SHA-crypt.txt */
/* SHA256-based Unix crypt implementation.
Released into the Public Domain by Ulrich Drepper <drepper@redhat.com>. */
void sha256_crypt_r(const unsigned char *key, size_t key_len,
const unsigned char *salt, size_t salt_len,
unsigned char *buffer, size_t rounds)
{
unsigned char tmp[SHA256_DIGEST_LENGTH];
unsigned char alt[SHA256_DIGEST_LENGTH];
size_t cnt;
static const char b64t[64] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
void *ctx = alloca(my_sha256_context_size());
unsigned char *p_bytes = alloca(key_len);
unsigned char *s_bytes = alloca(salt_len);
my_sha256_multi(alt, key, key_len, salt, salt_len, key, key_len, NULL);
my_sha256_init(ctx);
my_sha256_input(ctx, key, key_len);
my_sha256_input(ctx, salt, salt_len);
/* Add for every byte in the key one byte of the alternate sum. */
for (cnt = key_len; cnt > sizeof(alt); cnt -= sizeof(alt))
my_sha256_input(ctx, alt, sizeof(alt));
my_sha256_input(ctx, alt, cnt);
/* Take the binary representation of the length of the key and for every
1 add the alternate sum, for every 0 the key. */
for (cnt = key_len; cnt > 0; cnt >>= 1)
if ((cnt & 1) != 0)
my_sha256_input(ctx, alt, sizeof(alt));
else
my_sha256_input(ctx, key, key_len);
my_sha256_result(ctx, alt);
/* Start computing S byte sequence. */
my_sha256_init(ctx);
for (cnt = 0; cnt < 16u + alt[0]; ++cnt)
my_sha256_input(ctx, salt, salt_len);
my_sha256_result(ctx, tmp);
/* Create byte sequence S. */
for (cnt = salt_len; cnt >= sizeof(tmp); cnt -= sizeof(tmp))
memcpy(s_bytes + salt_len - cnt, tmp, sizeof(tmp));
memcpy(s_bytes + salt_len - cnt, tmp, cnt);
/* Start computing P byte sequence. */
my_sha256_init(ctx);
for (cnt = 0; cnt < key_len; ++cnt)
my_sha256_input(ctx, key, key_len);
my_sha256_result(ctx, tmp);
/* Create byte sequence P. */
for (cnt = key_len; cnt >= sizeof(tmp); cnt -= sizeof(tmp))
memcpy(p_bytes + key_len - cnt, tmp, sizeof(tmp));
memcpy(p_bytes + key_len - cnt, tmp, cnt);
/* Repeatedly run the collected hash value through SHA256 to burn
CPU cycles. */
for (cnt = 0; cnt < rounds; ++cnt)
{
my_sha256_init(ctx);
if ((cnt & 1) != 0)
my_sha256_input(ctx, p_bytes, key_len);
else
my_sha256_input(ctx, cnt ? tmp : alt, sizeof(tmp));
if (cnt % 3 != 0)
my_sha256_input(ctx, s_bytes, salt_len);
if (cnt % 7 != 0)
my_sha256_input(ctx, p_bytes, key_len);
if ((cnt & 1) != 0)
my_sha256_input(ctx, tmp, sizeof(tmp));
else
my_sha256_input(ctx, p_bytes, key_len);
my_sha256_result(ctx, tmp);
}
#define b64_from_24bit(B2, B1, B0, N) \
do { \
unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
int n = (N); \
while (n-- > 0) \
{ \
*buffer++ = b64t[w & 0x3f]; \
w >>= 6; \
} \
} while (0)
b64_from_24bit (tmp[0], tmp[10], tmp[20], 4);
b64_from_24bit (tmp[21], tmp[1], tmp[11], 4);
b64_from_24bit (tmp[12], tmp[22], tmp[2], 4);
b64_from_24bit (tmp[3], tmp[13], tmp[23], 4);
b64_from_24bit (tmp[24], tmp[4], tmp[14], 4);
b64_from_24bit (tmp[15], tmp[25], tmp[5], 4);
b64_from_24bit (tmp[6], tmp[16], tmp[26], 4);
b64_from_24bit (tmp[27], tmp[7], tmp[17], 4);
b64_from_24bit (tmp[18], tmp[28], tmp[8], 4);
b64_from_24bit (tmp[9], tmp[19], tmp[29], 4);
b64_from_24bit (0, tmp[31], tmp[30], 3); /* == 43 bytes in total */
}