PostgreSQL Source Code  git master
scram-common.h File Reference
#include "common/cryptohash.h"
#include "common/sha2.h"
Include dependency graph for scram-common.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define SCRAM_SHA_256_NAME   "SCRAM-SHA-256"
 
#define SCRAM_SHA_256_PLUS_NAME   "SCRAM-SHA-256-PLUS" /* with channel binding */
 
#define SCRAM_KEY_LEN   PG_SHA256_DIGEST_LENGTH
 
#define SHA256_HMAC_B   PG_SHA256_BLOCK_LENGTH
 
#define SCRAM_RAW_NONCE_LEN   18
 
#define SCRAM_DEFAULT_SALT_LEN   16
 
#define SCRAM_DEFAULT_ITERATIONS   4096
 

Functions

int scram_SaltedPassword (const char *password, const char *salt, int saltlen, int iterations, uint8 *result)
 
int scram_H (const uint8 *str, int len, uint8 *result)
 
int scram_ClientKey (const uint8 *salted_password, uint8 *result)
 
int scram_ServerKey (const uint8 *salted_password, uint8 *result)
 
char * scram_build_secret (const char *salt, int saltlen, int iterations, const char *password)
 

Macro Definition Documentation

◆ SCRAM_DEFAULT_ITERATIONS

#define SCRAM_DEFAULT_ITERATIONS   4096

◆ SCRAM_DEFAULT_SALT_LEN

#define SCRAM_DEFAULT_SALT_LEN   16

◆ SCRAM_KEY_LEN

◆ SCRAM_RAW_NONCE_LEN

#define SCRAM_RAW_NONCE_LEN   18

Definition at line 34 of file scram-common.h.

Referenced by build_client_first_message(), and build_server_first_message().

◆ SCRAM_SHA_256_NAME

#define SCRAM_SHA_256_NAME   "SCRAM-SHA-256"

Definition at line 20 of file scram-common.h.

Referenced by pg_be_scram_get_mechanisms(), pg_be_scram_init(), and pg_SASL_init().

◆ SCRAM_SHA_256_PLUS_NAME

#define SCRAM_SHA_256_PLUS_NAME   "SCRAM-SHA-256-PLUS" /* with channel binding */

◆ SHA256_HMAC_B

#define SHA256_HMAC_B   PG_SHA256_BLOCK_LENGTH

Definition at line 27 of file scram-common.h.

Function Documentation

◆ scram_build_secret()

char* scram_build_secret ( const char *  salt,
int  saltlen,
int  iterations,
const char *  password 
)

Definition at line 169 of file scram-common.c.

References Assert, elog, ERROR, free, malloc, palloc(), pg_b64_enc_len(), pg_b64_encode(), scram_ClientKey(), SCRAM_DEFAULT_ITERATIONS, scram_H(), SCRAM_KEY_LEN, scram_SaltedPassword(), scram_ServerKey(), and sprintf.

Referenced by pg_be_scram_build_secret(), and pg_fe_scram_build_secret().

