Example #1
0
/*
 * Calculate HMAC per RFC2104.
 *
 * The hash function used is SHA-256.
 */
void
scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen)
{
	uint8		k_ipad[SHA256_HMAC_B];
	int			i;
	uint8		keybuf[SCRAM_KEY_LEN];

	/*
	 * If the key is longer than the block size (64 bytes for SHA-256), pass
	 * it through SHA-256 once to shrink it down.
	 */
	if (keylen > SHA256_HMAC_B)
	{
		pg_sha256_ctx sha256_ctx;

		pg_sha256_init(&sha256_ctx);
		pg_sha256_update(&sha256_ctx, key, keylen);
		pg_sha256_final(&sha256_ctx, keybuf);
		key = keybuf;
		keylen = SCRAM_KEY_LEN;
	}

	memset(k_ipad, HMAC_IPAD, SHA256_HMAC_B);
	memset(ctx->k_opad, HMAC_OPAD, SHA256_HMAC_B);

	for (i = 0; i < keylen; i++)
	{
		k_ipad[i] ^= key[i];
		ctx->k_opad[i] ^= key[i];
	}

	/* tmp = H(K XOR ipad, text) */
	pg_sha256_init(&ctx->sha256ctx);
	pg_sha256_update(&ctx->sha256ctx, k_ipad, SHA256_HMAC_B);
}
Example #2
0
/*
 * Calculate SHA-256 hash for a NULL-terminated string. (The NULL terminator is
 * not included in the hash).
 */
void
scram_H(const uint8 *input, int len, uint8 *result)
{
	pg_sha256_ctx ctx;

	pg_sha256_init(&ctx);
	pg_sha256_update(&ctx, input, len);
	pg_sha256_final(&ctx, result);
}
Example #3
0
/*
 * Finalize HMAC calculation.
 * The hash function used is SHA-256.
 */
void
scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx)
{
	uint8		h[SCRAM_KEY_LEN];

	pg_sha256_final(&ctx->sha256ctx, h);

	/* H(K XOR opad, tmp) */
	pg_sha256_init(&ctx->sha256ctx);
	pg_sha256_update(&ctx->sha256ctx, ctx->k_opad, SHA256_HMAC_B);
	pg_sha256_update(&ctx->sha256ctx, h, SCRAM_KEY_LEN);
	pg_sha256_final(&ctx->sha256ctx, result);
}
Example #4
0
/*
 * Determinisitcally generate salt for mock authentication, using a SHA256
 * hash based on the username and a cluster-level secret key.  Returns a
 * pointer to a static buffer of size SCRAM_DEFAULT_SALT_LEN.
 */
static char *
scram_mock_salt(const char *username)
{
	pg_sha256_ctx ctx;
	static uint8 sha_digest[PG_SHA256_DIGEST_LENGTH];
	char	   *mock_auth_nonce = GetMockAuthenticationNonce();

	/*
	 * Generate salt using a SHA256 hash of the username and the cluster's
	 * mock authentication nonce.  (This works as long as the salt length is
	 * not larger the SHA256 digest length. If the salt is smaller, the caller
	 * will just ignore the extra data.)
	 */
	StaticAssertStmt(PG_SHA256_DIGEST_LENGTH >= SCRAM_DEFAULT_SALT_LEN,
					 "salt length greater than SHA256 digest length");

	pg_sha256_init(&ctx);
	pg_sha256_update(&ctx, (uint8 *) username, strlen(username));
	pg_sha256_update(&ctx, (uint8 *) mock_auth_nonce, MOCK_AUTH_NONCE_LEN);
	pg_sha256_final(&ctx, sha_digest);

	return (char *) sha_digest;
}