PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
crypt-blowfish.c File Reference
#include "postgres.h"
#include "miscadmin.h"
#include "px-crypt.h"
#include "px.h"
Include dependency graph for crypt-blowfish.c:

Go to the source code of this file.

Data Structures

struct  BF_ctx
 

Macros

#define BF_ASM   0
 
#define BF_SCALE   0
 
#define BF_N   16
 
#define BF_safe_atoi64(dst, src)
 
#define BF_INDEX(S, i)    (*((BF_word *)(((unsigned char *)(S)) + (i))))
 
#define BF_ROUND(L, R, N)
 
#define BF_ENCRYPT
 
#define BF_body()
 

Typedefs

typedef unsigned int BF_word
 
typedef signed int BF_word_signed
 
typedef BF_word BF_key[BF_N+2]
 

Functions

static int BF_decode (BF_word *dst, const char *src, int size)
 
static void BF_encode (char *dst, const BF_word *src, int size)
 
static void BF_swap (BF_word *x, int count)
 
static void BF_set_key (const char *key, BF_key expanded, BF_key initial, int sign_extension_bug)
 
char * _crypt_blowfish_rn (const char *key, const char *setting, char *output, int size)
 

Variables

static BF_word BF_magic_w [6]
 
static BF_ctx BF_init_state
 
static unsigned char BF_itoa64 [64+1]
 
static unsigned char BF_atoi64 [0x60]
 

Macro Definition Documentation

◆ BF_ASM

#define BF_ASM   0

Definition at line 48 of file crypt-blowfish.c.

◆ BF_body

#define BF_body ( )
Value:
do { \
L = R = 0; \
ptr = data.ctx.P; \
do { \
ptr += 2; \
BF_ENCRYPT; \
*(ptr - 2) = L; \
*(ptr - 1) = R; \
} while (ptr < &data.ctx.P[BF_N + 2]); \
\
ptr = data.ctx.S[0]; \
do { \
ptr += 2; \
BF_ENCRYPT; \
*(ptr - 2) = L; \
*(ptr - 1) = R; \
} while (ptr < &data.ctx.S[3][0xFF]); \
} while (0)
#define BF_N
const void * data
#define R(b, x)
Definition: sha2.c:132

Definition at line 529 of file crypt-blowfish.c.

◆ BF_ENCRYPT

#define BF_ENCRYPT
Value:
L ^= data.ctx.P[0]; \
BF_ROUND(L, R, 0); \
BF_ROUND(R, L, 1); \
BF_ROUND(L, R, 2); \
BF_ROUND(R, L, 3); \
BF_ROUND(L, R, 4); \
BF_ROUND(R, L, 5); \
BF_ROUND(L, R, 6); \
BF_ROUND(R, L, 7); \
BF_ROUND(L, R, 8); \
BF_ROUND(R, L, 9); \
BF_ROUND(L, R, 10); \
BF_ROUND(R, L, 11); \
BF_ROUND(L, R, 12); \
BF_ROUND(R, L, 13); \
BF_ROUND(L, R, 14); \
BF_ROUND(R, L, 15); \
tmp4 = R; \
R = L; \
L = tmp4 ^ data.ctx.P[BF_N + 1]

Definition at line 499 of file crypt-blowfish.c.

◆ BF_INDEX

#define BF_INDEX (   S,
  i 
)     (*((BF_word *)(((unsigned char *)(S)) + (i))))

Definition at line 475 of file crypt-blowfish.c.

◆ BF_N

#define BF_N   16

Definition at line 56 of file crypt-blowfish.c.

◆ BF_ROUND

#define BF_ROUND (   L,
  R,
 
)
Value:
tmp1 = (L) & 0xFF; \
tmp1 <<= 2; \
tmp2 = (L) >> 6; \
tmp2 &= 0x3FC; \
tmp3 = (L) >> 14; \
tmp3 &= 0x3FC; \
tmp4 = (L) >> 22; \
tmp4 &= 0x3FC; \
tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
tmp3 ^= tmp2; \
(R) ^= data.ctx.P[(N) + 1]; \
tmp3 += tmp1; \
(R) ^= tmp3
#define BF_INDEX(S, i)

Definition at line 477 of file crypt-blowfish.c.

◆ BF_safe_atoi64

#define BF_safe_atoi64 (   dst,
  src 
)
Value:
do { \
tmp = (unsigned char)(src); \
if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
tmp = BF_atoi64[tmp]; \
if (tmp > 63) return -1; \
(dst) = tmp; \
} while (0)
static unsigned char BF_atoi64[0x60]
while(p+4<=pend)

