|
Packit |
13e0ca |
/*
|
|
Packit |
13e0ca |
* Written by Solar Designer and placed in the public domain.
|
|
Packit |
13e0ca |
* See crypt-bcrypt.c for more information.
|
|
Packit |
13e0ca |
*
|
|
Packit |
13e0ca |
* This file contains setting-string generation code shared among the
|
|
Packit |
13e0ca |
* MD5, SHA256, and SHA512 hash algorithms, which use very similar
|
|
Packit |
13e0ca |
* setting formats. Setting-string generation for bcrypt and DES is
|
|
Packit |
13e0ca |
* entirely in crypt-bcrypt.c and crypt-des.c respectively.
|
|
Packit |
13e0ca |
*/
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#include "crypt-port.h"
|
|
Packit |
13e0ca |
#include "crypt-private.h"
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#include <errno.h>
|
|
Packit |
13e0ca |
#include <stdio.h>
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#if INCLUDE_md5 || INCLUDE_sha256 || INCLUDE_sha512
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
static const unsigned char _xcrypt_itoa64[64 + 1] =
|
|
Packit |
13e0ca |
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
void
|
|
Packit |
13e0ca |
gensalt_sha_rn (char tag, size_t maxsalt, unsigned long defcount,
|
|
Packit |
13e0ca |
unsigned long mincount, unsigned long maxcount,
|
|
Packit |
13e0ca |
unsigned long count,
|
|
Packit |
13e0ca |
const uint8_t *rbytes, size_t nrbytes,
|
|
Packit |
13e0ca |
uint8_t *output, size_t output_size)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
if (count == 0)
|
|
Packit |
13e0ca |
count = defcount;
|
|
Packit |
13e0ca |
if (count < mincount || count > maxcount)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* We will use more rbytes if available, but at least this much is
|
|
Packit |
13e0ca |
required. */
|
|
Packit |
13e0ca |
if (nrbytes < 3)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = EINVAL;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* Compute how much space we need. */
|
|
Packit |
13e0ca |
size_t output_len = 8; /* $x$ssss\0 */
|
|
Packit |
13e0ca |
if (count != defcount)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
output_len += 9; /* rounds=1$ */
|
|
Packit |
13e0ca |
for (unsigned long ceiling = 10; ceiling < count; ceiling *= 10)
|
|
Packit |
13e0ca |
output_len += 1;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
if (output_size < output_len)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
errno = ERANGE;
|
|
Packit |
13e0ca |
return;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
size_t written;
|
|
Packit |
13e0ca |
if (count == defcount)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
output[0] = '$';
|
|
Packit |
13e0ca |
output[1] = (unsigned char)tag;
|
|
Packit |
13e0ca |
output[2] = '$';
|
|
Packit |
13e0ca |
written = 3;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
else
|
|
Packit |
13e0ca |
written = (size_t) snprintf ((char *)output, output_size,
|
|
Packit |
13e0ca |
"$%c$rounds=%lu$", tag, count);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
/* The length calculation above should ensure that this is always true. */
|
|
Packit |
13e0ca |
assert (written + 5 < output_size);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
size_t used_rbytes = 0;
|
|
Packit |
13e0ca |
while (written + 5 < output_size &&
|
|
Packit |
13e0ca |
used_rbytes + 3 < nrbytes &&
|
|
Packit |
13e0ca |
(used_rbytes * 4 / 3) < maxsalt)
|
|
Packit |
13e0ca |
{
|
|
Packit |
13e0ca |
unsigned long value =
|
|
Packit |
13e0ca |
((unsigned long) (unsigned char) rbytes[used_rbytes + 0] << 0) |
|
|
Packit |
13e0ca |
((unsigned long) (unsigned char) rbytes[used_rbytes + 1] << 8) |
|
|
Packit |
13e0ca |
((unsigned long) (unsigned char) rbytes[used_rbytes + 2] << 16);
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[written + 0] = _xcrypt_itoa64[value & 0x3f];
|
|
Packit |
13e0ca |
output[written + 1] = _xcrypt_itoa64[(value >> 6) & 0x3f];
|
|
Packit |
13e0ca |
output[written + 2] = _xcrypt_itoa64[(value >> 12) & 0x3f];
|
|
Packit |
13e0ca |
output[written + 3] = _xcrypt_itoa64[(value >> 18) & 0x3f];
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
written += 4;
|
|
Packit |
13e0ca |
used_rbytes += 3;
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
output[written] = '\0';
|
|
Packit |
13e0ca |
}
|
|
Packit |
13e0ca |
|
|
Packit |
13e0ca |
#endif
|