Revert commit 66c0185a3 and follow-on patches.
[pgsql.git] / src / backend / libpq / auth-scram.c
blob416195991486de55f76db1bd3c1fe5d367a1cd29
1 /*-------------------------------------------------------------------------
3 * auth-scram.c
4 * Server-side implementation of the SASL SCRAM-SHA-256 mechanism.
6 * See the following RFCs for more details:
7 * - RFC 5802: https://tools.ietf.org/html/rfc5802
8 * - RFC 5803: https://tools.ietf.org/html/rfc5803
9 * - RFC 7677: https://tools.ietf.org/html/rfc7677
11 * Here are some differences:
13 * - Username from the authentication exchange is not used. The client
14 * should send an empty string as the username.
16 * - If the password isn't valid UTF-8, or contains characters prohibited
17 * by the SASLprep profile, we skip the SASLprep pre-processing and use
18 * the raw bytes in calculating the hash.
20 * - If channel binding is used, the channel binding type is always
21 * "tls-server-end-point". The spec says the default is "tls-unique"
22 * (RFC 5802, section 6.1. Default Channel Binding), but there are some
23 * problems with that. Firstly, not all SSL libraries provide an API to
24 * get the TLS Finished message, required to use "tls-unique". Secondly,
25 * "tls-unique" is not specified for TLS v1.3, and as of this writing,
26 * it's not clear if there will be a replacement. We could support both
27 * "tls-server-end-point" and "tls-unique", but for our use case,
28 * "tls-unique" doesn't really have any advantages. The main advantage
29 * of "tls-unique" would be that it works even if the server doesn't
30 * have a certificate, but PostgreSQL requires a server certificate
31 * whenever SSL is used, anyway.
34 * The password stored in pg_authid consists of the iteration count, salt,
35 * StoredKey and ServerKey.
37 * SASLprep usage
38 * --------------
40 * One notable difference to the SCRAM specification is that while the
41 * specification dictates that the password is in UTF-8, and prohibits
42 * certain characters, we are more lenient. If the password isn't a valid
43 * UTF-8 string, or contains prohibited characters, the raw bytes are used
44 * to calculate the hash instead, without SASLprep processing. This is
45 * because PostgreSQL supports other encodings too, and the encoding being
46 * used during authentication is undefined (client_encoding isn't set until
47 * after authentication). In effect, we try to interpret the password as
48 * UTF-8 and apply SASLprep processing, but if it looks invalid, we assume
49 * that it's in some other encoding.
51 * In the worst case, we misinterpret a password that's in a different
52 * encoding as being Unicode, because it happens to consists entirely of
53 * valid UTF-8 bytes, and we apply Unicode normalization to it. As long
54 * as we do that consistently, that will not lead to failed logins.
55 * Fortunately, the UTF-8 byte sequences that are ignored by SASLprep
56 * don't correspond to any commonly used characters in any of the other
57 * supported encodings, so it should not lead to any significant loss in
58 * entropy, even if the normalization is incorrectly applied to a
59 * non-UTF-8 password.
61 * Error handling
62 * --------------
64 * Don't reveal user information to an unauthenticated client. We don't
65 * want an attacker to be able to probe whether a particular username is
66 * valid. In SCRAM, the server has to read the salt and iteration count
67 * from the user's stored secret, and send it to the client. To avoid
68 * revealing whether a user exists, when the client tries to authenticate
69 * with a username that doesn't exist, or doesn't have a valid SCRAM
70 * secret in pg_authid, we create a fake salt and iteration count
71 * on-the-fly, and proceed with the authentication with that. In the end,
72 * we'll reject the attempt, as if an incorrect password was given. When
73 * we are performing a "mock" authentication, the 'doomed' flag in
74 * scram_state is set.
76 * In the error messages, avoid printing strings from the client, unless
77 * you check that they are pure ASCII. We don't want an unauthenticated
78 * attacker to be able to spam the logs with characters that are not valid
79 * to the encoding being used, whatever that is. We cannot avoid that in
80 * general, after logging in, but let's do what we can here.
83 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
84 * Portions Copyright (c) 1994, Regents of the University of California
86 * src/backend/libpq/auth-scram.c
88 *-------------------------------------------------------------------------
90 #include "postgres.h"
92 #include <unistd.h>
94 #include "access/xlog.h"
95 #include "catalog/pg_control.h"
96 #include "common/base64.h"
97 #include "common/hmac.h"
98 #include "common/saslprep.h"
99 #include "common/scram-common.h"
100 #include "common/sha2.h"
101 #include "libpq/crypt.h"
102 #include "libpq/sasl.h"
103 #include "libpq/scram.h"
105 static void scram_get_mechanisms(Port *port, StringInfo buf);
106 static void *scram_init(Port *port, const char *selected_mech,
107 const char *shadow_pass);
108 static int scram_exchange(void *opaq, const char *input, int inputlen,
109 char **output, int *outputlen,
110 const char **logdetail);
112 /* Mechanism declaration */
113 const pg_be_sasl_mech pg_be_scram_mech = {
114 scram_get_mechanisms,
115 scram_init,
116 scram_exchange
120 * Status data for a SCRAM authentication exchange. This should be kept
121 * internal to this file.
123 typedef enum
125 SCRAM_AUTH_INIT,
126 SCRAM_AUTH_SALT_SENT,
127 SCRAM_AUTH_FINISHED,
128 } scram_state_enum;
130 typedef struct
132 scram_state_enum state;
134 const char *username; /* username from startup packet */
136 Port *port;
137 bool channel_binding_in_use;
139 /* State data depending on the hash type */
140 pg_cryptohash_type hash_type;
141 int key_length;
143 int iterations;
144 char *salt; /* base64-encoded */
145 uint8 StoredKey[SCRAM_MAX_KEY_LEN];
146 uint8 ServerKey[SCRAM_MAX_KEY_LEN];
148 /* Fields of the first message from client */
149 char cbind_flag;
150 char *client_first_message_bare;
151 char *client_username;
152 char *client_nonce;
154 /* Fields from the last message from client */
155 char *client_final_message_without_proof;
156 char *client_final_nonce;
157 char ClientProof[SCRAM_MAX_KEY_LEN];
159 /* Fields generated in the server */
160 char *server_first_message;
161 char *server_nonce;
164 * If something goes wrong during the authentication, or we are performing
165 * a "mock" authentication (see comments at top of file), the 'doomed'
166 * flag is set. A reason for the failure, for the server log, is put in
167 * 'logdetail'.
169 bool doomed;
170 char *logdetail;
171 } scram_state;
173 static void read_client_first_message(scram_state *state, const char *input);
174 static void read_client_final_message(scram_state *state, const char *input);
175 static char *build_server_first_message(scram_state *state);
176 static char *build_server_final_message(scram_state *state);
177 static bool verify_client_proof(scram_state *state);
178 static bool verify_final_nonce(scram_state *state);
179 static void mock_scram_secret(const char *username, pg_cryptohash_type *hash_type,
180 int *iterations, int *key_length, char **salt,
181 uint8 *stored_key, uint8 *server_key);
182 static bool is_scram_printable(char *p);
183 static char *sanitize_char(char c);
184 static char *sanitize_str(const char *s);
185 static char *scram_mock_salt(const char *username,
186 pg_cryptohash_type hash_type,
187 int key_length);
190 * The number of iterations to use when generating new secrets.
192 int scram_sha_256_iterations = SCRAM_SHA_256_DEFAULT_ITERATIONS;
195 * Get a list of SASL mechanisms that this module supports.
197 * For the convenience of building the FE/BE packet that lists the
198 * mechanisms, the names are appended to the given StringInfo buffer,
199 * separated by '\0' bytes.
201 static void
202 scram_get_mechanisms(Port *port, StringInfo buf)
205 * Advertise the mechanisms in decreasing order of importance. So the
206 * channel-binding variants go first, if they are supported. Channel
207 * binding is only supported with SSL.
209 #ifdef USE_SSL
210 if (port->ssl_in_use)
212 appendStringInfoString(buf, SCRAM_SHA_256_PLUS_NAME);
213 appendStringInfoChar(buf, '\0');
215 #endif
216 appendStringInfoString(buf, SCRAM_SHA_256_NAME);
217 appendStringInfoChar(buf, '\0');
221 * Initialize a new SCRAM authentication exchange status tracker. This
222 * needs to be called before doing any exchange. It will be filled later
223 * after the beginning of the exchange with authentication information.
225 * 'selected_mech' identifies the SASL mechanism that the client selected.
226 * It should be one of the mechanisms that we support, as returned by
227 * scram_get_mechanisms().
229 * 'shadow_pass' is the role's stored secret, from pg_authid.rolpassword.
230 * The username was provided by the client in the startup message, and is
231 * available in port->user_name. If 'shadow_pass' is NULL, we still perform
232 * an authentication exchange, but it will fail, as if an incorrect password
233 * was given.
235 static void *
236 scram_init(Port *port, const char *selected_mech, const char *shadow_pass)
238 scram_state *state;
239 bool got_secret;
241 state = (scram_state *) palloc0(sizeof(scram_state));
242 state->port = port;
243 state->state = SCRAM_AUTH_INIT;
246 * Parse the selected mechanism.
248 * Note that if we don't support channel binding, or if we're not using
249 * SSL at all, we would not have advertised the PLUS variant in the first
250 * place. If the client nevertheless tries to select it, it's a protocol
251 * violation like selecting any other SASL mechanism we don't support.
253 #ifdef USE_SSL
254 if (strcmp(selected_mech, SCRAM_SHA_256_PLUS_NAME) == 0 && port->ssl_in_use)
255 state->channel_binding_in_use = true;
256 else
257 #endif
258 if (strcmp(selected_mech, SCRAM_SHA_256_NAME) == 0)
259 state->channel_binding_in_use = false;
260 else
261 ereport(ERROR,
262 (errcode(ERRCODE_PROTOCOL_VIOLATION),
263 errmsg("client selected an invalid SASL authentication mechanism")));
266 * Parse the stored secret.
268 if (shadow_pass)
270 int password_type = get_password_type(shadow_pass);
272 if (password_type == PASSWORD_TYPE_SCRAM_SHA_256)
274 if (parse_scram_secret(shadow_pass, &state->iterations,
275 &state->hash_type, &state->key_length,
276 &state->salt,
277 state->StoredKey,
278 state->ServerKey))
279 got_secret = true;
280 else
283 * The password looked like a SCRAM secret, but could not be
284 * parsed.
286 ereport(LOG,
287 (errmsg("invalid SCRAM secret for user \"%s\"",
288 state->port->user_name)));
289 got_secret = false;
292 else
295 * The user doesn't have SCRAM secret. (You cannot do SCRAM
296 * authentication with an MD5 hash.)
298 state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM secret."),
299 state->port->user_name);
300 got_secret = false;
303 else
306 * The caller requested us to perform a dummy authentication. This is
307 * considered normal, since the caller requested it, so don't set log
308 * detail.
310 got_secret = false;
314 * If the user did not have a valid SCRAM secret, we still go through the
315 * motions with a mock one, and fail as if the client supplied an
316 * incorrect password. This is to avoid revealing information to an
317 * attacker.
319 if (!got_secret)
321 mock_scram_secret(state->port->user_name, &state->hash_type,
322 &state->iterations, &state->key_length,
323 &state->salt,
324 state->StoredKey, state->ServerKey);
325 state->doomed = true;
328 return state;
332 * Continue a SCRAM authentication exchange.
334 * 'input' is the SCRAM payload sent by the client. On the first call,
335 * 'input' contains the "Initial Client Response" that the client sent as
336 * part of the SASLInitialResponse message, or NULL if no Initial Client
337 * Response was given. (The SASL specification distinguishes between an
338 * empty response and non-existing one.) On subsequent calls, 'input'
339 * cannot be NULL. For convenience in this function, the caller must
340 * ensure that there is a null terminator at input[inputlen].
342 * The next message to send to client is saved in 'output', for a length
343 * of 'outputlen'. In the case of an error, optionally store a palloc'd
344 * string at *logdetail that will be sent to the postmaster log (but not
345 * the client).
347 static int
348 scram_exchange(void *opaq, const char *input, int inputlen,
349 char **output, int *outputlen, const char **logdetail)
351 scram_state *state = (scram_state *) opaq;
352 int result;
354 *output = NULL;
357 * If the client didn't include an "Initial Client Response" in the
358 * SASLInitialResponse message, send an empty challenge, to which the
359 * client will respond with the same data that usually comes in the
360 * Initial Client Response.
362 if (input == NULL)
364 Assert(state->state == SCRAM_AUTH_INIT);
366 *output = pstrdup("");
367 *outputlen = 0;
368 return PG_SASL_EXCHANGE_CONTINUE;
372 * Check that the input length agrees with the string length of the input.
373 * We can ignore inputlen after this.
375 if (inputlen == 0)
376 ereport(ERROR,
377 (errcode(ERRCODE_PROTOCOL_VIOLATION),
378 errmsg("malformed SCRAM message"),
379 errdetail("The message is empty.")));
380 if (inputlen != strlen(input))
381 ereport(ERROR,
382 (errcode(ERRCODE_PROTOCOL_VIOLATION),
383 errmsg("malformed SCRAM message"),
384 errdetail("Message length does not match input length.")));
386 switch (state->state)
388 case SCRAM_AUTH_INIT:
391 * Initialization phase. Receive the first message from client
392 * and be sure that it parsed correctly. Then send the challenge
393 * to the client.
395 read_client_first_message(state, input);
397 /* prepare message to send challenge */
398 *output = build_server_first_message(state);
400 state->state = SCRAM_AUTH_SALT_SENT;
401 result = PG_SASL_EXCHANGE_CONTINUE;
402 break;
404 case SCRAM_AUTH_SALT_SENT:
407 * Final phase for the server. Receive the response to the
408 * challenge previously sent, verify, and let the client know that
409 * everything went well (or not).
411 read_client_final_message(state, input);
413 if (!verify_final_nonce(state))
414 ereport(ERROR,
415 (errcode(ERRCODE_PROTOCOL_VIOLATION),
416 errmsg("invalid SCRAM response"),
417 errdetail("Nonce does not match.")));
420 * Now check the final nonce and the client proof.
422 * If we performed a "mock" authentication that we knew would fail
423 * from the get go, this is where we fail.
425 * The SCRAM specification includes an error code,
426 * "invalid-proof", for authentication failure, but it also allows
427 * erroring out in an application-specific way. We choose to do
428 * the latter, so that the error message for invalid password is
429 * the same for all authentication methods. The caller will call
430 * ereport(), when we return PG_SASL_EXCHANGE_FAILURE with no
431 * output.
433 * NB: the order of these checks is intentional. We calculate the
434 * client proof even in a mock authentication, even though it's
435 * bound to fail, to thwart timing attacks to determine if a role
436 * with the given name exists or not.
438 if (!verify_client_proof(state) || state->doomed)
440 result = PG_SASL_EXCHANGE_FAILURE;
441 break;
444 /* Build final message for client */
445 *output = build_server_final_message(state);
447 /* Success! */
448 result = PG_SASL_EXCHANGE_SUCCESS;
449 state->state = SCRAM_AUTH_FINISHED;
450 break;
452 default:
453 elog(ERROR, "invalid SCRAM exchange state");
454 result = PG_SASL_EXCHANGE_FAILURE;
457 if (result == PG_SASL_EXCHANGE_FAILURE && state->logdetail && logdetail)
458 *logdetail = state->logdetail;
460 if (*output)
461 *outputlen = strlen(*output);
463 return result;
467 * Construct a SCRAM secret, for storing in pg_authid.rolpassword.
469 * The result is palloc'd, so caller is responsible for freeing it.
471 char *
472 pg_be_scram_build_secret(const char *password)
474 char *prep_password;
475 pg_saslprep_rc rc;
476 char saltbuf[SCRAM_DEFAULT_SALT_LEN];
477 char *result;
478 const char *errstr = NULL;
481 * Normalize the password with SASLprep. If that doesn't work, because
482 * the password isn't valid UTF-8 or contains prohibited characters, just
483 * proceed with the original password. (See comments at top of file.)
485 rc = pg_saslprep(password, &prep_password);
486 if (rc == SASLPREP_SUCCESS)
487 password = (const char *) prep_password;
489 /* Generate random salt */
490 if (!pg_strong_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
491 ereport(ERROR,
492 (errcode(ERRCODE_INTERNAL_ERROR),
493 errmsg("could not generate random salt")));
495 result = scram_build_secret(PG_SHA256, SCRAM_SHA_256_KEY_LEN,
496 saltbuf, SCRAM_DEFAULT_SALT_LEN,
497 scram_sha_256_iterations, password,
498 &errstr);
500 if (prep_password)
501 pfree(prep_password);
503 return result;
507 * Verify a plaintext password against a SCRAM secret. This is used when
508 * performing plaintext password authentication for a user that has a SCRAM
509 * secret stored in pg_authid.
511 bool
512 scram_verify_plain_password(const char *username, const char *password,
513 const char *secret)
515 char *encoded_salt;
516 char *salt;
517 int saltlen;
518 int iterations;
519 int key_length = 0;
520 pg_cryptohash_type hash_type;
521 uint8 salted_password[SCRAM_MAX_KEY_LEN];
522 uint8 stored_key[SCRAM_MAX_KEY_LEN];
523 uint8 server_key[SCRAM_MAX_KEY_LEN];
524 uint8 computed_key[SCRAM_MAX_KEY_LEN];
525 char *prep_password;
526 pg_saslprep_rc rc;
527 const char *errstr = NULL;
529 if (!parse_scram_secret(secret, &iterations, &hash_type, &key_length,
530 &encoded_salt, stored_key, server_key))
533 * The password looked like a SCRAM secret, but could not be parsed.
535 ereport(LOG,
536 (errmsg("invalid SCRAM secret for user \"%s\"", username)));
537 return false;
540 saltlen = pg_b64_dec_len(strlen(encoded_salt));
541 salt = palloc(saltlen);
542 saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt,
543 saltlen);
544 if (saltlen < 0)
546 ereport(LOG,
547 (errmsg("invalid SCRAM secret for user \"%s\"", username)));
548 return false;
551 /* Normalize the password */
552 rc = pg_saslprep(password, &prep_password);
553 if (rc == SASLPREP_SUCCESS)
554 password = prep_password;
556 /* Compute Server Key based on the user-supplied plaintext password */
557 if (scram_SaltedPassword(password, hash_type, key_length,
558 salt, saltlen, iterations,
559 salted_password, &errstr) < 0 ||
560 scram_ServerKey(salted_password, hash_type, key_length,
561 computed_key, &errstr) < 0)
563 elog(ERROR, "could not compute server key: %s", errstr);
566 if (prep_password)
567 pfree(prep_password);
570 * Compare the secret's Server Key with the one computed from the
571 * user-supplied password.
573 return memcmp(computed_key, server_key, key_length) == 0;
578 * Parse and validate format of given SCRAM secret.
580 * On success, the iteration count, salt, stored key, and server key are
581 * extracted from the secret, and returned to the caller. For 'stored_key'
582 * and 'server_key', the caller must pass pre-allocated buffers of size
583 * SCRAM_MAX_KEY_LEN. Salt is returned as a base64-encoded, null-terminated
584 * string. The buffer for the salt is palloc'd by this function.
586 * Returns true if the SCRAM secret has been parsed, and false otherwise.
588 bool
589 parse_scram_secret(const char *secret, int *iterations,
590 pg_cryptohash_type *hash_type, int *key_length,
591 char **salt, uint8 *stored_key, uint8 *server_key)
593 char *v;
594 char *p;
595 char *scheme_str;
596 char *salt_str;
597 char *iterations_str;
598 char *storedkey_str;
599 char *serverkey_str;
600 int decoded_len;
601 char *decoded_salt_buf;
602 char *decoded_stored_buf;
603 char *decoded_server_buf;
606 * The secret is of form:
608 * SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
610 v = pstrdup(secret);
611 if ((scheme_str = strtok(v, "$")) == NULL)
612 goto invalid_secret;
613 if ((iterations_str = strtok(NULL, ":")) == NULL)
614 goto invalid_secret;
615 if ((salt_str = strtok(NULL, "$")) == NULL)
616 goto invalid_secret;
617 if ((storedkey_str = strtok(NULL, ":")) == NULL)
618 goto invalid_secret;
619 if ((serverkey_str = strtok(NULL, "")) == NULL)
620 goto invalid_secret;
622 /* Parse the fields */
623 if (strcmp(scheme_str, "SCRAM-SHA-256") != 0)
624 goto invalid_secret;
625 *hash_type = PG_SHA256;
626 *key_length = SCRAM_SHA_256_KEY_LEN;
628 errno = 0;
629 *iterations = strtol(iterations_str, &p, 10);
630 if (*p || errno != 0)
631 goto invalid_secret;
634 * Verify that the salt is in Base64-encoded format, by decoding it,
635 * although we return the encoded version to the caller.
637 decoded_len = pg_b64_dec_len(strlen(salt_str));
638 decoded_salt_buf = palloc(decoded_len);
639 decoded_len = pg_b64_decode(salt_str, strlen(salt_str),
640 decoded_salt_buf, decoded_len);
641 if (decoded_len < 0)
642 goto invalid_secret;
643 *salt = pstrdup(salt_str);
646 * Decode StoredKey and ServerKey.
648 decoded_len = pg_b64_dec_len(strlen(storedkey_str));
649 decoded_stored_buf = palloc(decoded_len);
650 decoded_len = pg_b64_decode(storedkey_str, strlen(storedkey_str),
651 decoded_stored_buf, decoded_len);
652 if (decoded_len != *key_length)
653 goto invalid_secret;
654 memcpy(stored_key, decoded_stored_buf, *key_length);
656 decoded_len = pg_b64_dec_len(strlen(serverkey_str));
657 decoded_server_buf = palloc(decoded_len);
658 decoded_len = pg_b64_decode(serverkey_str, strlen(serverkey_str),
659 decoded_server_buf, decoded_len);
660 if (decoded_len != *key_length)
661 goto invalid_secret;
662 memcpy(server_key, decoded_server_buf, *key_length);
664 return true;
666 invalid_secret:
667 *salt = NULL;
668 return false;
672 * Generate plausible SCRAM secret parameters for mock authentication.
674 * In a normal authentication, these are extracted from the secret
675 * stored in the server. This function generates values that look
676 * realistic, for when there is no stored secret, using SCRAM-SHA-256.
678 * Like in parse_scram_secret(), for 'stored_key' and 'server_key', the
679 * caller must pass pre-allocated buffers of size SCRAM_MAX_KEY_LEN, and
680 * the buffer for the salt is palloc'd by this function.
682 static void
683 mock_scram_secret(const char *username, pg_cryptohash_type *hash_type,
684 int *iterations, int *key_length, char **salt,
685 uint8 *stored_key, uint8 *server_key)
687 char *raw_salt;
688 char *encoded_salt;
689 int encoded_len;
691 /* Enforce the use of SHA-256, which would be realistic enough */
692 *hash_type = PG_SHA256;
693 *key_length = SCRAM_SHA_256_KEY_LEN;
696 * Generate deterministic salt.
698 * Note that we cannot reveal any information to an attacker here so the
699 * error messages need to remain generic. This should never fail anyway
700 * as the salt generated for mock authentication uses the cluster's nonce
701 * value.
703 raw_salt = scram_mock_salt(username, *hash_type, *key_length);
704 if (raw_salt == NULL)
705 elog(ERROR, "could not encode salt");
707 encoded_len = pg_b64_enc_len(SCRAM_DEFAULT_SALT_LEN);
708 /* don't forget the zero-terminator */
709 encoded_salt = (char *) palloc(encoded_len + 1);
710 encoded_len = pg_b64_encode(raw_salt, SCRAM_DEFAULT_SALT_LEN, encoded_salt,
711 encoded_len);
713 if (encoded_len < 0)
714 elog(ERROR, "could not encode salt");
715 encoded_salt[encoded_len] = '\0';
717 *salt = encoded_salt;
718 *iterations = SCRAM_SHA_256_DEFAULT_ITERATIONS;
720 /* StoredKey and ServerKey are not used in a doomed authentication */
721 memset(stored_key, 0, SCRAM_MAX_KEY_LEN);
722 memset(server_key, 0, SCRAM_MAX_KEY_LEN);
726 * Read the value in a given SCRAM exchange message for given attribute.
728 static char *
729 read_attr_value(char **input, char attr)
731 char *begin = *input;
732 char *end;
734 if (*begin != attr)
735 ereport(ERROR,
736 (errcode(ERRCODE_PROTOCOL_VIOLATION),
737 errmsg("malformed SCRAM message"),
738 errdetail("Expected attribute \"%c\" but found \"%s\".",
739 attr, sanitize_char(*begin))));
740 begin++;
742 if (*begin != '=')
743 ereport(ERROR,
744 (errcode(ERRCODE_PROTOCOL_VIOLATION),
745 errmsg("malformed SCRAM message"),
746 errdetail("Expected character \"=\" for attribute \"%c\".", attr)));
747 begin++;
749 end = begin;
750 while (*end && *end != ',')
751 end++;
753 if (*end)
755 *end = '\0';
756 *input = end + 1;
758 else
759 *input = end;
761 return begin;
764 static bool
765 is_scram_printable(char *p)
767 /*------
768 * Printable characters, as defined by SCRAM spec: (RFC 5802)
770 * printable = %x21-2B / %x2D-7E
771 * ;; Printable ASCII except ",".
772 * ;; Note that any "printable" is also
773 * ;; a valid "value".
774 *------
776 for (; *p; p++)
778 if (*p < 0x21 || *p > 0x7E || *p == 0x2C /* comma */ )
779 return false;
781 return true;
785 * Convert an arbitrary byte to printable form. For error messages.
787 * If it's a printable ASCII character, print it as a single character.
788 * otherwise, print it in hex.
790 * The returned pointer points to a static buffer.
792 static char *
793 sanitize_char(char c)
795 static char buf[5];
797 if (c >= 0x21 && c <= 0x7E)
798 snprintf(buf, sizeof(buf), "'%c'", c);
799 else
800 snprintf(buf, sizeof(buf), "0x%02x", (unsigned char) c);
801 return buf;
805 * Convert an arbitrary string to printable form, for error messages.
807 * Anything that's not a printable ASCII character is replaced with
808 * '?', and the string is truncated at 30 characters.
810 * The returned pointer points to a static buffer.
812 static char *
813 sanitize_str(const char *s)
815 static char buf[30 + 1];
816 int i;
818 for (i = 0; i < sizeof(buf) - 1; i++)
820 char c = s[i];
822 if (c == '\0')
823 break;
825 if (c >= 0x21 && c <= 0x7E)
826 buf[i] = c;
827 else
828 buf[i] = '?';
830 buf[i] = '\0';
831 return buf;
835 * Read the next attribute and value in a SCRAM exchange message.
837 * The attribute character is set in *attr_p, the attribute value is the
838 * return value.
840 static char *
841 read_any_attr(char **input, char *attr_p)
843 char *begin = *input;
844 char *end;
845 char attr = *begin;
847 if (attr == '\0')
848 ereport(ERROR,
849 (errcode(ERRCODE_PROTOCOL_VIOLATION),
850 errmsg("malformed SCRAM message"),
851 errdetail("Attribute expected, but found end of string.")));
853 /*------
854 * attr-val = ALPHA "=" value
855 * ;; Generic syntax of any attribute sent
856 * ;; by server or client
857 *------
859 if (!((attr >= 'A' && attr <= 'Z') ||
860 (attr >= 'a' && attr <= 'z')))
861 ereport(ERROR,
862 (errcode(ERRCODE_PROTOCOL_VIOLATION),
863 errmsg("malformed SCRAM message"),
864 errdetail("Attribute expected, but found invalid character \"%s\".",
865 sanitize_char(attr))));
866 if (attr_p)
867 *attr_p = attr;
868 begin++;
870 if (*begin != '=')
871 ereport(ERROR,
872 (errcode(ERRCODE_PROTOCOL_VIOLATION),
873 errmsg("malformed SCRAM message"),
874 errdetail("Expected character \"=\" for attribute \"%c\".", attr)));
875 begin++;
877 end = begin;
878 while (*end && *end != ',')
879 end++;
881 if (*end)
883 *end = '\0';
884 *input = end + 1;
886 else
887 *input = end;
889 return begin;
893 * Read and parse the first message from client in the context of a SCRAM
894 * authentication exchange message.
896 * At this stage, any errors will be reported directly with ereport(ERROR).
898 static void
899 read_client_first_message(scram_state *state, const char *input)
901 char *p = pstrdup(input);
902 char *channel_binding_type;
905 /*------
906 * The syntax for the client-first-message is: (RFC 5802)
908 * saslname = 1*(value-safe-char / "=2C" / "=3D")
909 * ;; Conforms to <value>.
911 * authzid = "a=" saslname
912 * ;; Protocol specific.
914 * cb-name = 1*(ALPHA / DIGIT / "." / "-")
915 * ;; See RFC 5056, Section 7.
916 * ;; E.g., "tls-server-end-point" or
917 * ;; "tls-unique".
919 * gs2-cbind-flag = ("p=" cb-name) / "n" / "y"
920 * ;; "n" -> client doesn't support channel binding.
921 * ;; "y" -> client does support channel binding
922 * ;; but thinks the server does not.
923 * ;; "p" -> client requires channel binding.
924 * ;; The selected channel binding follows "p=".
926 * gs2-header = gs2-cbind-flag "," [ authzid ] ","
927 * ;; GS2 header for SCRAM
928 * ;; (the actual GS2 header includes an optional
929 * ;; flag to indicate that the GSS mechanism is not
930 * ;; "standard", but since SCRAM is "standard", we
931 * ;; don't include that flag).
933 * username = "n=" saslname
934 * ;; Usernames are prepared using SASLprep.
936 * reserved-mext = "m=" 1*(value-char)
937 * ;; Reserved for signaling mandatory extensions.
938 * ;; The exact syntax will be defined in
939 * ;; the future.
941 * nonce = "r=" c-nonce [s-nonce]
942 * ;; Second part provided by server.
944 * c-nonce = printable
946 * client-first-message-bare =
947 * [reserved-mext ","]
948 * username "," nonce ["," extensions]
950 * client-first-message =
951 * gs2-header client-first-message-bare
953 * For example:
954 * n,,n=user,r=fyko+d2lbbFgONRv9qkxdawL
956 * The "n,," in the beginning means that the client doesn't support
957 * channel binding, and no authzid is given. "n=user" is the username.
958 * However, in PostgreSQL the username is sent in the startup packet, and
959 * the username in the SCRAM exchange is ignored. libpq always sends it
960 * as an empty string. The last part, "r=fyko+d2lbbFgONRv9qkxdawL" is
961 * the client nonce.
962 *------
966 * Read gs2-cbind-flag. (For details see also RFC 5802 Section 6 "Channel
967 * Binding".)
969 state->cbind_flag = *p;
970 switch (*p)
972 case 'n':
975 * The client does not support channel binding or has simply
976 * decided to not use it. In that case just let it go.
978 if (state->channel_binding_in_use)
979 ereport(ERROR,
980 (errcode(ERRCODE_PROTOCOL_VIOLATION),
981 errmsg("malformed SCRAM message"),
982 errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
984 p++;
985 if (*p != ',')
986 ereport(ERROR,
987 (errcode(ERRCODE_PROTOCOL_VIOLATION),
988 errmsg("malformed SCRAM message"),
989 errdetail("Comma expected, but found character \"%s\".",
990 sanitize_char(*p))));
991 p++;
992 break;
993 case 'y':
996 * The client supports channel binding and thinks that the server
997 * does not. In this case, the server must fail authentication if
998 * it supports channel binding.
1000 if (state->channel_binding_in_use)
1001 ereport(ERROR,
1002 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1003 errmsg("malformed SCRAM message"),
1004 errdetail("The client selected SCRAM-SHA-256-PLUS, but the SCRAM message does not include channel binding data.")));
1006 #ifdef USE_SSL
1007 if (state->port->ssl_in_use)
1008 ereport(ERROR,
1009 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
1010 errmsg("SCRAM channel binding negotiation error"),
1011 errdetail("The client supports SCRAM channel binding but thinks the server does not. "
1012 "However, this server does support channel binding.")));
1013 #endif
1014 p++;
1015 if (*p != ',')
1016 ereport(ERROR,
1017 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1018 errmsg("malformed SCRAM message"),
1019 errdetail("Comma expected, but found character \"%s\".",
1020 sanitize_char(*p))));
1021 p++;
1022 break;
1023 case 'p':
1026 * The client requires channel binding. Channel binding type
1027 * follows, e.g., "p=tls-server-end-point".
1029 if (!state->channel_binding_in_use)
1030 ereport(ERROR,
1031 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1032 errmsg("malformed SCRAM message"),
1033 errdetail("The client selected SCRAM-SHA-256 without channel binding, but the SCRAM message includes channel binding data.")));
1035 channel_binding_type = read_attr_value(&p, 'p');
1038 * The only channel binding type we support is
1039 * tls-server-end-point.
1041 if (strcmp(channel_binding_type, "tls-server-end-point") != 0)
1042 ereport(ERROR,
1043 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1044 errmsg("unsupported SCRAM channel-binding type \"%s\"",
1045 sanitize_str(channel_binding_type))));
1046 break;
1047 default:
1048 ereport(ERROR,
1049 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1050 errmsg("malformed SCRAM message"),
1051 errdetail("Unexpected channel-binding flag \"%s\".",
1052 sanitize_char(*p))));
1056 * Forbid optional authzid (authorization identity). We don't support it.
1058 if (*p == 'a')
1059 ereport(ERROR,
1060 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1061 errmsg("client uses authorization identity, but it is not supported")));
1062 if (*p != ',')
1063 ereport(ERROR,
1064 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1065 errmsg("malformed SCRAM message"),
1066 errdetail("Unexpected attribute \"%s\" in client-first-message.",
1067 sanitize_char(*p))));
1068 p++;
1070 state->client_first_message_bare = pstrdup(p);
1073 * Any mandatory extensions would go here. We don't support any.
1075 * RFC 5802 specifies error code "e=extensions-not-supported" for this,
1076 * but it can only be sent in the server-final message. We prefer to fail
1077 * immediately (which the RFC also allows).
1079 if (*p == 'm')
1080 ereport(ERROR,
1081 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1082 errmsg("client requires an unsupported SCRAM extension")));
1085 * Read username. Note: this is ignored. We use the username from the
1086 * startup message instead, still it is kept around if provided as it
1087 * proves to be useful for debugging purposes.
1089 state->client_username = read_attr_value(&p, 'n');
1091 /* read nonce and check that it is made of only printable characters */
1092 state->client_nonce = read_attr_value(&p, 'r');
1093 if (!is_scram_printable(state->client_nonce))
1094 ereport(ERROR,
1095 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1096 errmsg("non-printable characters in SCRAM nonce")));
1099 * There can be any number of optional extensions after this. We don't
1100 * support any extensions, so ignore them.
1102 while (*p != '\0')
1103 read_any_attr(&p, NULL);
1105 /* success! */
1109 * Verify the final nonce contained in the last message received from
1110 * client in an exchange.
1112 static bool
1113 verify_final_nonce(scram_state *state)
1115 int client_nonce_len = strlen(state->client_nonce);
1116 int server_nonce_len = strlen(state->server_nonce);
1117 int final_nonce_len = strlen(state->client_final_nonce);
1119 if (final_nonce_len != client_nonce_len + server_nonce_len)
1120 return false;
1121 if (memcmp(state->client_final_nonce, state->client_nonce, client_nonce_len) != 0)
1122 return false;
1123 if (memcmp(state->client_final_nonce + client_nonce_len, state->server_nonce, server_nonce_len) != 0)
1124 return false;
1126 return true;
1130 * Verify the client proof contained in the last message received from
1131 * client in an exchange. Returns true if the verification is a success,
1132 * or false for a failure.
1134 static bool
1135 verify_client_proof(scram_state *state)
1137 uint8 ClientSignature[SCRAM_MAX_KEY_LEN];
1138 uint8 ClientKey[SCRAM_MAX_KEY_LEN];
1139 uint8 client_StoredKey[SCRAM_MAX_KEY_LEN];
1140 pg_hmac_ctx *ctx = pg_hmac_create(state->hash_type);
1141 int i;
1142 const char *errstr = NULL;
1145 * Calculate ClientSignature. Note that we don't log directly a failure
1146 * here even when processing the calculations as this could involve a mock
1147 * authentication.
1149 if (pg_hmac_init(ctx, state->StoredKey, state->key_length) < 0 ||
1150 pg_hmac_update(ctx,
1151 (uint8 *) state->client_first_message_bare,
1152 strlen(state->client_first_message_bare)) < 0 ||
1153 pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
1154 pg_hmac_update(ctx,
1155 (uint8 *) state->server_first_message,
1156 strlen(state->server_first_message)) < 0 ||
1157 pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
1158 pg_hmac_update(ctx,
1159 (uint8 *) state->client_final_message_without_proof,
1160 strlen(state->client_final_message_without_proof)) < 0 ||
1161 pg_hmac_final(ctx, ClientSignature, state->key_length) < 0)
1163 elog(ERROR, "could not calculate client signature: %s",
1164 pg_hmac_error(ctx));
1167 pg_hmac_free(ctx);
1169 /* Extract the ClientKey that the client calculated from the proof */
1170 for (i = 0; i < state->key_length; i++)
1171 ClientKey[i] = state->ClientProof[i] ^ ClientSignature[i];
1173 /* Hash it one more time, and compare with StoredKey */
1174 if (scram_H(ClientKey, state->hash_type, state->key_length,
1175 client_StoredKey, &errstr) < 0)
1176 elog(ERROR, "could not hash stored key: %s", errstr);
1178 if (memcmp(client_StoredKey, state->StoredKey, state->key_length) != 0)
1179 return false;
1181 return true;
1185 * Build the first server-side message sent to the client in a SCRAM
1186 * communication exchange.
1188 static char *
1189 build_server_first_message(scram_state *state)
1191 /*------
1192 * The syntax for the server-first-message is: (RFC 5802)
1194 * server-first-message =
1195 * [reserved-mext ","] nonce "," salt ","
1196 * iteration-count ["," extensions]
1198 * nonce = "r=" c-nonce [s-nonce]
1199 * ;; Second part provided by server.
1201 * c-nonce = printable
1203 * s-nonce = printable
1205 * salt = "s=" base64
1207 * iteration-count = "i=" posit-number
1208 * ;; A positive number.
1210 * Example:
1212 * r=fyko+d2lbbFgONRv9qkxdawL3rfcNHYJY1ZVvWVs7j,s=QSXCR+Q6sek8bf92,i=4096
1213 *------
1217 * Per the spec, the nonce may consist of any printable ASCII characters.
1218 * For convenience, however, we don't use the whole range available,
1219 * rather, we generate some random bytes, and base64 encode them.
1221 char raw_nonce[SCRAM_RAW_NONCE_LEN];
1222 int encoded_len;
1224 if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
1225 ereport(ERROR,
1226 (errcode(ERRCODE_INTERNAL_ERROR),
1227 errmsg("could not generate random nonce")));
1229 encoded_len = pg_b64_enc_len(SCRAM_RAW_NONCE_LEN);
1230 /* don't forget the zero-terminator */
1231 state->server_nonce = palloc(encoded_len + 1);
1232 encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN,
1233 state->server_nonce, encoded_len);
1234 if (encoded_len < 0)
1235 ereport(ERROR,
1236 (errcode(ERRCODE_INTERNAL_ERROR),
1237 errmsg("could not encode random nonce")));
1238 state->server_nonce[encoded_len] = '\0';
1240 state->server_first_message =
1241 psprintf("r=%s%s,s=%s,i=%d",
1242 state->client_nonce, state->server_nonce,
1243 state->salt, state->iterations);
1245 return pstrdup(state->server_first_message);
1250 * Read and parse the final message received from client.
1252 static void
1253 read_client_final_message(scram_state *state, const char *input)
1255 char attr;
1256 char *channel_binding;
1257 char *value;
1258 char *begin,
1259 *proof;
1260 char *p;
1261 char *client_proof;
1262 int client_proof_len;
1264 begin = p = pstrdup(input);
1266 /*------
1267 * The syntax for the server-first-message is: (RFC 5802)
1269 * gs2-header = gs2-cbind-flag "," [ authzid ] ","
1270 * ;; GS2 header for SCRAM
1271 * ;; (the actual GS2 header includes an optional
1272 * ;; flag to indicate that the GSS mechanism is not
1273 * ;; "standard", but since SCRAM is "standard", we
1274 * ;; don't include that flag).
1276 * cbind-input = gs2-header [ cbind-data ]
1277 * ;; cbind-data MUST be present for
1278 * ;; gs2-cbind-flag of "p" and MUST be absent
1279 * ;; for "y" or "n".
1281 * channel-binding = "c=" base64
1282 * ;; base64 encoding of cbind-input.
1284 * proof = "p=" base64
1286 * client-final-message-without-proof =
1287 * channel-binding "," nonce [","
1288 * extensions]
1290 * client-final-message =
1291 * client-final-message-without-proof "," proof
1292 *------
1296 * Read channel binding. This repeats the channel-binding flags and is
1297 * then followed by the actual binding data depending on the type.
1299 channel_binding = read_attr_value(&p, 'c');
1300 if (state->channel_binding_in_use)
1302 #ifdef USE_SSL
1303 const char *cbind_data = NULL;
1304 size_t cbind_data_len = 0;
1305 size_t cbind_header_len;
1306 char *cbind_input;
1307 size_t cbind_input_len;
1308 char *b64_message;
1309 int b64_message_len;
1311 Assert(state->cbind_flag == 'p');
1313 /* Fetch hash data of server's SSL certificate */
1314 cbind_data = be_tls_get_certificate_hash(state->port,
1315 &cbind_data_len);
1317 /* should not happen */
1318 if (cbind_data == NULL || cbind_data_len == 0)
1319 elog(ERROR, "could not get server certificate hash");
1321 cbind_header_len = strlen("p=tls-server-end-point,,"); /* p=type,, */
1322 cbind_input_len = cbind_header_len + cbind_data_len;
1323 cbind_input = palloc(cbind_input_len);
1324 snprintf(cbind_input, cbind_input_len, "p=tls-server-end-point,,");
1325 memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
1327 b64_message_len = pg_b64_enc_len(cbind_input_len);
1328 /* don't forget the zero-terminator */
1329 b64_message = palloc(b64_message_len + 1);
1330 b64_message_len = pg_b64_encode(cbind_input, cbind_input_len,
1331 b64_message, b64_message_len);
1332 if (b64_message_len < 0)
1333 elog(ERROR, "could not encode channel binding data");
1334 b64_message[b64_message_len] = '\0';
1337 * Compare the value sent by the client with the value expected by the
1338 * server.
1340 if (strcmp(channel_binding, b64_message) != 0)
1341 ereport(ERROR,
1342 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
1343 errmsg("SCRAM channel binding check failed")));
1344 #else
1345 /* shouldn't happen, because we checked this earlier already */
1346 elog(ERROR, "channel binding not supported by this build");
1347 #endif
1349 else
1352 * If we are not using channel binding, the binding data is expected
1353 * to always be "biws", which is "n,," base64-encoded, or "eSws",
1354 * which is "y,,". We also have to check whether the flag is the same
1355 * one that the client originally sent.
1357 if (!(strcmp(channel_binding, "biws") == 0 && state->cbind_flag == 'n') &&
1358 !(strcmp(channel_binding, "eSws") == 0 && state->cbind_flag == 'y'))
1359 ereport(ERROR,
1360 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1361 errmsg("unexpected SCRAM channel-binding attribute in client-final-message")));
1364 state->client_final_nonce = read_attr_value(&p, 'r');
1366 /* ignore optional extensions, read until we find "p" attribute */
1369 proof = p - 1;
1370 value = read_any_attr(&p, &attr);
1371 } while (attr != 'p');
1373 client_proof_len = pg_b64_dec_len(strlen(value));
1374 client_proof = palloc(client_proof_len);
1375 if (pg_b64_decode(value, strlen(value), client_proof,
1376 client_proof_len) != state->key_length)
1377 ereport(ERROR,
1378 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1379 errmsg("malformed SCRAM message"),
1380 errdetail("Malformed proof in client-final-message.")));
1381 memcpy(state->ClientProof, client_proof, state->key_length);
1382 pfree(client_proof);
1384 if (*p != '\0')
1385 ereport(ERROR,
1386 (errcode(ERRCODE_PROTOCOL_VIOLATION),
1387 errmsg("malformed SCRAM message"),
1388 errdetail("Garbage found at the end of client-final-message.")));
1390 state->client_final_message_without_proof = palloc(proof - begin + 1);
1391 memcpy(state->client_final_message_without_proof, input, proof - begin);
1392 state->client_final_message_without_proof[proof - begin] = '\0';
1396 * Build the final server-side message of an exchange.
1398 static char *
1399 build_server_final_message(scram_state *state)
1401 uint8 ServerSignature[SCRAM_MAX_KEY_LEN];
1402 char *server_signature_base64;
1403 int siglen;
1404 pg_hmac_ctx *ctx = pg_hmac_create(state->hash_type);
1406 /* calculate ServerSignature */
1407 if (pg_hmac_init(ctx, state->ServerKey, state->key_length) < 0 ||
1408 pg_hmac_update(ctx,
1409 (uint8 *) state->client_first_message_bare,
1410 strlen(state->client_first_message_bare)) < 0 ||
1411 pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
1412 pg_hmac_update(ctx,
1413 (uint8 *) state->server_first_message,
1414 strlen(state->server_first_message)) < 0 ||
1415 pg_hmac_update(ctx, (uint8 *) ",", 1) < 0 ||
1416 pg_hmac_update(ctx,
1417 (uint8 *) state->client_final_message_without_proof,
1418 strlen(state->client_final_message_without_proof)) < 0 ||
1419 pg_hmac_final(ctx, ServerSignature, state->key_length) < 0)
1421 elog(ERROR, "could not calculate server signature: %s",
1422 pg_hmac_error(ctx));
1425 pg_hmac_free(ctx);
1427 siglen = pg_b64_enc_len(state->key_length);
1428 /* don't forget the zero-terminator */
1429 server_signature_base64 = palloc(siglen + 1);
1430 siglen = pg_b64_encode((const char *) ServerSignature,
1431 state->key_length, server_signature_base64,
1432 siglen);
1433 if (siglen < 0)
1434 elog(ERROR, "could not encode server signature");
1435 server_signature_base64[siglen] = '\0';
1437 /*------
1438 * The syntax for the server-final-message is: (RFC 5802)
1440 * verifier = "v=" base64
1441 * ;; base-64 encoded ServerSignature.
1443 * server-final-message = (server-error / verifier)
1444 * ["," extensions]
1446 *------
1448 return psprintf("v=%s", server_signature_base64);
1453 * Deterministically generate salt for mock authentication, using a SHA256
1454 * hash based on the username and a cluster-level secret key. Returns a
1455 * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN, or NULL.
1457 static char *
1458 scram_mock_salt(const char *username, pg_cryptohash_type hash_type,
1459 int key_length)
1461 pg_cryptohash_ctx *ctx;
1462 static uint8 sha_digest[SCRAM_MAX_KEY_LEN];
1463 char *mock_auth_nonce = GetMockAuthenticationNonce();
1466 * Generate salt using a SHA256 hash of the username and the cluster's
1467 * mock authentication nonce. (This works as long as the salt length is
1468 * not larger than the SHA256 digest length. If the salt is smaller, the
1469 * caller will just ignore the extra data.)
1471 StaticAssertDecl(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN,
1472 "salt length greater than SHA256 digest length");
1475 * This may be worth refreshing if support for more hash methods is\
1476 * added.
1478 Assert(hash_type == PG_SHA256);
1480 ctx = pg_cryptohash_create(hash_type);
1481 if (pg_cryptohash_init(ctx) < 0 ||
1482 pg_cryptohash_update(ctx, (uint8 *) username, strlen(username)) < 0 ||
1483 pg_cryptohash_update(ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN) < 0 ||
1484 pg_cryptohash_final(ctx, sha_digest, key_length) < 0)
1486 pg_cryptohash_free(ctx);
1487 return NULL;
1489 pg_cryptohash_free(ctx);
1491 return (char *) sha_digest;