1 /*-------------------------------------------------------------------------
2  *
3  * fe-auth-scram.c
4  *	   The front-end (client) implementation of SCRAM authentication.
5  *
6  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *	  src/interfaces/libpq/fe-auth-scram.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres_fe.h"
16 
17 #include "common/base64.h"
18 #include "common/saslprep.h"
19 #include "common/scram-common.h"
20 #include "fe-auth.h"
21 
22 
23 /*
24  * Status of exchange messages used for SCRAM authentication via the
25  * SASL protocol.
26  */
27 typedef enum
28 {
29 	FE_SCRAM_INIT,
30 	FE_SCRAM_NONCE_SENT,
31 	FE_SCRAM_PROOF_SENT,
32 	FE_SCRAM_FINISHED
33 } fe_scram_state_enum;
34 
35 typedef struct
36 {
37 	fe_scram_state_enum state;
38 
39 	/* These are supplied by the user */
40 	PGconn	   *conn;
41 	char	   *password;
42 	char	   *sasl_mechanism;
43 
44 	/* We construct these */
45 	uint8		SaltedPassword[SCRAM_KEY_LEN];
46 	char	   *client_nonce;
47 	char	   *client_first_message_bare;
48 	char	   *client_final_message_without_proof;
49 
50 	/* These come from the server-first message */
51 	char	   *server_first_message;
52 	char	   *salt;
53 	int			saltlen;
54 	int			iterations;
55 	char	   *nonce;
56 
57 	/* These come from the server-final message */
58 	char	   *server_final_message;
59 	char		ServerSignature[SCRAM_KEY_LEN];
60 } fe_scram_state;
61 
62 static bool read_server_first_message(fe_scram_state *state, char *input);
63 static bool read_server_final_message(fe_scram_state *state, char *input);
64 static char *build_client_first_message(fe_scram_state *state);
65 static char *build_client_final_message(fe_scram_state *state);
66 static bool verify_server_signature(fe_scram_state *state);
67 static void calculate_client_proof(fe_scram_state *state,
68 								   const char *client_final_message_without_proof,
69 								   uint8 *result);
70 
71 /*
72  * Initialize SCRAM exchange status.
73  */
74 void *
75 pg_fe_scram_init(PGconn *conn,
76 				 const char *password,
77 				 const char *sasl_mechanism)
78 {
79 	fe_scram_state *state;
80 	char	   *prep_password;
81 	pg_saslprep_rc rc;
82 
83 	Assert(sasl_mechanism != NULL);
84 
85 	state = (fe_scram_state *) malloc(sizeof(fe_scram_state));
86 	if (!state)
87 		return NULL;
88 	memset(state, 0, sizeof(fe_scram_state));
89 	state->conn = conn;
90 	state->state = FE_SCRAM_INIT;
91 	state->sasl_mechanism = strdup(sasl_mechanism);
92 
93 	if (!state->sasl_mechanism)
94 	{
95 		free(state);
96 		return NULL;
97 	}
98 
99 	/* Normalize the password with SASLprep, if possible */
100 	rc = pg_saslprep(password, &prep_password);
101 	if (rc == SASLPREP_OOM)
102 	{
103 		free(state->sasl_mechanism);
104 		free(state);
105 		return NULL;
106 	}
107 	if (rc != SASLPREP_SUCCESS)
108 	{
109 		prep_password = strdup(password);
110 		if (!prep_password)
111 		{
112 			free(state->sasl_mechanism);
113 			free(state);
114 			return NULL;
115 		}
116 	}
117 	state->password = prep_password;
118 
119 	return state;
120 }
121 
122 /*
123  * Free SCRAM exchange status
124  */
125 void
126 pg_fe_scram_free(void *opaq)
127 {
128 	fe_scram_state *state = (fe_scram_state *) opaq;
129 
130 	if (state->password)
131 		free(state->password);
132 	if (state->sasl_mechanism)
133 		free(state->sasl_mechanism);
134 
135 	/* client messages */
136 	if (state->client_nonce)
137 		free(state->client_nonce);
138 	if (state->client_first_message_bare)
139 		free(state->client_first_message_bare);
140 	if (state->client_final_message_without_proof)
141 		free(state->client_final_message_without_proof);
142 
143 	/* first message from server */
144 	if (state->server_first_message)
145 		free(state->server_first_message);
146 	if (state->salt)
147 		free(state->salt);
148 	if (state->nonce)
149 		free(state->nonce);
150 
151 	/* final message from server */
152 	if (state->server_final_message)
153 		free(state->server_final_message);
154 
155 	free(state);
156 }
157 
158 /*
159  * Exchange a SCRAM message with backend.
160  */
161 void
162 pg_fe_scram_exchange(void *opaq, char *input, int inputlen,
163 					 char **output, int *outputlen,
164 					 bool *done, bool *success)
165 {
166 	fe_scram_state *state = (fe_scram_state *) opaq;
167 	PGconn	   *conn = state->conn;
168 
169 	*done = false;
170 	*success = false;
171 	*output = NULL;
172 	*outputlen = 0;
173 
174 	/*
175 	 * Check that the input length agrees with the string length of the input.
176 	 * We can ignore inputlen after this.
177 	 */
178 	if (state->state != FE_SCRAM_INIT)
179 	{
180 		if (inputlen == 0)
181 		{
182 			printfPQExpBuffer(&conn->errorMessage,
183 							  libpq_gettext("malformed SCRAM message (empty message)\n"));
184 			goto error;
185 		}
186 		if (inputlen != strlen(input))
187 		{
188 			printfPQExpBuffer(&conn->errorMessage,
189 							  libpq_gettext("malformed SCRAM message (length mismatch)\n"));
190 			goto error;
191 		}
192 	}
193 
194 	switch (state->state)
195 	{
196 		case FE_SCRAM_INIT:
197 			/* Begin the SCRAM handshake, by sending client nonce */
198 			*output = build_client_first_message(state);
199 			if (*output == NULL)
200 				goto error;
201 
202 			*outputlen = strlen(*output);
203 			*done = false;
204 			state->state = FE_SCRAM_NONCE_SENT;
205 			break;
206 
207 		case FE_SCRAM_NONCE_SENT:
208 			/* Receive salt and server nonce, send response. */
209 			if (!read_server_first_message(state, input))
210 				goto error;
211 
212 			*output = build_client_final_message(state);
213 			if (*output == NULL)
214 				goto error;
215 
216 			*outputlen = strlen(*output);
217 			*done = false;
218 			state->state = FE_SCRAM_PROOF_SENT;
219 			break;
220 
221 		case FE_SCRAM_PROOF_SENT:
222 			/* Receive server signature */
223 			if (!read_server_final_message(state, input))
224 				goto error;
225 
226 			/*
227 			 * Verify server signature, to make sure we're talking to the
228 			 * genuine server.  XXX: A fake server could simply not require
229 			 * authentication, though.  There is currently no option in libpq
230 			 * to reject a connection, if SCRAM authentication did not happen.
231 			 */
232 			if (verify_server_signature(state))
233 				*success = true;
234 			else
235 			{
236 				*success = false;
237 				printfPQExpBuffer(&conn->errorMessage,
238 								  libpq_gettext("incorrect server signature\n"));
239 			}
240 			*done = true;
241 			state->state = FE_SCRAM_FINISHED;
242 			break;
243 
244 		default:
245 			/* shouldn't happen */
246 			printfPQExpBuffer(&conn->errorMessage,
247 							  libpq_gettext("invalid SCRAM exchange state\n"));
248 			goto error;
249 	}
250 	return;
251 
252 error:
253 	*done = true;
254 	*success = false;
255 	return;
256 }
257 
258 /*
259  * Read value for an attribute part of a SCRAM message.
260  */
261 static char *
262 read_attr_value(char **input, char attr, PQExpBuffer errorMessage)
263 {
264 	char	   *begin = *input;
265 	char	   *end;
266 
267 	if (*begin != attr)
268 	{
269 		printfPQExpBuffer(errorMessage,
270 						  libpq_gettext("malformed SCRAM message (attribute \"%c\" expected)\n"),
271 						  attr);
272 		return NULL;
273 	}
274 	begin++;
275 
276 	if (*begin != '=')
277 	{
278 		printfPQExpBuffer(errorMessage,
279 						  libpq_gettext("malformed SCRAM message (expected character \"=\" for attribute \"%c\")\n"),
280 						  attr);
281 		return NULL;
282 	}
283 	begin++;
284 
285 	end = begin;
286 	while (*end && *end != ',')
287 		end++;
288 
289 	if (*end)
290 	{
291 		*end = '\0';
292 		*input = end + 1;
293 	}
294 	else
295 		*input = end;
296 
297 	return begin;
298 }
299 
300 /*
301  * Build the first exchange message sent by the client.
302  */
303 static char *
304 build_client_first_message(fe_scram_state *state)
305 {
306 	PGconn	   *conn = state->conn;
307 	char		raw_nonce[SCRAM_RAW_NONCE_LEN + 1];
308 	char	   *result;
309 	int			channel_info_len;
310 	int			encoded_len;
311 	PQExpBufferData buf;
312 
313 	/*
314 	 * Generate a "raw" nonce.  This is converted to ASCII-printable form by
315 	 * base64-encoding it.
316 	 */
317 	if (!pg_strong_random(raw_nonce, SCRAM_RAW_NONCE_LEN))
318 	{
319 		printfPQExpBuffer(&conn->errorMessage,
320 						  libpq_gettext("could not generate nonce\n"));
321 		return NULL;
322 	}
323 
324 	state->client_nonce = malloc(pg_b64_enc_len(SCRAM_RAW_NONCE_LEN) + 1);
325 	if (state->client_nonce == NULL)
326 	{
327 		printfPQExpBuffer(&conn->errorMessage,
328 						  libpq_gettext("out of memory\n"));
329 		return NULL;
330 	}
331 	encoded_len = pg_b64_encode(raw_nonce, SCRAM_RAW_NONCE_LEN, state->client_nonce);
332 	state->client_nonce[encoded_len] = '\0';
333 
334 	/*
335 	 * Generate message.  The username is left empty as the backend uses the
336 	 * value provided by the startup packet.  Also, as this username is not
337 	 * prepared with SASLprep, the message parsing would fail if it includes
338 	 * '=' or ',' characters.
339 	 */
340 
341 	initPQExpBuffer(&buf);
342 
343 	/*
344 	 * First build the gs2-header with channel binding information.
345 	 */
346 	if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
347 	{
348 		Assert(conn->ssl_in_use);
349 		appendPQExpBuffer(&buf, "p=tls-server-end-point");
350 	}
351 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
352 	else if (conn->ssl_in_use)
353 	{
354 		/*
355 		 * Client supports channel binding, but thinks the server does not.
356 		 */
357 		appendPQExpBuffer(&buf, "y");
358 	}
359 #endif
360 	else
361 	{
362 		/*
363 		 * Client does not support channel binding.
364 		 */
365 		appendPQExpBuffer(&buf, "n");
366 	}
367 
368 	if (PQExpBufferDataBroken(buf))
369 		goto oom_error;
370 
371 	channel_info_len = buf.len;
372 
373 	appendPQExpBuffer(&buf, ",,n=,r=%s", state->client_nonce);
374 	if (PQExpBufferDataBroken(buf))
375 		goto oom_error;
376 
377 	/*
378 	 * The first message content needs to be saved without channel binding
379 	 * information.
380 	 */
381 	state->client_first_message_bare = strdup(buf.data + channel_info_len + 2);
382 	if (!state->client_first_message_bare)
383 		goto oom_error;
384 
385 	result = strdup(buf.data);
386 	if (result == NULL)
387 		goto oom_error;
388 
389 	termPQExpBuffer(&buf);
390 	return result;
391 
392 oom_error:
393 	termPQExpBuffer(&buf);
394 	printfPQExpBuffer(&conn->errorMessage,
395 					  libpq_gettext("out of memory\n"));
396 	return NULL;
397 }
398 
399 /*
400  * Build the final exchange message sent from the client.
401  */
402 static char *
403 build_client_final_message(fe_scram_state *state)
404 {
405 	PQExpBufferData buf;
406 	PGconn	   *conn = state->conn;
407 	uint8		client_proof[SCRAM_KEY_LEN];
408 	char	   *result;
409 
410 	initPQExpBuffer(&buf);
411 
412 	/*
413 	 * Construct client-final-message-without-proof.  We need to remember it
414 	 * for verifying the server proof in the final step of authentication.
415 	 *
416 	 * The channel binding flag handling (p/y/n) must be consistent with
417 	 * build_client_first_message(), because the server will check that it's
418 	 * the same flag both times.
419 	 */
420 	if (strcmp(state->sasl_mechanism, SCRAM_SHA_256_PLUS_NAME) == 0)
421 	{
422 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
423 		char	   *cbind_data = NULL;
424 		size_t		cbind_data_len = 0;
425 		size_t		cbind_header_len;
426 		char	   *cbind_input;
427 		size_t		cbind_input_len;
428 
429 		/* Fetch hash data of server's SSL certificate */
430 		cbind_data =
431 			pgtls_get_peer_certificate_hash(state->conn,
432 											&cbind_data_len);
433 		if (cbind_data == NULL)
434 		{
435 			/* error message is already set on error */
436 			termPQExpBuffer(&buf);
437 			return NULL;
438 		}
439 
440 		appendPQExpBuffer(&buf, "c=");
441 
442 		/* p=type,, */
443 		cbind_header_len = strlen("p=tls-server-end-point,,");
444 		cbind_input_len = cbind_header_len + cbind_data_len;
445 		cbind_input = malloc(cbind_input_len);
446 		if (!cbind_input)
447 		{
448 			free(cbind_data);
449 			goto oom_error;
450 		}
451 		memcpy(cbind_input, "p=tls-server-end-point,,", cbind_header_len);
452 		memcpy(cbind_input + cbind_header_len, cbind_data, cbind_data_len);
453 
454 		if (!enlargePQExpBuffer(&buf, pg_b64_enc_len(cbind_input_len)))
455 		{
456 			free(cbind_data);
457 			free(cbind_input);
458 			goto oom_error;
459 		}
460 		buf.len += pg_b64_encode(cbind_input, cbind_input_len, buf.data + buf.len);
461 		buf.data[buf.len] = '\0';
462 
463 		free(cbind_data);
464 		free(cbind_input);
465 #else
466 		/*
467 		 * Chose channel binding, but the SSL library doesn't support it.
468 		 * Shouldn't happen.
469 		 */
470 		termPQExpBuffer(&buf);
471 		printfPQExpBuffer(&conn->errorMessage,
472 						  "channel binding not supported by this build\n");
473 		return NULL;
474 #endif							/* HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH */
475 	}
476 #ifdef HAVE_PGTLS_GET_PEER_CERTIFICATE_HASH
477 	else if (conn->ssl_in_use)
478 		appendPQExpBuffer(&buf, "c=eSws");	/* base64 of "y,," */
479 #endif
480 	else
481 		appendPQExpBuffer(&buf, "c=biws");	/* base64 of "n,," */
482 
483 	if (PQExpBufferDataBroken(buf))
484 		goto oom_error;
485 
486 	appendPQExpBuffer(&buf, ",r=%s", state->nonce);
487 	if (PQExpBufferDataBroken(buf))
488 		goto oom_error;
489 
490 	state->client_final_message_without_proof = strdup(buf.data);
491 	if (state->client_final_message_without_proof == NULL)
492 		goto oom_error;
493 
494 	/* Append proof to it, to form client-final-message. */
495 	calculate_client_proof(state,
496 						   state->client_final_message_without_proof,
497 						   client_proof);
498 
499 	appendPQExpBuffer(&buf, ",p=");
500 	if (!enlargePQExpBuffer(&buf, pg_b64_enc_len(SCRAM_KEY_LEN)))
501 		goto oom_error;
502 	buf.len += pg_b64_encode((char *) client_proof,
503 							 SCRAM_KEY_LEN,
504 							 buf.data + buf.len);
505 	buf.data[buf.len] = '\0';
506 
507 	result = strdup(buf.data);
508 	if (result == NULL)
509 		goto oom_error;
510 
511 	termPQExpBuffer(&buf);
512 	return result;
513 
514 oom_error:
515 	termPQExpBuffer(&buf);
516 	printfPQExpBuffer(&conn->errorMessage,
517 					  libpq_gettext("out of memory\n"));
518 	return NULL;
519 }
520 
521 /*
522  * Read the first exchange message coming from the server.
523  */
524 static bool
525 read_server_first_message(fe_scram_state *state, char *input)
526 {
527 	PGconn	   *conn = state->conn;
528 	char	   *iterations_str;
529 	char	   *endptr;
530 	char	   *encoded_salt;
531 	char	   *nonce;
532 
533 	state->server_first_message = strdup(input);
534 	if (state->server_first_message == NULL)
535 	{
536 		printfPQExpBuffer(&conn->errorMessage,
537 						  libpq_gettext("out of memory\n"));
538 		return false;
539 	}
540 
541 	/* parse the message */
542 	nonce = read_attr_value(&input, 'r',
543 							&conn->errorMessage);
544 	if (nonce == NULL)
545 	{
546 		/* read_attr_value() has generated an error string */
547 		return false;
548 	}
549 
550 	/* Verify immediately that the server used our part of the nonce */
551 	if (strlen(nonce) < strlen(state->client_nonce) ||
552 		memcmp(nonce, state->client_nonce, strlen(state->client_nonce)) != 0)
553 	{
554 		printfPQExpBuffer(&conn->errorMessage,
555 						  libpq_gettext("invalid SCRAM response (nonce mismatch)\n"));
556 		return false;
557 	}
558 
559 	state->nonce = strdup(nonce);
560 	if (state->nonce == NULL)
561 	{
562 		printfPQExpBuffer(&conn->errorMessage,
563 						  libpq_gettext("out of memory\n"));
564 		return false;
565 	}
566 
567 	encoded_salt = read_attr_value(&input, 's', &conn->errorMessage);
568 	if (encoded_salt == NULL)
569 	{
570 		/* read_attr_value() has generated an error string */
571 		return false;
572 	}
573 	state->salt = malloc(pg_b64_dec_len(strlen(encoded_salt)));
574 	if (state->salt == NULL)
575 	{
576 		printfPQExpBuffer(&conn->errorMessage,
577 						  libpq_gettext("out of memory\n"));
578 		return false;
579 	}
580 	state->saltlen = pg_b64_decode(encoded_salt,
581 								   strlen(encoded_salt),
582 								   state->salt);
583 	if (state->saltlen < 0)
584 	{
585 		printfPQExpBuffer(&conn->errorMessage,
586 						  libpq_gettext("malformed SCRAM message (invalid salt)\n"));
587 		return false;
588 	}
589 
590 	iterations_str = read_attr_value(&input, 'i', &conn->errorMessage);
591 	if (iterations_str == NULL)
592 	{
593 		/* read_attr_value() has generated an error string */
594 		return false;
595 	}
596 	state->iterations = strtol(iterations_str, &endptr, 10);
597 	if (*endptr != '\0' || state->iterations < 1)
598 	{
599 		printfPQExpBuffer(&conn->errorMessage,
600 						  libpq_gettext("malformed SCRAM message (invalid iteration count)\n"));
601 		return false;
602 	}
603 
604 	if (*input != '\0')
605 		printfPQExpBuffer(&conn->errorMessage,
606 						  libpq_gettext("malformed SCRAM message (garbage at end of server-first-message)\n"));
607 
608 	return true;
609 }
610 
611 /*
612  * Read the final exchange message coming from the server.
613  */
614 static bool
615 read_server_final_message(fe_scram_state *state, char *input)
616 {
617 	PGconn	   *conn = state->conn;
618 	char	   *encoded_server_signature;
619 	char	   *decoded_server_signature;
620 	int			server_signature_len;
621 
622 	state->server_final_message = strdup(input);
623 	if (!state->server_final_message)
624 	{
625 		printfPQExpBuffer(&conn->errorMessage,
626 						  libpq_gettext("out of memory\n"));
627 		return false;
628 	}
629 
630 	/* Check for error result. */
631 	if (*input == 'e')
632 	{
633 		char	   *errmsg = read_attr_value(&input, 'e',
634 											 &conn->errorMessage);
635 
636 		printfPQExpBuffer(&conn->errorMessage,
637 						  libpq_gettext("error received from server in SCRAM exchange: %s\n"),
638 						  errmsg);
639 		return false;
640 	}
641 
642 	/* Parse the message. */
643 	encoded_server_signature = read_attr_value(&input, 'v',
644 											   &conn->errorMessage);
645 	if (encoded_server_signature == NULL)
646 	{
647 		/* read_attr_value() has generated an error message */
648 		return false;
649 	}
650 
651 	if (*input != '\0')
652 		printfPQExpBuffer(&conn->errorMessage,
653 						  libpq_gettext("malformed SCRAM message (garbage at end of server-final-message)\n"));
654 
655 	server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
656 	decoded_server_signature = malloc(server_signature_len);
657 	if (!decoded_server_signature)
658 	{
659 		printfPQExpBuffer(&conn->errorMessage,
660 						  libpq_gettext("out of memory\n"));
661 		return false;
662 	}
663 
664 	server_signature_len = pg_b64_decode(encoded_server_signature,
665 										 strlen(encoded_server_signature),
666 										 decoded_server_signature);
667 	if (server_signature_len != SCRAM_KEY_LEN)
668 	{
669 		free(decoded_server_signature);
670 		printfPQExpBuffer(&conn->errorMessage,
671 						  libpq_gettext("malformed SCRAM message (invalid server signature)\n"));
672 		return false;
673 	}
674 	memcpy(state->ServerSignature, decoded_server_signature, SCRAM_KEY_LEN);
675 	free(decoded_server_signature);
676 
677 	return true;
678 }
679 
680 /*
681  * Calculate the client proof, part of the final exchange message sent
682  * by the client.
683  */
684 static void
685 calculate_client_proof(fe_scram_state *state,
686 					   const char *client_final_message_without_proof,
687 					   uint8 *result)
688 {
689 	uint8		StoredKey[SCRAM_KEY_LEN];
690 	uint8		ClientKey[SCRAM_KEY_LEN];
691 	uint8		ClientSignature[SCRAM_KEY_LEN];
692 	int			i;
693 	scram_HMAC_ctx ctx;
694 
695 	/*
696 	 * Calculate SaltedPassword, and store it in 'state' so that we can reuse
697 	 * it later in verify_server_signature.
698 	 */
699 	scram_SaltedPassword(state->password, state->salt, state->saltlen,
700 						 state->iterations, state->SaltedPassword);
701 
702 	scram_ClientKey(state->SaltedPassword, ClientKey);
703 	scram_H(ClientKey, SCRAM_KEY_LEN, StoredKey);
704 
705 	scram_HMAC_init(&ctx, StoredKey, SCRAM_KEY_LEN);
706 	scram_HMAC_update(&ctx,
707 					  state->client_first_message_bare,
708 					  strlen(state->client_first_message_bare));
709 	scram_HMAC_update(&ctx, ",", 1);
710 	scram_HMAC_update(&ctx,
711 					  state->server_first_message,
712 					  strlen(state->server_first_message));
713 	scram_HMAC_update(&ctx, ",", 1);
714 	scram_HMAC_update(&ctx,
715 					  client_final_message_without_proof,
716 					  strlen(client_final_message_without_proof));
717 	scram_HMAC_final(ClientSignature, &ctx);
718 
719 	for (i = 0; i < SCRAM_KEY_LEN; i++)
720 		result[i] = ClientKey[i] ^ ClientSignature[i];
721 }
722 
723 /*
724  * Validate the server signature, received as part of the final exchange
725  * message received from the server.
726  */
727 static bool
728 verify_server_signature(fe_scram_state *state)
729 {
730 	uint8		expected_ServerSignature[SCRAM_KEY_LEN];
731 	uint8		ServerKey[SCRAM_KEY_LEN];
732 	scram_HMAC_ctx ctx;
733 
734 	scram_ServerKey(state->SaltedPassword, ServerKey);
735 
736 	/* calculate ServerSignature */
737 	scram_HMAC_init(&ctx, ServerKey, SCRAM_KEY_LEN);
738 	scram_HMAC_update(&ctx,
739 					  state->client_first_message_bare,
740 					  strlen(state->client_first_message_bare));
741 	scram_HMAC_update(&ctx, ",", 1);
742 	scram_HMAC_update(&ctx,
743 					  state->server_first_message,
744 					  strlen(state->server_first_message));
745 	scram_HMAC_update(&ctx, ",", 1);
746 	scram_HMAC_update(&ctx,
747 					  state->client_final_message_without_proof,
748 					  strlen(state->client_final_message_without_proof));
749 	scram_HMAC_final(expected_ServerSignature, &ctx);
750 
751 	if (memcmp(expected_ServerSignature, state->ServerSignature, SCRAM_KEY_LEN) != 0)
752 		return false;
753 
754 	return true;
755 }
756 
757 /*
758  * Build a new SCRAM verifier.
759  */
760 char *
761 pg_fe_scram_build_verifier(const char *password)
762 {
763 	char	   *prep_password;
764 	pg_saslprep_rc rc;
765 	char		saltbuf[SCRAM_DEFAULT_SALT_LEN];
766 	char	   *result;
767 
768 	/*
769 	 * Normalize the password with SASLprep.  If that doesn't work, because
770 	 * the password isn't valid UTF-8 or contains prohibited characters, just
771 	 * proceed with the original password.  (See comments at top of file.)
772 	 */
773 	rc = pg_saslprep(password, &prep_password);
774 	if (rc == SASLPREP_OOM)
775 		return NULL;
776 	if (rc == SASLPREP_SUCCESS)
777 		password = (const char *) prep_password;
778 
779 	/* Generate a random salt */
780 	if (!pg_strong_random(saltbuf, SCRAM_DEFAULT_SALT_LEN))
781 	{
782 		if (prep_password)
783 			free(prep_password);
784 		return NULL;
785 	}
786 
787 	result = scram_build_verifier(saltbuf, SCRAM_DEFAULT_SALT_LEN,
788 								  SCRAM_DEFAULT_ITERATIONS, password);
789 
790 	if (prep_password)
791 		free(prep_password);
792 
793 	return result;
794 }
795