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_SHA_256_KEY_LEN   PG_SHA256_DIGEST_LENGTH
 
#define SCRAM_MAX_KEY_LEN   SCRAM_SHA_256_KEY_LEN
 
#define SCRAM_RAW_NONCE_LEN   18
 
#define SCRAM_DEFAULT_SALT_LEN   16
 
#define SCRAM_SHA_256_DEFAULT_ITERATIONS   4096
 

Functions

int scram_SaltedPassword (const char *password, pg_cryptohash_type hash_type, int key_length, const char *salt, int saltlen, int iterations, uint8 *result, const char **errstr)
 
int scram_H (const uint8 *input, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
 
int scram_ClientKey (const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
 
int scram_ServerKey (const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
 
char * scram_build_secret (pg_cryptohash_type hash_type, int key_length, const char *salt, int saltlen, int iterations, const char *password, const char **errstr)
 

Macro Definition Documentation

◆ SCRAM_DEFAULT_SALT_LEN

#define SCRAM_DEFAULT_SALT_LEN   16

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

◆ SCRAM_MAX_KEY_LEN

#define SCRAM_MAX_KEY_LEN   SCRAM_SHA_256_KEY_LEN

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

◆ SCRAM_RAW_NONCE_LEN

#define SCRAM_RAW_NONCE_LEN   18

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

◆ SCRAM_SHA_256_DEFAULT_ITERATIONS

#define SCRAM_SHA_256_DEFAULT_ITERATIONS   4096

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

◆ SCRAM_SHA_256_KEY_LEN

#define SCRAM_SHA_256_KEY_LEN   PG_SHA256_DIGEST_LENGTH

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

◆ SCRAM_SHA_256_NAME

#define SCRAM_SHA_256_NAME   "SCRAM-SHA-256"

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

◆ SCRAM_SHA_256_PLUS_NAME

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

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

Function Documentation

◆ scram_build_secret()

char * scram_build_secret ( pg_cryptohash_type  hash_type,
int  key_length,
const char *  salt,
int  saltlen,
int  iterations,
const char *  password,
const char **  errstr 
)

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

212{
213 uint8 salted_password[SCRAM_MAX_KEY_LEN];
214 uint8 stored_key[SCRAM_MAX_KEY_LEN];
215 uint8 server_key[SCRAM_MAX_KEY_LEN];
216 char *result;
217 char *p;
218 int maxlen;
219 int encoded_salt_len;
220 int encoded_stored_len;
221 int encoded_server_len;
222 int encoded_result;
223
224 /* Only this hash method is supported currently */
225 Assert(hash_type == PG_SHA256);
226
227 Assert(iterations > 0);
228
229 /* Calculate StoredKey and ServerKey */
230 if (scram_SaltedPassword(password, hash_type, key_length,
231 salt, saltlen, iterations,
232 salted_password, errstr) < 0 ||
233 scram_ClientKey(salted_password, hash_type, key_length,
234 stored_key, errstr) < 0 ||
235 scram_H(stored_key, hash_type, key_length,
236 stored_key, errstr) < 0 ||
237 scram_ServerKey(salted_password, hash_type, key_length,
238 server_key, errstr) < 0)
239 {
240 /* errstr is filled already here */
241#ifdef FRONTEND
242 return NULL;
243#else
244 elog(ERROR, "could not calculate stored key and server key: %s",
245 *errstr);
246#endif
247 }
248
249 /*----------
250 * The format is:
251 * SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
252 *----------
253 */
254 encoded_salt_len = pg_b64_enc_len(saltlen);
255 encoded_stored_len = pg_b64_enc_len(key_length);
256 encoded_server_len = pg_b64_enc_len(key_length);
257
258 maxlen = strlen("SCRAM-SHA-256") + 1
259 + 10 + 1 /* iteration count */
260 + encoded_salt_len + 1 /* Base64-encoded salt */
261 + encoded_stored_len + 1 /* Base64-encoded StoredKey */
262 + encoded_server_len + 1; /* Base64-encoded ServerKey */
263
264#ifdef FRONTEND
265 result = malloc(maxlen);
266 if (!result)
267 {
268 *errstr = _("out of memory");
269 return NULL;
270 }
271#else
272 result = palloc(maxlen);
273#endif
274
275 p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
276
277 /* salt */
278 encoded_result = pg_b64_encode(salt, saltlen, p, encoded_salt_len);
279 if (encoded_result < 0)
280 {
281 *errstr = _("could not encode salt");
282#ifdef FRONTEND
283 free(result);
284 return NULL;
285#else
286 elog(ERROR, "%s", *errstr);
287#endif
288 }
289 p += encoded_result;
290 *(p++) = '$';
291
292 /* stored key */
293 encoded_result = pg_b64_encode((char *) stored_key, key_length, p,
294 encoded_stored_len);
295 if (encoded_result < 0)
296 {
297 *errstr = _("could not encode stored key");
298#ifdef FRONTEND
299 free(result);
300 return NULL;
301#else
302 elog(ERROR, "%s", *errstr);
303#endif
304 }
305
306 p += encoded_result;
307 *(p++) = ':';
308
309 /* server key */
310 encoded_result = pg_b64_encode((char *) server_key, key_length, p,
311 encoded_server_len);
312 if (encoded_result < 0)
313 {
314 *errstr = _("could not encode server key");
315#ifdef FRONTEND
316 free(result);
317 return NULL;
318#else
319 elog(ERROR, "%s", *errstr);
320#endif
321 }
322
323 p += encoded_result;
324 *(p++) = '\0';
325
326 Assert(p - result <= maxlen);
327
328 return result;
329}
int pg_b64_enc_len(int srclen)
Definition: base64.c:224
int pg_b64_encode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:49
uint8_t uint8
Definition: c.h:486
#define Assert(condition)
Definition: c.h:815
@ PG_SHA256
Definition: cryptohash.h:24
#define _(x)
Definition: elog.c:90
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
void * palloc(Size size)
Definition: mcxt.c:1317
#define sprintf
Definition: port.h:240
int scram_ServerKey(const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
Definition: scram-common.c:172
int scram_SaltedPassword(const char *password, pg_cryptohash_type hash_type, int key_length, const char *salt, int saltlen, int iterations, uint8 *result, const char **errstr)
Definition: scram-common.c:38
int scram_ClientKey(const uint8 *salted_password, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
Definition: scram-common.c:142
int scram_H(const uint8 *input, pg_cryptohash_type hash_type, int key_length, uint8 *result, const char **errstr)
Definition: scram-common.c:112
#define SCRAM_MAX_KEY_LEN
Definition: scram-common.h:30
static char * password
Definition: streamutil.c:52
int iterations
Definition: thread-thread.c:39

References _, Assert, elog, ERROR, free, iterations, malloc, palloc(), password, pg_b64_enc_len(), pg_b64_encode(), PG_SHA256, scram_ClientKey(), scram_H(), SCRAM_MAX_KEY_LEN, scram_SaltedPassword(), scram_ServerKey(), and sprintf.

Referenced by pg_be_scram_build_secret(), and pg_fe_scram_build_secret().

◆ scram_ClientKey()

int scram_ClientKey ( const uint8 salted_password,
pg_cryptohash_type  hash_type,
int  key_length,
uint8 result,
const char **  errstr 
)

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

145{
146 pg_hmac_ctx *ctx = pg_hmac_create(hash_type);
147
148 if (ctx == NULL)
149 {
150 *errstr = pg_hmac_error(NULL); /* returns OOM */
151 return -1;
152 }
153
154 if (pg_hmac_init(ctx, salted_password, key_length) < 0 ||
155 pg_hmac_update(ctx, (uint8 *) "Client Key", strlen("Client Key")) < 0 ||
156 pg_hmac_final(ctx, result, key_length) < 0)
157 {
158 *errstr = pg_hmac_error(ctx);
159 pg_hmac_free(ctx);
160 return -1;
161 }
162
163 pg_hmac_free(ctx);
164 return 0;
165}
pg_hmac_ctx * pg_hmac_create(pg_cryptohash_type type)
Definition: hmac.c:77
void pg_hmac_free(pg_hmac_ctx *ctx)
Definition: hmac.c:289
const char * pg_hmac_error(pg_hmac_ctx *ctx)
Definition: hmac.c:306
int pg_hmac_update(pg_hmac_ctx *ctx, const uint8 *data, size_t len)
Definition: hmac.c:223
int pg_hmac_init(pg_hmac_ctx *ctx, const uint8 *key, size_t len)
Definition: hmac.c:138
int pg_hmac_final(pg_hmac_ctx *ctx, uint8 *dest, size_t len)
Definition: hmac.c:244

References pg_hmac_create(), pg_hmac_error(), pg_hmac_final(), pg_hmac_free(), pg_hmac_init(), and pg_hmac_update().

Referenced by calculate_client_proof(), and scram_build_secret().

◆ scram_H()

int scram_H ( const uint8 input,
pg_cryptohash_type  hash_type,
int  key_length,
uint8 result,
const char **  errstr 
)

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

114{
116
117 ctx = pg_cryptohash_create(hash_type);
118 if (ctx == NULL)
119 {
120 *errstr = pg_cryptohash_error(NULL); /* returns OOM */
121 return -1;
122 }
123
124 if (pg_cryptohash_init(ctx) < 0 ||
125 pg_cryptohash_update(ctx, input, key_length) < 0 ||
126 pg_cryptohash_final(ctx, result, key_length) < 0)
127 {
128 *errstr = pg_cryptohash_error(ctx);
130 return -1;
131 }
132
134 return 0;
135}
const char * pg_cryptohash_error(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:254
int pg_cryptohash_update(pg_cryptohash_ctx *ctx, const uint8 *data, size_t len)
Definition: cryptohash.c:136
pg_cryptohash_ctx * pg_cryptohash_create(pg_cryptohash_type type)
Definition: cryptohash.c:74
int pg_cryptohash_init(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:100
void pg_cryptohash_free(pg_cryptohash_ctx *ctx)
Definition: cryptohash.c:238
int pg_cryptohash_final(pg_cryptohash_ctx *ctx, uint8 *dest, size_t len)
Definition: cryptohash.c:172
FILE * input

References input, pg_cryptohash_create(), pg_cryptohash_error(), pg_cryptohash_final(), pg_cryptohash_free(), pg_cryptohash_init(), and pg_cryptohash_update().

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

◆ scram_SaltedPassword()

int scram_SaltedPassword ( const char *  password,
pg_cryptohash_type  hash_type,
int  key_length,
const char *  salt,
int  saltlen,
int  iterations,
uint8 result,
const char **  errstr 
)

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

42{
43 int password_len = strlen(password);
44 uint32 one = pg_hton32(1);
45 int i,
46 j;
48 uint8 Ui_prev[SCRAM_MAX_KEY_LEN];
49 pg_hmac_ctx *hmac_ctx = pg_hmac_create(hash_type);
50
51 if (hmac_ctx == NULL)
52 {
53 *errstr = pg_hmac_error(NULL); /* returns OOM */
54 return -1;
55 }
56
57 /*
58 * Iterate hash calculation of HMAC entry using given salt. This is
59 * essentially PBKDF2 (see RFC2898) with HMAC() as the pseudorandom
60 * function.
61 */
62
63 /* First iteration */
64 if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
65 pg_hmac_update(hmac_ctx, (uint8 *) salt, saltlen) < 0 ||
66 pg_hmac_update(hmac_ctx, (uint8 *) &one, sizeof(uint32)) < 0 ||
67 pg_hmac_final(hmac_ctx, Ui_prev, key_length) < 0)
68 {
69 *errstr = pg_hmac_error(hmac_ctx);
70 pg_hmac_free(hmac_ctx);
71 return -1;
72 }
73
74 memcpy(result, Ui_prev, key_length);
75
76 /* Subsequent iterations */
77 for (i = 2; i <= iterations; i++)
78 {
79#ifndef FRONTEND
80 /*
81 * Make sure that this is interruptible as scram_iterations could be
82 * set to a large value.
83 */
85#endif
86
87 if (pg_hmac_init(hmac_ctx, (uint8 *) password, password_len) < 0 ||
88 pg_hmac_update(hmac_ctx, (uint8 *) Ui_prev, key_length) < 0 ||
89 pg_hmac_final(hmac_ctx, Ui, key_length) < 0)
90 {
91 *errstr = pg_hmac_error(hmac_ctx);
92 pg_hmac_free(hmac_ctx);
93 return -1;
94 }
95
96 for (j = 0; j < key_length; j++)
97 result[j] ^= Ui[j];
98 memcpy(Ui_prev, Ui, key_length);
99 }
100
101 pg_hmac_free(hmac_ctx);
102 return 0;
103}
uint32_t uint32
Definition: c.h:488
int j
Definition: isn.c:73
int i
Definition: isn.c:72
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define pg_hton32(x)
Definition: pg_bswap.h:121

References CHECK_FOR_INTERRUPTS, i, iterations, j, password, pg_hmac_create(), pg_hmac_error(), pg_hmac_final(), pg_hmac_free(), pg_hmac_init(), pg_hmac_update(), pg_hton32, and SCRAM_MAX_KEY_LEN.

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

◆ scram_ServerKey()

int scram_ServerKey ( const uint8 salted_password,
pg_cryptohash_type  hash_type,
int  key_length,
uint8 result,
const char **  errstr 
)

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

175{
176 pg_hmac_ctx *ctx = pg_hmac_create(hash_type);
177
178 if (ctx == NULL)
179 {
180 *errstr = pg_hmac_error(NULL); /* returns OOM */
181 return -1;
182 }
183
184 if (pg_hmac_init(ctx, salted_password, key_length) < 0 ||
185 pg_hmac_update(ctx, (uint8 *) "Server Key", strlen("Server Key")) < 0 ||
186 pg_hmac_final(ctx, result, key_length) < 0)
187 {
188 *errstr = pg_hmac_error(ctx);
189 pg_hmac_free(ctx);
190 return -1;
191 }
192
193 pg_hmac_free(ctx);
194 return 0;
195}

References pg_hmac_create(), pg_hmac_error(), pg_hmac_final(), pg_hmac_free(), pg_hmac_init(), and pg_hmac_update().

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