PostgreSQL Source Code: contrib/pgcrypto/crypt-sha.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

47

51

53#include "px.h"

54

55typedef enum

56{

61

63"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

64

65

66

67

68char *

69px_crypt_shacrypt(const char *pw, const char *salt, char *passwd, unsigned dstlen)

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;

83 StringInfo decoded_salt = NULL;

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;

97 unsigned int len,

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

128 len = strlen(pw);

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),

140 errmsg("invalid salt"));

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 != '$')

193 errcode(ERRCODE_SYNTAX_ERROR),

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

236 switch (type)

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

401 block = len;

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

435 if ((p_bytes = palloc0(len)) == NULL)

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)

517 px_md_update(digestB, (const unsigned char *) p_bytes, len);

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

557 switch (type)

558 {

560 {

561 b64_from_24bit(sha_buf[0], sha_buf[10], sha_buf[20], 4);

562 b64_from_24bit(sha_buf[21], sha_buf[1], sha_buf[11], 4);

563 b64_from_24bit(sha_buf[12], sha_buf[22], sha_buf[2], 4);

564 b64_from_24bit(sha_buf[3], sha_buf[13], sha_buf[23], 4);

565 b64_from_24bit(sha_buf[24], sha_buf[4], sha_buf[14], 4);

566 b64_from_24bit(sha_buf[15], sha_buf[25], sha_buf[5], 4);

567 b64_from_24bit(sha_buf[6], sha_buf[16], sha_buf[26], 4);

568 b64_from_24bit(sha_buf[27], sha_buf[7], sha_buf[17], 4);

569 b64_from_24bit(sha_buf[18], sha_buf[28], sha_buf[8], 4);

570 b64_from_24bit(sha_buf[9], sha_buf[19], sha_buf[29], 4);

572

573 break;

574 }

575

577 {

578 b64_from_24bit(sha_buf[0], sha_buf[21], sha_buf[42], 4);

579 b64_from_24bit(sha_buf[22], sha_buf[43], sha_buf[1], 4);

580 b64_from_24bit(sha_buf[44], sha_buf[2], sha_buf[23], 4);

581 b64_from_24bit(sha_buf[3], sha_buf[24], sha_buf[45], 4);

582 b64_from_24bit(sha_buf[25], sha_buf[46], sha_buf[4], 4);

583 b64_from_24bit(sha_buf[47], sha_buf[5], sha_buf[26], 4);

584 b64_from_24bit(sha_buf[6], sha_buf[27], sha_buf[48], 4);

585 b64_from_24bit(sha_buf[28], sha_buf[49], sha_buf[7], 4);

586 b64_from_24bit(sha_buf[50], sha_buf[8], sha_buf[29], 4);

587 b64_from_24bit(sha_buf[9], sha_buf[30], sha_buf[51], 4);

588 b64_from_24bit(sha_buf[31], sha_buf[52], sha_buf[10], 4);

589 b64_from_24bit(sha_buf[53], sha_buf[11], sha_buf[32], 4);

590 b64_from_24bit(sha_buf[12], sha_buf[33], sha_buf[54], 4);

591 b64_from_24bit(sha_buf[34], sha_buf[55], sha_buf[13], 4);

592 b64_from_24bit(sha_buf[56], sha_buf[14], sha_buf[35], 4);

593 b64_from_24bit(sha_buf[15], sha_buf[36], sha_buf[57], 4);

594 b64_from_24bit(sha_buf[37], sha_buf[58], sha_buf[16], 4);

595 b64_from_24bit(sha_buf[59], sha_buf[17], sha_buf[38], 4);

596 b64_from_24bit(sha_buf[18], sha_buf[39], sha_buf[60], 4);

597 b64_from_24bit(sha_buf[40], sha_buf[61], sha_buf[19], 4);

598 b64_from_24bit(sha_buf[62], sha_buf[20], sha_buf[41], 4);

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

621 px_memset(&sha_buf, 0, sizeof sha_buf);

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}

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)