Definition at line 362 of file crypt-blowfish.c.

◆ BF_SCALE

#define BF_SCALE   0

Definition at line 49 of file crypt-blowfish.c.

Typedef Documentation

◆ BF_key

typedef BF_word BF_key[BF_N+2]

Definition at line 58 of file crypt-blowfish.c.

◆ BF_word

typedef unsigned int BF_word

Definition at line 52 of file crypt-blowfish.c.

◆ BF_word_signed

typedef signed int BF_word_signed

Definition at line 53 of file crypt-blowfish.c.

Function Documentation

◆ _crypt_blowfish_rn()

char* _crypt_blowfish_rn ( const char *  key,
const char *  setting,
char *  output,
int  size 
)

Definition at line 582 of file crypt-blowfish.c.

584 {
585  struct
586  {
587  BF_ctx ctx;
588  BF_key expanded_key;
589  union
590  {
591  BF_word salt[4];
592  BF_word output[6];
593  } binary;
594  } data;
595  BF_word L,
596  R;
597  BF_word tmp1,
598  tmp2,
599  tmp3,
600  tmp4;
601  BF_word *ptr;
602  BF_word count;
603  int i;
604 
605  if (size < 7 + 22 + 31 + 1)
606  return NULL;
607 
608  /*
609  * Blowfish salt value must be formatted as follows: "$2a$" or "$2x$", a
610  * two digit cost parameter, "$", and 22 digits from the alphabet
611  * "./0-9A-Za-z". -- from the PHP crypt docs. Apparently we enforce a few
612  * more restrictions on the count in the salt as well.
613  */
614  if (strlen(setting) < 29)
615  ereport(ERROR,
616  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
617  errmsg("invalid salt")));
618 
619  if (setting[0] != '$' ||
620  setting[1] != '2' ||
621  (setting[2] != 'a' && setting[2] != 'x') ||
622  setting[3] != '$' ||
623  setting[4] < '0' || setting[4] > '3' ||
624  setting[5] < '0' || setting[5] > '9' ||
625  (setting[4] == '3' && setting[5] > '1') ||
626  setting[6] != '$')
627  {
628  ereport(ERROR,
629  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
630  errmsg("invalid salt")));
631  }
632 
633  count = (BF_word) 1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
634  if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16))
635  {
636  px_memset(data.binary.salt, 0, sizeof(data.binary.salt));
637  ereport(ERROR,
638  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
639  errmsg("invalid salt")));
640  }
641  BF_swap(data.binary.salt, 4);
642 
643  BF_set_key(key, data.expanded_key, data.ctx.P, setting[2] == 'x');
644 
645  memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
646 
647  L = R = 0;
648  for (i = 0; i < BF_N + 2; i += 2)
649  {
650  L ^= data.binary.salt[i & 2];
651  R ^= data.binary.salt[(i & 2) + 1];
652  BF_ENCRYPT;
653  data.ctx.P[i] = L;
654  data.ctx.P[i + 1] = R;
655  }
656 
657  ptr = data.ctx.S[0];
658  do
659  {
660  ptr += 4;
661  L ^= data.binary.salt[(BF_N + 2) & 3];
662  R ^= data.binary.salt[(BF_N + 3) & 3];
663  BF_ENCRYPT;
664  *(ptr - 4) = L;
665  *(ptr - 3) = R;
666 
667  L ^= data.binary.salt[(BF_N + 4) & 3];
668  R ^= data.binary.salt[(BF_N + 5) & 3];
669  BF_ENCRYPT;
670  *(ptr - 2) = L;
671  *(ptr - 1) = R;
672  } while (ptr < &data.ctx.S[3][0xFF]);
673 
674  do
675  {
677 
678  data.ctx.P[0] ^= data.expanded_key[0];
679  data.ctx.P[1] ^= data.expanded_key[1];
680  data.ctx.P[2] ^= data.expanded_key[2];
681  data.ctx.P[3] ^= data.expanded_key[3];
682  data.ctx.P[4] ^= data.expanded_key[4];
683  data.ctx.P[5] ^= data.expanded_key[5];
684  data.ctx.P[6] ^= data.expanded_key[6];
685  data.ctx.P[7] ^= data.expanded_key[7];
686  data.ctx.P[8] ^= data.expanded_key[8];
687  data.ctx.P[9] ^= data.expanded_key[9];
688  data.ctx.P[10] ^= data.expanded_key[10];
689  data.ctx.P[11] ^= data.expanded_key[11];
690  data.ctx.P[12] ^= data.expanded_key[12];
691  data.ctx.P[13] ^= data.expanded_key[13];
692  data.ctx.P[14] ^= data.expanded_key[14];
693  data.ctx.P[15] ^= data.expanded_key[15];
694  data.ctx.P[16] ^= data.expanded_key[16];
695  data.ctx.P[17] ^= data.expanded_key[17];
696 
697  BF_body();
698 
699  tmp1 = data.binary.salt[0];
700  tmp2 = data.binary.salt[1];
701  tmp3 = data.binary.salt[2];
702  tmp4 = data.binary.salt[3];
703  data.ctx.P[0] ^= tmp1;
704  data.ctx.P[1] ^= tmp2;
705  data.ctx.P[2] ^= tmp3;
706  data.ctx.P[3] ^= tmp4;
707  data.ctx.P[4] ^= tmp1;
708  data.ctx.P[5] ^= tmp2;
709  data.ctx.P[6] ^= tmp3;
710  data.ctx.P[7] ^= tmp4;
711  data.ctx.P[8] ^= tmp1;
712  data.ctx.P[9] ^= tmp2;
713  data.ctx.P[10] ^= tmp3;
714  data.ctx.P[11] ^= tmp4;
715  data.ctx.P[12] ^= tmp1;
716  data.ctx.P[13] ^= tmp2;
717  data.ctx.P[14] ^= tmp3;
718  data.ctx.P[15] ^= tmp4;
719  data.ctx.P[16] ^= tmp1;
720  data.ctx.P[17] ^= tmp2;
721 
722  BF_body();
723  } while (--count);
724 
725  for (i = 0; i < 6; i += 2)
726  {
727  L = BF_magic_w[i];
728  R = BF_magic_w[i + 1];
729 
730  count = 64;
731  do
732  {
733  BF_ENCRYPT;
734  } while (--count);
735 
736  data.binary.output[i] = L;
737  data.binary.output[i + 1] = R;
738  }
739 
740  memcpy(output, setting, 7 + 22 - 1);
741  output[7 + 22 - 1] = BF_itoa64[(int)
742  BF_atoi64[(int) setting[7 + 22 - 1] - 0x20] & 0x30];
743 
744 /* This has to be bug-compatible with the original implementation, so
745  * only encode 23 of the 24 bytes. :-) */
746  BF_swap(data.binary.output, 6);
747  BF_encode(&output[7 + 22], data.binary.output, 23);
748  output[7 + 22 + 31] = '\0';
749 
750 /* Overwrite the most obvious sensitive data we have on the stack. Note
751  * that this does not guarantee there's no sensitive data left on the
752  * stack and/or in registers; I'm not aware of portable code that does. */
753  px_memset(&data, 0, sizeof(data));
754 
755  return output;
756 }
static int BF_decode(BF_word *dst, const char *src, int size)
static void BF_set_key(const char *key, BF_key expanded, BF_key initial, int sign_extension_bug)
static void BF_swap(BF_word *x, int count)
#define BF_ENCRYPT
static BF_word BF_magic_w[6]
static unsigned char BF_itoa64[64+1]
static BF_ctx BF_init_state
static void BF_encode(char *dst, const BF_word *src, int size)
#define BF_body()
unsigned int BF_word
BF_word BF_key[BF_N+2]
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
FILE * output
int i
Definition: isn.c:72
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
void px_memset(void *ptr, int c, size_t len)
Definition: px.c:123
static pg_noinline void Size size
Definition: slab.c:607
BF_word S[4][0x100]

