re-factor SCRAM to be independent of the hash

This commit is contained in:
Steffen Jaeckel
2019-10-08 10:22:34 +02:00
committed by Dmitry Podgorny
parent 2ca2fcfedd
commit fc064bc883
7 changed files with 158 additions and 107 deletions

View File

@@ -19,6 +19,7 @@
#include <assert.h>
#include <string.h>
#include "common.h"
#include "sha1.h"
#include "ostypes.h"
@@ -29,25 +30,39 @@
static const uint8_t ipad = 0x36;
static const uint8_t opad = 0x5C;
static void crypto_HMAC_SHA1(const uint8_t *key,
size_t key_len,
const uint8_t *text,
size_t len,
uint8_t *digest)
const struct hash_alg scram_sha1 = {
"SCRAM-SHA-1",
SASL_MASK_SCRAMSHA1,
SHA1_DIGEST_SIZE,
(void (*)(const uint8_t *, size_t, uint8_t *))crypto_SHA1,
(void (*)(void *))crypto_SHA1_Init,
(void (*)(void *, const uint8_t *, size_t))crypto_SHA1_Update,
(void (*)(void *, uint8_t *))crypto_SHA1_Final};
union common_hash_ctx {
SHA1_CTX sha1;
};
static void crypto_HMAC(const struct hash_alg *alg,
const uint8_t *key,
size_t key_len,
const uint8_t *text,
size_t len,
uint8_t *digest)
{
uint8_t key_pad[HMAC_BLOCK_SIZE];
uint8_t key_ipad[HMAC_BLOCK_SIZE];
uint8_t key_opad[HMAC_BLOCK_SIZE];
uint8_t sha_digest[SHA1_DIGEST_SIZE];
int i;
SHA1_CTX ctx;
union common_hash_ctx ctx;
memset(key_pad, 0, sizeof(key_pad));
if (key_len <= HMAC_BLOCK_SIZE) {
memcpy(key_pad, key, key_len);
} else {
/* according to RFC2104 */
crypto_SHA1(key, key_len, key_pad);
alg->hash(key, key_len, key_pad);
}
for (i = 0; i < HMAC_BLOCK_SIZE; i++) {
@@ -55,25 +70,26 @@ static void crypto_HMAC_SHA1(const uint8_t *key,
key_opad[i] = key_pad[i] ^ opad;
}
crypto_SHA1_Init(&ctx);
crypto_SHA1_Update(&ctx, key_ipad, HMAC_BLOCK_SIZE);
crypto_SHA1_Update(&ctx, text, len);
crypto_SHA1_Final(&ctx, sha_digest);
alg->init((void *)&ctx);
alg->update((void *)&ctx, key_ipad, HMAC_BLOCK_SIZE);
alg->update((void *)&ctx, text, len);
alg->final((void *)&ctx, sha_digest);
crypto_SHA1_Init(&ctx);
crypto_SHA1_Update(&ctx, key_opad, HMAC_BLOCK_SIZE);
crypto_SHA1_Update(&ctx, sha_digest, SHA1_DIGEST_SIZE);
crypto_SHA1_Final(&ctx, digest);
alg->init((void *)&ctx);
alg->update((void *)&ctx, key_opad, HMAC_BLOCK_SIZE);
alg->update((void *)&ctx, sha_digest, alg->digest_size);
alg->final((void *)&ctx, digest);
}
static void SCRAM_SHA1_Hi(const uint8_t *text,
size_t len,
const uint8_t *salt,
size_t salt_len,
uint32_t i,
uint8_t *digest)
static void SCRAM_Hi(const struct hash_alg *alg,
const uint8_t *text,
size_t len,
const uint8_t *salt,
size_t salt_len,
uint32_t i,
uint8_t *digest)
{
int k;
size_t k;
uint32_t j;
uint8_t tmp[128];
@@ -82,7 +98,7 @@ static void SCRAM_SHA1_Hi(const uint8_t *text,
/* assume salt + INT(1) isn't longer than sizeof(tmp) */
assert(salt_len <= sizeof(tmp) - sizeof(int1));
memset(digest, 0, SHA1_DIGEST_SIZE);
memset(digest, 0, alg->digest_size);
if (i == 0) {
return;
}
@@ -91,50 +107,53 @@ static void SCRAM_SHA1_Hi(const uint8_t *text,
memcpy(&tmp[salt_len], int1, sizeof(int1));
/* 'text' for Hi is a 'key' for HMAC */
crypto_HMAC_SHA1(text, len, tmp, salt_len + sizeof(int1), digest);
memcpy(tmp, digest, SHA1_DIGEST_SIZE);
crypto_HMAC(alg, text, len, tmp, salt_len + sizeof(int1), digest);
memcpy(tmp, digest, alg->digest_size);
for (j = 1; j < i; j++) {
crypto_HMAC_SHA1(text, len, tmp, SHA1_DIGEST_SIZE, tmp);
for (k = 0; k < SHA1_DIGEST_SIZE; k++) {
crypto_HMAC(alg, text, len, tmp, alg->digest_size, tmp);
for (k = 0; k < alg->digest_size; k++) {
digest[k] ^= tmp[k];
}
}
}
void SCRAM_SHA1_ClientKey(const uint8_t *password,
size_t len,
const uint8_t *salt,
size_t salt_len,
uint32_t i,
uint8_t *key)
void SCRAM_ClientKey(const struct hash_alg *alg,
const uint8_t *password,
size_t len,
const uint8_t *salt,
size_t salt_len,
uint32_t i,
uint8_t *key)
{
uint8_t salted[SHA1_DIGEST_SIZE];
/* XXX: Normalize(password) is omitted */
SCRAM_SHA1_Hi(password, len, salt, salt_len, i, salted);
crypto_HMAC_SHA1(salted, SHA1_DIGEST_SIZE, (uint8_t *)"Client Key",
strlen("Client Key"), key);
SCRAM_Hi(alg, password, len, salt, salt_len, i, salted);
crypto_HMAC(alg, salted, alg->digest_size, (uint8_t *)"Client Key",
strlen("Client Key"), key);
}
void SCRAM_SHA1_ClientSignature(const uint8_t *ClientKey,
const uint8_t *AuthMessage,
size_t len,
uint8_t *sign)
void SCRAM_ClientSignature(const struct hash_alg *alg,
const uint8_t *ClientKey,
const uint8_t *AuthMessage,
size_t len,
uint8_t *sign)
{
uint8_t stored[SHA1_DIGEST_SIZE];
crypto_SHA1(ClientKey, SHA1_DIGEST_SIZE, stored);
crypto_HMAC_SHA1(stored, SHA1_DIGEST_SIZE, AuthMessage, len, sign);
alg->hash(ClientKey, alg->digest_size, stored);
crypto_HMAC(alg, stored, alg->digest_size, AuthMessage, len, sign);
}
void SCRAM_SHA1_ClientProof(const uint8_t *ClientKey,
const uint8_t *ClientSignature,
uint8_t *proof)
void SCRAM_ClientProof(const struct hash_alg *alg,
const uint8_t *ClientKey,
const uint8_t *ClientSignature,
uint8_t *proof)
{
int i;
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
size_t i;
for (i = 0; i < alg->digest_size; i++) {
proof[i] = ClientKey[i] ^ ClientSignature[i];
}
}