171 {
172  uint8 salted_password[SCRAM_KEY_LEN];
173  uint8 stored_key[SCRAM_KEY_LEN];
174  uint8 server_key[SCRAM_KEY_LEN];
175  char *result;
176  char *p;
177  int maxlen;
178  int encoded_salt_len;
179  int encoded_stored_len;
180  int encoded_server_len;
181  int encoded_result;
182 
183  if (iterations <= 0)
184  iterations = SCRAM_DEFAULT_ITERATIONS;
185 
186  /* Calculate StoredKey and ServerKey */
187  if (scram_SaltedPassword(password, salt, saltlen, iterations,
188  salted_password) < 0 ||
189  scram_ClientKey(salted_password, stored_key) < 0 ||
190  scram_H(stored_key, SCRAM_KEY_LEN, stored_key) < 0 ||
191  scram_ServerKey(salted_password, server_key) < 0)
192  {
193 #ifdef FRONTEND
194  return NULL;
195 #else
196  elog(ERROR, "could not calculate stored key and server key");
197 #endif
198  }
199 
200  /*----------
201  * The format is:
202  * SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
203  *----------
204  */
205  encoded_salt_len = pg_b64_enc_len(saltlen);
206  encoded_stored_len = pg_b64_enc_len(SCRAM_KEY_LEN);
207  encoded_server_len = pg_b64_enc_len(SCRAM_KEY_LEN);
208 
209  maxlen = strlen("SCRAM-SHA-256") + 1
210  + 10 + 1 /* iteration count */
211  + encoded_salt_len + 1 /* Base64-encoded salt */
212  + encoded_stored_len + 1 /* Base64-encoded StoredKey */
213  + encoded_server_len + 1; /* Base64-encoded ServerKey */
214 
215 #ifdef FRONTEND
216  result = malloc(maxlen);
217  if (!result)
218  return NULL;
219 #else
220  result = palloc(maxlen);
221 #endif
222 
223  p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
224 
225  /* salt */
226  encoded_result = pg_b64_encode(salt, saltlen, p, encoded_salt_len);
227  if (encoded_result < 0)
228  {
229 #ifdef FRONTEND
230  free(result);
231  return NULL;
232 #else
233  elog(ERROR, "could not encode salt");
234 #endif
235  }
236  p += encoded_result;
237  *(p++) = '$';
238 
239  /* stored key */
240  encoded_result = pg_b64_encode((char *) stored_key, SCRAM_KEY_LEN, p,
241  encoded_stored_len);
242  if (encoded_result < 0)
243  {
244 #ifdef FRONTEND
245  free(result);
246  return NULL;
247 #else
248  elog(ERROR, "could not encode stored key");
249 #endif
250  }
251 
252  p += encoded_result;
253  *(p++) = ':';
254 
255  /* server key */
256  encoded_result = pg_b64_encode((char *) server_key, SCRAM_KEY_LEN, p,
257  encoded_server_len);
258  if (encoded_result < 0)
259  {
260 #ifdef FRONTEND
261  free(result);
262  return NULL;
263 #else
264  elog(ERROR, "could not encode server key");
265 #endif
266  }
267 
268  p += encoded_result;
269  *(p++) = '\0';
270 
271  Assert(p - result <= maxlen);
272 
273  return result;
274 }
int pg_b64_encode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:49
unsigned char uint8
Definition: c.h:439
int scram_ServerKey(const uint8 *salted_password, uint8 *result)
Definition: scram-common.c:140
int scram_H(const uint8 *input, int len, uint8 *result)
Definition: scram-common.c:93
#define malloc(a)
Definition: header.h:50
#define sprintf
Definition: port.h:218
int scram_ClientKey(const uint8 *salted_password, uint8 *result)
Definition: scram-common.c:117
#define ERROR
Definition: elog.h:46
static char * password
Definition: streamutil.c:53
#define free(a)
Definition: header.h:65
#define Assert(condition)
Definition: c.h:804
#define SCRAM_DEFAULT_ITERATIONS
Definition: scram-common.h:47
int scram_SaltedPassword(const char *password, const char *salt, int saltlen, int iterations, uint8 *result)
Definition: scram-common.c:34
int pg_b64_enc_len(int srclen)
Definition: base64.c:224
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
#define SCRAM_KEY_LEN
Definition: scram-common.h:24

◆ scram_ClientKey()

int scram_ClientKey ( const uint8 salted_password,
uint8 result 
)

Definition at line 117 of file scram-common.c.

References pg_hmac_create(), pg_hmac_final(), pg_hmac_free(), pg_hmac_init(), pg_hmac_update(), PG_SHA256, and SCRAM_KEY_LEN.

Referenced by calculate_client_proof(), and scram_build_secret().

118 {
120 
121  if (ctx == NULL)
122  return -1;
123 
124  if (pg_hmac_init(ctx, salted_password, SCRAM_KEY_LEN) < 0 ||
125  pg_hmac_update(ctx, (uint8 *) "Client Key", strlen("Client Key")) < 0 ||
126  pg_hmac_final(ctx, result, SCRAM_KEY_LEN) < 0)
127  {
128  pg_hmac_free(ctx);
129  return -1;
130  }
131 
132  pg_hmac_free(ctx);
133  return 0;
134 }
unsigned char uint8
Definition: c.h:439
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
Definition: hmac.c:69
int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
Definition: hmac.c:205
int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
Definition: hmac.c:128
void pg_hmac_free(pg_hmac_ctx *ctx)
Definition: hmac.c:255
#define SCRAM_KEY_LEN
Definition: scram-common.h:24
int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
Definition: hmac.c:222

◆ scram_H()

int scram_H ( const uint8 str,
int  len,
uint8 result 
)

Definition at line 93 of file scram-common.c.

References pg_cryptohash_create(), pg_cryptohash_final(), pg_cryptohash_free(), pg_cryptohash_init(), pg_cryptohash_update(), PG_SHA256, and SCRAM_KEY_LEN.

Referenced by calculate_client_proof(), scram_build_secret(), and verify_client_proof().