References BF_atoi64, BF_body, BF_decode(), BF_encode(), BF_ENCRYPT, BF_init_state, BF_itoa64, BF_magic_w, BF_N, BF_set_key(), BF_swap(), CHECK_FOR_INTERRUPTS, data, ereport, errcode(), errmsg(), ERROR, i, sort-test::key, output, px_memset(), R, BF_ctx::S, and size.

◆ BF_decode()

static int BF_decode ( BF_word dst,
const char *  src,
int  size 
)
static

Definition at line 372 of file crypt-blowfish.c.

373 {
374  unsigned char *dptr = (unsigned char *) dst;
375  unsigned char *end = dptr + size;
376  const unsigned char *sptr = (const unsigned char *) src;
377  unsigned int tmp,
378  c1,
379  c2,
380  c3,
381  c4;
382 
383  do
384  {
385  BF_safe_atoi64(c1, *sptr++);
386  BF_safe_atoi64(c2, *sptr++);
387  *dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
388  if (dptr >= end)
389  break;
390 
391  BF_safe_atoi64(c3, *sptr++);
392  *dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
393  if (dptr >= end)
394  break;
395 
396  BF_safe_atoi64(c4, *sptr++);
397  *dptr++ = ((c3 & 0x03) << 6) | c4;
398  } while (dptr < end);
399 
400  return 0;
401 }
#define BF_safe_atoi64(dst, src)

