63"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
71 static const char rounds_prefix[] =
"rounds=";
72 static const char *magic_bytes[2] = {
"$5$",
"$6$"};
78 PX_MD *digestA = NULL;
79 PX_MD *digestB = NULL;
82 const char *dec_salt_binary;
88 char rounds_custom = 0;
92 const char *fp = NULL;
93 const char *ep = NULL;
105 elog(
ERROR,
"null value for password rejected");
108 elog(
ERROR,
"null value for salt rejected");
114 elog(
ERROR,
"insufficient result buffer size to encrypt password");
121 memset(&sha_buf,
'\0',
sizeof(sha_buf));
122 memset(&sha_buf_tmp,
'\0',
sizeof(sha_buf_tmp));
129 dec_salt_binary = salt;
137 if (strlen(dec_salt_binary) < 3)
139 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
146 if ((dec_salt_binary[0] !=
'$') || (dec_salt_binary[2] !=
'$'))
148 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
149 errmsg(
"invalid format of salt"),
150 errhint(
"magic byte format for shacrypt is either \"$5$\" or \"$6$\""));
158 if (strncmp(dec_salt_binary, magic_bytes[0], strlen(magic_bytes[0])) == 0)
161 dec_salt_binary += strlen(magic_bytes[0]);
163 else if (strncmp(dec_salt_binary, magic_bytes[1], strlen(magic_bytes[1])) == 0)
166 dec_salt_binary += strlen(magic_bytes[1]);
184 if (strncmp(dec_salt_binary,
185 rounds_prefix,
sizeof(rounds_prefix) - 1) == 0)
187 const char *num = dec_salt_binary +
sizeof(rounds_prefix) - 1;
189 int srounds =
strtoint(num, &endp, 10);
194 errmsg(
"could not parse salt options"));
196 dec_salt_binary = endp + 1;
212 errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
213 errmsg(
"rounds=%d exceeds maximum supported value (%d), using %d instead",
221 errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
222 errmsg(
"rounds=%d is below supported value (%d), using %d instead",
228 rounds = (
uint32) srounds;
274 elog(
ERROR,
"unknown crypt identifier \"%c\"", salt[1]);
277 if (rounds_custom > 0)
293 for (ep = dec_salt_binary;
307 fp = strstr(dec_salt_binary, magic_bytes[0]);
309 elog(
ERROR,
"bogus magic byte found in salt string");
311 fp = strstr(dec_salt_binary, magic_bytes[1]);
313 elog(
ERROR,
"bogus magic byte found in salt string");
319 fp = strstr(dec_salt_binary, rounds_prefix);
321 elog(
ERROR,
"invalid rounds option specified in salt string");
329 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
330 errmsg(
"invalid character in salt string: \"%.*s\"",
344 if (decoded_salt->
len > 0)
349 salt_len = decoded_salt->
len;
351 elog(
DEBUG1,
"using salt \"%s\", salt len = %d, rounds = %u",
352 decoded_salt->
data, decoded_salt->
len, rounds);
358 if (out_buf->
len > (3 + 17 * rounds_custom + salt_len))
359 elog(
ERROR,
"unexpected length of salt string");
367 px_md_update(digestA, (
const unsigned char *) decoded_salt->
data, salt_len);
377 px_md_update(digestB, (
const unsigned char *) dec_salt_binary, salt_len);
384 for (block =
len; block > buf_size; block -= buf_size)
405 (block & 1) ? sha_buf : (
const unsigned char *) pw,
406 (block & 1) ? buf_size :
len);
422 for (block =
len; block > 0; block--)
441 for (cp = p_bytes, block =
len; block > buf_size; block -= buf_size, cp += buf_size)
442 memcpy(cp, sha_buf_tmp, buf_size);
443 memcpy(cp, sha_buf_tmp, block);
455 for (block = 16 + sha_buf[0]; block > 0; block--)
456 px_md_update(digestB, (
const unsigned char *) dec_salt_binary, salt_len);
472 if ((s_bytes =
palloc0(salt_len)) == NULL)
475 for (cp = s_bytes, block = salt_len; block > buf_size; block -= buf_size, cp += buf_size)
476 memcpy(cp, sha_buf_tmp, buf_size);
477 memcpy(cp, sha_buf_tmp, block);
480 px_memset(&sha_buf_tmp, 0,
sizeof sha_buf);
492 for (block = 0; block < rounds; block++)
508 (block & 1) ? (
const unsigned char *) p_bytes : sha_buf,
509 (block & 1) ?
len : buf_size);
512 if ((block % 3) != 0)
513 px_md_update(digestB, (
const unsigned char *) s_bytes, salt_len);
516 if ((block % 7) != 0)
524 (block & 1) ? sha_buf : (
const unsigned char *) p_bytes,
525 (block & 1) ? buf_size :
len);
546#define b64_from_24bit(B2, B1, B0, N) \
548 unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
552 appendStringInfoCharMacro(out_buf, _crypt_itoa64[w & 0x3f]); \
606 elog(
ERROR,
"unsupported digest length");
618 memcpy(passwd, out_buf->
data, out_buf->
len);
639 errcode(ERRCODE_INTERNAL_ERROR),
640 errmsg(
"cannot create encrypted password"));
char * px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstlen)
#define b64_from_24bit(B2, B1, B0, N)
static const char _crypt_itoa64[64+1]
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void err(int eval, const char *fmt,...)
int pg_mblen(const char *mbstr)
void pfree(void *pointer)
void * palloc0(Size size)
#define CHECK_FOR_INTERRUPTS()
int px_find_digest(const char *name, PX_MD **res)
#define PX_SHACRYPT_ROUNDS_MAX
#define PX_SHACRYPT_BUF_LEN
#define PX_SHACRYPT_ROUNDS_MIN
#define PX_SHACRYPT_DIGEST_MAX_LEN
#define PX_SHACRYPT_SALT_MAX_LEN
#define PX_SHACRYPT_ROUNDS_DEFAULT
void px_memset(void *ptr, int c, size_t len)
#define px_md_finish(md, buf)
#define px_md_update(md, data, dlen)
int strtoint(const char *pg_restrict str, char **pg_restrict endptr, int base)
void destroyStringInfo(StringInfo str)
void appendStringInfo(StringInfo str, const char *fmt,...)
StringInfo makeStringInfoExt(int initsize)
void appendStringInfoString(StringInfo str, const char *s)
#define appendStringInfoCharMacro(str, ch)