70{
71 static const char rounds_prefix[] = "rounds=";
72 static const char *magic_bytes[2] = {"$5$", "$6$"};
73
74
76
78 PX_MD *digestA = NULL;
79 PX_MD *digestB = NULL;
81
82 const char *dec_salt_binary;
85
86
88 char rounds_custom = 0;
89 char *p_bytes = NULL;
90 char *s_bytes = NULL;
91 char *cp = NULL;
92 const char *fp = NULL;
93 const char *ep = NULL;
94 size_t buf_size = 0;
95 unsigned int block;
98 salt_len = 0;
99
100
101 if (!passwd)
102 return NULL;
103
104 if (pw == NULL)
105 elog(
ERROR,
"null value for password rejected");
106
107 if (salt == NULL)
108 elog(
ERROR,
"null value for salt rejected");
109
110
111
112
114 elog(
ERROR,
"insufficient result buffer size to encrypt password");
115
116
119
120
121 memset(&sha_buf, '\0', sizeof(sha_buf));
122 memset(&sha_buf_tmp, '\0', sizeof(sha_buf_tmp));
123
124
125
126
127
129 dec_salt_binary = salt;
130
131
132
133
134
135
136
137 if (strlen(dec_salt_binary) < 3)
139 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
141
142
143
144
145
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$\""));
151
152
153
154
155
156
157
158 if (strncmp(dec_salt_binary, magic_bytes[0], strlen(magic_bytes[0])) == 0)
159 {
161 dec_salt_binary += strlen(magic_bytes[0]);
162 }
163 else if (strncmp(dec_salt_binary, magic_bytes[1], strlen(magic_bytes[1])) == 0)
164 {
166 dec_salt_binary += strlen(magic_bytes[1]);
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184 if (strncmp(dec_salt_binary,
185 rounds_prefix, sizeof(rounds_prefix) - 1) == 0)
186 {
187 const char *num = dec_salt_binary + sizeof(rounds_prefix) - 1;
188 char *endp;
189 int srounds =
strtoint(num, &endp, 10);
190
191 if (*endp != '$')
194 errmsg(
"could not parse salt options"));
195
196 dec_salt_binary = endp + 1;
197
198
199
200
201
202
203
204
205
206
207
208
210 {
212 errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
213 errmsg(
"rounds=%d exceeds maximum supported value (%d), using %d instead",
217 }
219 {
221 errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
222 errmsg(
"rounds=%d is below supported value (%d), using %d instead",
226 }
227
228 rounds = (
uint32) srounds;
229 rounds_custom = 1;
230 }
231
232
233
234
235
237 {
239 {
240
244
248
249
250 buf_size = 32;
251
253 break;
254 }
255
257 {
258
262
266
268
270 break;
271 }
272
274 elog(
ERROR,
"unknown crypt identifier \"%c\"", salt[1]);
275 }
276
277 if (rounds_custom > 0)
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293 for (ep = dec_salt_binary;
295 ep++)
296 {
297
298
299
300
301
302
303
304
305
306
307 fp = strstr(dec_salt_binary, magic_bytes[0]);
308 if (fp != NULL)
309 elog(
ERROR,
"bogus magic byte found in salt string");
310
311 fp = strstr(dec_salt_binary, magic_bytes[1]);
312 if (fp != NULL)
313 elog(
ERROR,
"bogus magic byte found in salt string");
314
315
316
317
318
319 fp = strstr(dec_salt_binary, rounds_prefix);
320 if (fp != NULL)
321 elog(
ERROR,
"invalid rounds option specified in salt string");
322
323 if (*ep != '$')
324 {
327 else
329 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
330 errmsg(
"invalid character in salt string: \"%.*s\"",
332 }
333 else
334 {
335
336
337
338
339
340
341
342
343
344 if (decoded_salt->
len > 0)
345 break;
346 }
347 }
348
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);
353
354
355
356
357
358 if (out_buf->
len > (3 + 17 * rounds_custom + salt_len))
359 elog(
ERROR,
"unexpected length of salt string");
360
361
362
363
364
365
367 px_md_update(digestA, (
const unsigned char *) decoded_salt->
data, salt_len);
368
369
370
371
372
373
374
375
377 px_md_update(digestB, (
const unsigned char *) dec_salt_binary, salt_len);
380
381
382
383
384 for (block =
len; block > buf_size; block -= buf_size)
386
387
388
389
390
392
393
394
395
396
397
398
399
400
402 while (block)
403 {
405 (block & 1) ? sha_buf : (const unsigned char *) pw,
406 (block & 1) ? buf_size :
len);
407
408
409 block >>= 1;
410 }
411
412
414
415
417
418
419
420
421
422 for (block =
len; block > 0; block--)
424
425
427
428
429
430
431
432
433
434
436 {
438 }
439
440
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);
444
445
446
447
449
450
451
452
453
454
455 for (block = 16 + sha_buf[0]; block > 0; block--)
456 px_md_update(digestB, (
const unsigned char *) dec_salt_binary, salt_len);
457
458
459
460
462
463
464
465
466
467
468
469
470
471
472 if ((s_bytes =
palloc0(salt_len)) == NULL)
474
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);
478
479
480 px_memset(&sha_buf_tmp, 0,
sizeof sha_buf);
481
482
483
484
485
486
487
488
489
490
491
492 for (block = 0; block < rounds; block++)
493 {
494
495
496
497
499
500
502
503
504
505
506
508 (block & 1) ? (const unsigned char *) p_bytes : sha_buf,
509 (block & 1) ?
len : buf_size);
510
511
512 if ((block % 3) != 0)
513 px_md_update(digestB, (
const unsigned char *) s_bytes, salt_len);
514
515
516 if ((block % 7) != 0)
518
519
520
521
522
524 (block & 1) ? sha_buf : (const unsigned char *) p_bytes,
525 (block & 1) ? buf_size :
len);
526
527
529 }
530
533
534 digestA = NULL;
535 digestB = NULL;
536
539
540 s_bytes = NULL;
541 p_bytes = NULL;
542
543
545
546#define b64_from_24bit(B2, B1, B0, N) \
547 do { \
548 unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
549 int i = (N); \
550 while (i-- > 0) \
551 { \
552 appendStringInfoCharMacro(out_buf, _crypt_itoa64[w & 0x3f]); \
553 w >>= 6; \
554 } \
555 } while (0)
556
558 {
560 {
572
573 break;
574 }
575
577 {
600
601 break;
602 }
603
605
606 elog(
ERROR,
"unsupported digest length");
607 }
608
609
610
611
612
613
614
615
616
617
618 memcpy(passwd, out_buf->
data, out_buf->
len);
619
620
624
625
626 return passwd;
627
629 if (digestA != NULL)
631
632 if (digestB != NULL)
634
637
639 errcode(ERRCODE_INTERNAL_ERROR),
640 errmsg(
"cannot create encrypted password"));
641 return NULL;
642}
#define b64_from_24bit(B2, B1, B0, N)
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)