References BF_safe_atoi64, and size.

Referenced by _crypt_blowfish_rn().

◆ BF_encode()

static void BF_encode ( char *  dst,
const BF_word src,
int  size 
)
static

Definition at line 404 of file crypt-blowfish.c.

405 {
406  const unsigned char *sptr = (const unsigned char *) src;
407  const unsigned char *end = sptr + size;
408  unsigned char *dptr = (unsigned char *) dst;
409  unsigned int c1,
410  c2;
411 
412  do
413  {
414  c1 = *sptr++;
415  *dptr++ = BF_itoa64[c1 >> 2];
416  c1 = (c1 & 0x03) << 4;
417  if (sptr >= end)
418  {
419  *dptr++ = BF_itoa64[c1];
420  break;
421  }
422 
423  c2 = *sptr++;
424  c1 |= c2 >> 4;
425  *dptr++ = BF_itoa64[c1];
426  c1 = (c2 & 0x0f) << 2;
427  if (sptr >= end)
428  {
429  *dptr++ = BF_itoa64[c1];
430  break;
431  }
432 
433  c2 = *sptr++;
434  c1 |= c2 >> 6;
435  *dptr++ = BF_itoa64[c1];
436  *dptr++ = BF_itoa64[c2 & 0x3f];
437  } while (sptr < end);
438 }

References BF_itoa64, and size.

Referenced by _crypt_blowfish_rn().

◆ BF_set_key()

static void BF_set_key ( const char *  key,
BF_key  expanded,
BF_key  initial,
int  sign_extension_bug 
)
static

Definition at line 551 of file crypt-blowfish.c.

553 {
554  const char *ptr = key;
555  int i,
556  j;
557  BF_word tmp;
558 
559  for (i = 0; i < BF_N + 2; i++)
560  {
561  tmp = 0;
562  for (j = 0; j < 4; j++)
563  {
564  tmp <<= 8;
565  if (sign_extension_bug)
566  tmp |= (BF_word_signed) (signed char) *ptr;
567  else
568  tmp |= (unsigned char) *ptr;
569 
570  if (!*ptr)
571  ptr = key;
572  else
573  ptr++;
574  }
575 
576  expanded[i] = tmp;
577  initial[i] = BF_init_state.P[i] ^ tmp;
578  }
579 }
signed int BF_word_signed
int j
Definition: isn.c:73
BF_key P

References BF_init_state, BF_N, i, j, sort-test::key, and BF_ctx::P.

Referenced by _crypt_blowfish_rn().

◆ BF_swap()

static void BF_swap ( BF_word x,
int  count 
)
static

Definition at line 441 of file crypt-blowfish.c.

442 {
443  /* Swap on little-endian hardware, else do nothing */
444 #ifndef WORDS_BIGENDIAN
445  BF_word tmp;
446 
447  do
448  {
449  tmp = *x;
450  tmp = (tmp << 16) | (tmp >> 16);
451  *x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
452  } while (--count);
453 #endif
454 }
int x
Definition: isn.c:70

References x.

Referenced by _crypt_blowfish_rn().

Variable Documentation

◆ BF_atoi64

unsigned char BF_atoi64[0x60]
static
Initial value:
= {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
64, 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, 64, 64, 64, 64, 64,
64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
}

Definition at line 353 of file crypt-blowfish.c.

Referenced by _crypt_blowfish_rn().

◆ BF_init_state

BF_ctx BF_init_state
static

Definition at line 78 of file crypt-blowfish.c.

Referenced by _crypt_blowfish_rn(), and BF_set_key().

◆ BF_itoa64

unsigned char BF_itoa64[64+1]
static
Initial value:
=
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"

Definition at line 350 of file crypt-blowfish.c.

Referenced by _crypt_blowfish_rn(), and BF_encode().

◆ BF_magic_w

BF_word BF_magic_w[6]
static
Initial value:
= {
0x4F727068, 0x65616E42, 0x65686F6C,
0x64657253, 0x63727944, 0x6F756274
}

Definition at line 70 of file crypt-blowfish.c.

Referenced by _crypt_blowfish_rn().