aboutsummaryrefslogtreecommitdiff
path: root/src/common/scram-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/scram-common.c')
-rw-r--r--src/common/scram-common.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/common/scram-common.c b/src/common/scram-common.c
index a8ea44944c4..77b54c8a5e7 100644
--- a/src/common/scram-common.c
+++ b/src/common/scram-common.c
@@ -23,6 +23,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
+#include "common/base64.h"
#include "common/scram-common.h"
#define HMAC_IPAD 0x36
@@ -180,3 +181,66 @@ scram_ServerKey(const uint8 *salted_password, uint8 *result)
scram_HMAC_update(&ctx, "Server Key", strlen("Server Key"));
scram_HMAC_final(result, &ctx);
}
+
+
+/*
+ * Construct a verifier string for SCRAM, stored in pg_authid.rolpassword.
+ *
+ * The password should already have been processed with SASLprep, if necessary!
+ *
+ * If iterations is 0, default number of iterations is used. The result is
+ * palloc'd or malloc'd, so caller is responsible for freeing it.
+ */
+char *
+scram_build_verifier(const char *salt, int saltlen, int iterations,
+ const char *password)
+{
+ uint8 salted_password[SCRAM_KEY_LEN];
+ uint8 stored_key[SCRAM_KEY_LEN];
+ uint8 server_key[SCRAM_KEY_LEN];
+ char *result;
+ char *p;
+ int maxlen;
+
+ if (iterations <= 0)
+ iterations = SCRAM_DEFAULT_ITERATIONS;
+
+ /* Calculate StoredKey and ServerKey */
+ scram_SaltedPassword(password, salt, saltlen, iterations,
+ salted_password);
+ scram_ClientKey(salted_password, stored_key);
+ scram_H(stored_key, SCRAM_KEY_LEN, stored_key);
+
+ scram_ServerKey(salted_password, server_key);
+
+ /*
+ * The format is:
+ * SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
+ */
+ maxlen = strlen("SCRAM-SHA-256") + 1
+ + 10 + 1 /* iteration count */
+ + pg_b64_enc_len(saltlen) + 1 /* Base64-encoded salt */
+ + pg_b64_enc_len(SCRAM_KEY_LEN) + 1 /* Base64-encoded StoredKey */
+ + pg_b64_enc_len(SCRAM_KEY_LEN) + 1; /* Base64-encoded ServerKey */
+
+#ifdef FRONTEND
+ result = malloc(maxlen);
+ if (!result)
+ return NULL;
+#else
+ result = palloc(maxlen);
+#endif
+
+ p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
+
+ p += pg_b64_encode(salt, saltlen, p);
+ *(p++) = '$';
+ p += pg_b64_encode((char *) stored_key, SCRAM_KEY_LEN, p);
+ *(p++) = ':';
+ p += pg_b64_encode((char *) server_key, SCRAM_KEY_LEN, p);
+ *(p++) = '\0';
+
+ Assert(p - result <= maxlen);
+
+ return result;
+}