94 {
95  pg_cryptohash_ctx *ctx;
96 
98  if (ctx == NULL)
99  return -1;
100 
101  if (pg_cryptohash_init(ctx) < 0 ||
102  pg_cryptohash_update(ctx, input, len) < 0 ||
103  pg_cryptohash_final(ctx, result, SCRAM_KEY_LEN) < 0)
104  {
105  pg_cryptohash_free(ctx);
106  return -1;
107  }
108 
109  pg_cryptohash_free(ctx);
110  return 0;
111 }
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:168
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:66
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:92
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:130
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:216
#define SCRAM_KEY_LEN
Definition: scram-common.h:24

◆ scram_SaltedPassword()

int scram_SaltedPassword ( const char *  password,
const char *  salt,
int  saltlen,
int  iterations,
uint8 result 
)

Definition at line 34 of file scram-common.c.

References i, pg_hmac_create(), pg_hmac_final(), pg_hmac_free(), pg_hmac_init(), pg_hmac_update(), pg_hton32, PG_SHA256, and SCRAM_KEY_LEN.

Referenced by calculate_client_proof(), scram_build_secret(), and scram_verify_plain_password().

37 {
38  int password_len = strlen(password);
39  uint32 one = pg_hton32(1);
40  int i,
41  j;
42  uint8 Ui[SCRAM_KEY_LEN];
43  uint8 Ui_prev[SCRAM_KEY_LEN];
45 
46  if (hmac_ctx == NULL)
47  return -1;
48 
49  /*
50  * Iterate hash calculation of HMAC entry using given salt. This is
51  * essentially PBKDF2 (see RFC2898) with HMAC() as the pseudorandom
52  * function.
53  */
54 
55  /* First iteration */
56  if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
57  pg_hmac_update(hmac_ctx, (uint8 *) salt, saltlen) < 0 ||
58  pg_hmac_update(hmac_ctx, (uint8 *) &one, sizeof(uint32)) < 0 ||
59  pg_hmac_final(hmac_ctx, Ui_prev, sizeof(Ui_prev)) < 0)
60  {
61  pg_hmac_free(hmac_ctx);
62  return -1;
63  }
64 
65  memcpy(result, Ui_prev, SCRAM_KEY_LEN);
66 
67  /* Subsequent iterations */
68  for (i = 2; i <= iterations; i++)
69  {
70  if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
71  pg_hmac_update(hmac_ctx, (uint8 *) Ui_prev, SCRAM_KEY_LEN) < 0 ||
72  pg_hmac_final(hmac_ctx, Ui, sizeof(Ui)) < 0)
73  {
74  pg_hmac_free(hmac_ctx);
75  return -1;
76  }
77 
78  for (j = 0; j < SCRAM_KEY_LEN; j++)
79  result[j] ^= Ui[j];
80  memcpy(Ui_prev, Ui, SCRAM_KEY_LEN);
81  }
82 
83  pg_hmac_free(hmac_ctx);
84  return 0;
85 }
unsigned char uint8
Definition: c.h:439
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
Definition: hmac.c:69
#define pg_hton32(x)
Definition: pg_bswap.h:121
int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
Definition: hmac.c:205
unsigned int uint32
Definition: c.h:441
static char * password
Definition: streamutil.c:53
int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
Definition: hmac.c:128
void pg_hmac_free(pg_hmac_ctx *ctx)
Definition: hmac.c:255
int i
#define SCRAM_KEY_LEN
Definition: scram-common.h:24
int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
Definition: hmac.c:222

◆ scram_ServerKey()

int scram_ServerKey ( const uint8 salted_password,
uint8 result 
)

Definition at line 140 of file scram-common.c.

References pg_hmac_create(), pg_hmac_final(), pg_hmac_free(), pg_hmac_init(), pg_hmac_update(), PG_SHA256, and SCRAM_KEY_LEN.

Referenced by scram_build_secret(), scram_verify_plain_password(), and verify_server_signature().

141 {
143 
144  if (ctx == NULL)
145  return -1;
146 
147  if (pg_hmac_init(ctx, salted_password, SCRAM_KEY_LEN) < 0 ||
148  pg_hmac_update(ctx, (uint8 *) "Server Key", strlen("Server Key")) < 0 ||
149  pg_hmac_final(ctx, result, SCRAM_KEY_LEN) < 0)
150  {
151  pg_hmac_free(ctx);
152  return -1;
153  }
154 
155  pg_hmac_free(ctx);
156  return 0;
157 }
unsigned char uint8
Definition: c.h:439
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
Definition: hmac.c:69
int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
Definition: hmac.c:205
int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
Definition: hmac.c:128
void pg_hmac_free(pg_hmac_ctx *ctx)
Definition: hmac.c:255
#define SCRAM_KEY_LEN
Definition: scram-common.h:24
int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
Definition: hmac.c:222