re-factor SCRAM to be independent of the hash
This commit is contained in:
committed by
Dmitry Podgorny
parent
2ca2fcfedd
commit
fc064bc883
60
src/auth.c
60
src/auth.c
@@ -85,7 +85,7 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t *const conn,
|
|||||||
static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
||||||
xmpp_stanza_t *const stanza,
|
xmpp_stanza_t *const stanza,
|
||||||
void *const userdata);
|
void *const userdata);
|
||||||
static char *_make_scram_sha1_init_msg(xmpp_conn_t *const conn);
|
static char *_make_scram_init_msg(xmpp_conn_t *const conn);
|
||||||
|
|
||||||
static int _handle_missing_features_sasl(xmpp_conn_t *const conn,
|
static int _handle_missing_features_sasl(xmpp_conn_t *const conn,
|
||||||
void *const userdata);
|
void *const userdata);
|
||||||
@@ -430,6 +430,11 @@ static int _handle_digestmd5_rspauth(xmpp_conn_t *const conn,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct scram_user_data {
|
||||||
|
char *scram_init;
|
||||||
|
const struct hash_alg *alg;
|
||||||
|
};
|
||||||
|
|
||||||
/* handle the challenge phase of SCRAM-SHA-1 auth */
|
/* handle the challenge phase of SCRAM-SHA-1 auth */
|
||||||
static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
||||||
xmpp_stanza_t *const stanza,
|
xmpp_stanza_t *const stanza,
|
||||||
@@ -437,14 +442,16 @@ static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
|||||||
{
|
{
|
||||||
char *text;
|
char *text;
|
||||||
char *response;
|
char *response;
|
||||||
xmpp_stanza_t *auth, *authdata;
|
xmpp_stanza_t *auth;
|
||||||
|
xmpp_stanza_t *authdata;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
const char *scram_name;
|
||||||
char *challenge;
|
char *challenge;
|
||||||
char *scram_init = (char *)userdata;
|
struct scram_user_data *scram_ctx = (struct scram_user_data *)userdata;
|
||||||
|
|
||||||
name = xmpp_stanza_get_name(stanza);
|
name = xmpp_stanza_get_name(stanza);
|
||||||
xmpp_debug(conn->ctx, "xmpp",
|
xmpp_debug(conn->ctx, "xmpp", "handle %s (challenge) called for %s",
|
||||||
"handle SCRAM-SHA-1 (challenge) called for %s", name);
|
scram_ctx->alg->scram_name, name);
|
||||||
|
|
||||||
if (strcmp(name, "challenge") == 0) {
|
if (strcmp(name, "challenge") == 0) {
|
||||||
text = xmpp_stanza_get_text(stanza);
|
text = xmpp_stanza_get_text(stanza);
|
||||||
@@ -456,8 +463,8 @@ static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
|||||||
if (!challenge)
|
if (!challenge)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
response = sasl_scram_sha1(conn->ctx, challenge, scram_init, conn->jid,
|
response = sasl_scram(conn->ctx, scram_ctx->alg, challenge,
|
||||||
conn->pass);
|
scram_ctx->scram_init, conn->jid, conn->pass);
|
||||||
xmpp_free(conn->ctx, challenge);
|
xmpp_free(conn->ctx, challenge);
|
||||||
if (!response)
|
if (!response)
|
||||||
goto err;
|
goto err;
|
||||||
@@ -481,8 +488,10 @@ static int _handle_scram_sha1_challenge(xmpp_conn_t *const conn,
|
|||||||
xmpp_stanza_release(auth);
|
xmpp_stanza_release(auth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
xmpp_free(conn->ctx, scram_init);
|
scram_name = scram_ctx->alg->scram_name;
|
||||||
return _handle_sasl_result(conn, stanza, "SCRAM-SHA-1");
|
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||||
|
xmpp_free(conn->ctx, scram_ctx);
|
||||||
|
return _handle_sasl_result(conn, stanza, (void *)scram_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -492,12 +501,13 @@ err_release_auth:
|
|||||||
err_free_response:
|
err_free_response:
|
||||||
xmpp_free(conn->ctx, response);
|
xmpp_free(conn->ctx, response);
|
||||||
err:
|
err:
|
||||||
xmpp_free(conn->ctx, scram_init);
|
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||||
|
xmpp_free(conn->ctx, scram_ctx);
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *_make_scram_sha1_init_msg(xmpp_conn_t *const conn)
|
static char *_make_scram_init_msg(xmpp_conn_t *const conn)
|
||||||
{
|
{
|
||||||
xmpp_ctx_t *ctx = conn->ctx;
|
xmpp_ctx_t *ctx = conn->ctx;
|
||||||
size_t message_len;
|
size_t message_len;
|
||||||
@@ -559,8 +569,8 @@ static void _auth(xmpp_conn_t *const conn)
|
|||||||
{
|
{
|
||||||
xmpp_stanza_t *auth;
|
xmpp_stanza_t *auth;
|
||||||
xmpp_stanza_t *authdata;
|
xmpp_stanza_t *authdata;
|
||||||
|
struct scram_user_data *scram_ctx;
|
||||||
char *authid;
|
char *authid;
|
||||||
char *scram_init;
|
|
||||||
char *str;
|
char *str;
|
||||||
int anonjid;
|
int anonjid;
|
||||||
|
|
||||||
@@ -632,25 +642,30 @@ static void _auth(xmpp_conn_t *const conn)
|
|||||||
xmpp_error(conn->ctx, "auth",
|
xmpp_error(conn->ctx, "auth",
|
||||||
"No node in JID, and SASL ANONYMOUS unsupported.");
|
"No node in JID, and SASL ANONYMOUS unsupported.");
|
||||||
xmpp_disconnect(conn);
|
xmpp_disconnect(conn);
|
||||||
} else if (conn->sasl_support & SASL_MASK_SCRAMSHA1) {
|
} else if (conn->sasl_support & SASL_MASK_SCRAM) {
|
||||||
auth = _make_sasl_auth(conn, "SCRAM-SHA-1");
|
scram_ctx = xmpp_alloc(conn->ctx, sizeof(*scram_ctx));
|
||||||
|
scram_ctx->alg = &scram_sha1;
|
||||||
|
auth = _make_sasl_auth(conn, scram_ctx->alg->scram_name);
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't free scram_init on success */
|
/* don't free scram_init on success */
|
||||||
scram_init = _make_scram_sha1_init_msg(conn);
|
scram_ctx->scram_init = _make_scram_init_msg(conn);
|
||||||
if (!scram_init) {
|
if (!scram_ctx->scram_init) {
|
||||||
|
xmpp_free(conn->ctx, scram_ctx);
|
||||||
xmpp_stanza_release(auth);
|
xmpp_stanza_release(auth);
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = xmpp_base64_encode(conn->ctx, (unsigned char *)scram_init,
|
str = xmpp_base64_encode(conn->ctx,
|
||||||
strlen(scram_init));
|
(unsigned char *)scram_ctx->scram_init,
|
||||||
|
strlen(scram_ctx->scram_init));
|
||||||
if (!str) {
|
if (!str) {
|
||||||
xmpp_free(conn->ctx, scram_init);
|
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||||
|
xmpp_free(conn->ctx, scram_ctx);
|
||||||
xmpp_stanza_release(auth);
|
xmpp_stanza_release(auth);
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return;
|
return;
|
||||||
@@ -659,7 +674,8 @@ static void _auth(xmpp_conn_t *const conn)
|
|||||||
authdata = xmpp_stanza_new(conn->ctx);
|
authdata = xmpp_stanza_new(conn->ctx);
|
||||||
if (!authdata) {
|
if (!authdata) {
|
||||||
xmpp_free(conn->ctx, str);
|
xmpp_free(conn->ctx, str);
|
||||||
xmpp_free(conn->ctx, scram_init);
|
xmpp_free(conn->ctx, scram_ctx->scram_init);
|
||||||
|
xmpp_free(conn->ctx, scram_ctx);
|
||||||
xmpp_stanza_release(auth);
|
xmpp_stanza_release(auth);
|
||||||
disconnect_mem_error(conn);
|
disconnect_mem_error(conn);
|
||||||
return;
|
return;
|
||||||
@@ -670,13 +686,13 @@ static void _auth(xmpp_conn_t *const conn)
|
|||||||
xmpp_stanza_release(authdata);
|
xmpp_stanza_release(authdata);
|
||||||
|
|
||||||
handler_add(conn, _handle_scram_sha1_challenge, XMPP_NS_SASL, NULL,
|
handler_add(conn, _handle_scram_sha1_challenge, XMPP_NS_SASL, NULL,
|
||||||
NULL, (void *)scram_init);
|
NULL, (void *)scram_ctx);
|
||||||
|
|
||||||
xmpp_send(conn, auth);
|
xmpp_send(conn, auth);
|
||||||
xmpp_stanza_release(auth);
|
xmpp_stanza_release(auth);
|
||||||
|
|
||||||
/* SASL SCRAM-SHA-1 was tried, unset flag */
|
/* SASL SCRAM-SHA-1 was tried, unset flag */
|
||||||
conn->sasl_support &= ~SASL_MASK_SCRAMSHA1;
|
conn->sasl_support &= ~scram_ctx->alg->mask;
|
||||||
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
} else if (conn->sasl_support & SASL_MASK_DIGESTMD5) {
|
||||||
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
auth = _make_sasl_auth(conn, "DIGEST-MD5");
|
||||||
if (!auth) {
|
if (!auth) {
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ struct _xmpp_handlist_t {
|
|||||||
#define SASL_MASK_ANONYMOUS (1 << 2)
|
#define SASL_MASK_ANONYMOUS (1 << 2)
|
||||||
#define SASL_MASK_SCRAMSHA1 (1 << 3)
|
#define SASL_MASK_SCRAMSHA1 (1 << 3)
|
||||||
|
|
||||||
|
#define SASL_MASK_SCRAM (SASL_MASK_SCRAMSHA1)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
XMPP_PORT_CLIENT = 5222,
|
XMPP_PORT_CLIENT = 5222,
|
||||||
XMPP_PORT_CLIENT_LEGACY_SSL = 5223,
|
XMPP_PORT_CLIENT_LEGACY_SSL = 5223,
|
||||||
|
|||||||
22
src/sasl.c
22
src/sasl.c
@@ -380,11 +380,12 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** generate auth response string for the SASL SCRAM-SHA-1 mechanism */
|
/** generate auth response string for the SASL SCRAM-SHA-1 mechanism */
|
||||||
char *sasl_scram_sha1(xmpp_ctx_t *ctx,
|
char *sasl_scram(xmpp_ctx_t *ctx,
|
||||||
const char *challenge,
|
const struct hash_alg *alg,
|
||||||
const char *first_bare,
|
const char *challenge,
|
||||||
const char *jid,
|
const char *first_bare,
|
||||||
const char *password)
|
const char *jid,
|
||||||
|
const char *password)
|
||||||
{
|
{
|
||||||
uint8_t key[SHA1_DIGEST_SIZE];
|
uint8_t key[SHA1_DIGEST_SIZE];
|
||||||
uint8_t sign[SHA1_DIGEST_SIZE];
|
uint8_t sign[SHA1_DIGEST_SIZE];
|
||||||
@@ -404,7 +405,6 @@ char *sasl_scram_sha1(xmpp_ctx_t *ctx,
|
|||||||
char *result = NULL;
|
char *result = NULL;
|
||||||
size_t response_len;
|
size_t response_len;
|
||||||
size_t auth_len;
|
size_t auth_len;
|
||||||
int j;
|
|
||||||
|
|
||||||
tmp = xmpp_strdup(ctx, challenge);
|
tmp = xmpp_strdup(ctx, challenge);
|
||||||
if (!tmp) {
|
if (!tmp) {
|
||||||
@@ -449,12 +449,10 @@ char *sasl_scram_sha1(xmpp_ctx_t *ctx,
|
|||||||
xmpp_snprintf(auth, auth_len, "%s,%s,%s", first_bare + 3, challenge,
|
xmpp_snprintf(auth, auth_len, "%s,%s,%s", first_bare + 3, challenge,
|
||||||
response);
|
response);
|
||||||
|
|
||||||
SCRAM_SHA1_ClientKey((uint8_t *)password, strlen(password), (uint8_t *)sval,
|
SCRAM_ClientKey(alg, (uint8_t *)password, strlen(password), (uint8_t *)sval,
|
||||||
sval_len, (uint32_t)ival, key);
|
sval_len, (uint32_t)ival, key);
|
||||||
SCRAM_SHA1_ClientSignature(key, (uint8_t *)auth, strlen(auth), sign);
|
SCRAM_ClientSignature(alg, key, (uint8_t *)auth, strlen(auth), sign);
|
||||||
for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
|
SCRAM_ClientProof(alg, sign, key, sign);
|
||||||
sign[j] ^= key[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
sign_b64 = xmpp_base64_encode(ctx, sign, sizeof(sign));
|
sign_b64 = xmpp_base64_encode(ctx, sign, sizeof(sign));
|
||||||
if (!sign_b64) {
|
if (!sign_b64) {
|
||||||
|
|||||||
12
src/sasl.h
12
src/sasl.h
@@ -17,6 +17,7 @@
|
|||||||
#define __LIBSTROPHE_SASL_H__
|
#define __LIBSTROPHE_SASL_H__
|
||||||
|
|
||||||
#include "strophe.h"
|
#include "strophe.h"
|
||||||
|
#include "scram.h"
|
||||||
|
|
||||||
/** low-level sasl routines */
|
/** low-level sasl routines */
|
||||||
|
|
||||||
@@ -25,10 +26,11 @@ char *sasl_digest_md5(xmpp_ctx_t *ctx,
|
|||||||
const char *challenge,
|
const char *challenge,
|
||||||
const char *jid,
|
const char *jid,
|
||||||
const char *password);
|
const char *password);
|
||||||
char *sasl_scram_sha1(xmpp_ctx_t *ctx,
|
char *sasl_scram(xmpp_ctx_t *ctx,
|
||||||
const char *challenge,
|
const struct hash_alg *alg,
|
||||||
const char *first_bare,
|
const char *challenge,
|
||||||
const char *jid,
|
const char *first_bare,
|
||||||
const char *password);
|
const char *jid,
|
||||||
|
const char *password);
|
||||||
|
|
||||||
#endif /* _LIBXMPP_SASL_H__ */
|
#endif /* _LIBXMPP_SASL_H__ */
|
||||||
|
|||||||
113
src/scram.c
113
src/scram.c
@@ -19,6 +19,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "ostypes.h"
|
#include "ostypes.h"
|
||||||
|
|
||||||
@@ -29,25 +30,39 @@
|
|||||||
static const uint8_t ipad = 0x36;
|
static const uint8_t ipad = 0x36;
|
||||||
static const uint8_t opad = 0x5C;
|
static const uint8_t opad = 0x5C;
|
||||||
|
|
||||||
static void crypto_HMAC_SHA1(const uint8_t *key,
|
const struct hash_alg scram_sha1 = {
|
||||||
size_t key_len,
|
"SCRAM-SHA-1",
|
||||||
const uint8_t *text,
|
SASL_MASK_SCRAMSHA1,
|
||||||
size_t len,
|
SHA1_DIGEST_SIZE,
|
||||||
uint8_t *digest)
|
(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_pad[HMAC_BLOCK_SIZE];
|
||||||
uint8_t key_ipad[HMAC_BLOCK_SIZE];
|
uint8_t key_ipad[HMAC_BLOCK_SIZE];
|
||||||
uint8_t key_opad[HMAC_BLOCK_SIZE];
|
uint8_t key_opad[HMAC_BLOCK_SIZE];
|
||||||
uint8_t sha_digest[SHA1_DIGEST_SIZE];
|
uint8_t sha_digest[SHA1_DIGEST_SIZE];
|
||||||
int i;
|
int i;
|
||||||
SHA1_CTX ctx;
|
union common_hash_ctx ctx;
|
||||||
|
|
||||||
memset(key_pad, 0, sizeof(key_pad));
|
memset(key_pad, 0, sizeof(key_pad));
|
||||||
if (key_len <= HMAC_BLOCK_SIZE) {
|
if (key_len <= HMAC_BLOCK_SIZE) {
|
||||||
memcpy(key_pad, key, key_len);
|
memcpy(key_pad, key, key_len);
|
||||||
} else {
|
} else {
|
||||||
/* according to RFC2104 */
|
/* 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++) {
|
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;
|
key_opad[i] = key_pad[i] ^ opad;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto_SHA1_Init(&ctx);
|
alg->init((void *)&ctx);
|
||||||
crypto_SHA1_Update(&ctx, key_ipad, HMAC_BLOCK_SIZE);
|
alg->update((void *)&ctx, key_ipad, HMAC_BLOCK_SIZE);
|
||||||
crypto_SHA1_Update(&ctx, text, len);
|
alg->update((void *)&ctx, text, len);
|
||||||
crypto_SHA1_Final(&ctx, sha_digest);
|
alg->final((void *)&ctx, sha_digest);
|
||||||
|
|
||||||
crypto_SHA1_Init(&ctx);
|
alg->init((void *)&ctx);
|
||||||
crypto_SHA1_Update(&ctx, key_opad, HMAC_BLOCK_SIZE);
|
alg->update((void *)&ctx, key_opad, HMAC_BLOCK_SIZE);
|
||||||
crypto_SHA1_Update(&ctx, sha_digest, SHA1_DIGEST_SIZE);
|
alg->update((void *)&ctx, sha_digest, alg->digest_size);
|
||||||
crypto_SHA1_Final(&ctx, digest);
|
alg->final((void *)&ctx, digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SCRAM_SHA1_Hi(const uint8_t *text,
|
static void SCRAM_Hi(const struct hash_alg *alg,
|
||||||
size_t len,
|
const uint8_t *text,
|
||||||
const uint8_t *salt,
|
size_t len,
|
||||||
size_t salt_len,
|
const uint8_t *salt,
|
||||||
uint32_t i,
|
size_t salt_len,
|
||||||
uint8_t *digest)
|
uint32_t i,
|
||||||
|
uint8_t *digest)
|
||||||
{
|
{
|
||||||
int k;
|
size_t k;
|
||||||
uint32_t j;
|
uint32_t j;
|
||||||
uint8_t tmp[128];
|
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) */
|
/* assume salt + INT(1) isn't longer than sizeof(tmp) */
|
||||||
assert(salt_len <= sizeof(tmp) - sizeof(int1));
|
assert(salt_len <= sizeof(tmp) - sizeof(int1));
|
||||||
|
|
||||||
memset(digest, 0, SHA1_DIGEST_SIZE);
|
memset(digest, 0, alg->digest_size);
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -91,50 +107,53 @@ static void SCRAM_SHA1_Hi(const uint8_t *text,
|
|||||||
memcpy(&tmp[salt_len], int1, sizeof(int1));
|
memcpy(&tmp[salt_len], int1, sizeof(int1));
|
||||||
|
|
||||||
/* 'text' for Hi is a 'key' for HMAC */
|
/* 'text' for Hi is a 'key' for HMAC */
|
||||||
crypto_HMAC_SHA1(text, len, tmp, salt_len + sizeof(int1), digest);
|
crypto_HMAC(alg, text, len, tmp, salt_len + sizeof(int1), digest);
|
||||||
memcpy(tmp, digest, SHA1_DIGEST_SIZE);
|
memcpy(tmp, digest, alg->digest_size);
|
||||||
|
|
||||||
for (j = 1; j < i; j++) {
|
for (j = 1; j < i; j++) {
|
||||||
crypto_HMAC_SHA1(text, len, tmp, SHA1_DIGEST_SIZE, tmp);
|
crypto_HMAC(alg, text, len, tmp, alg->digest_size, tmp);
|
||||||
for (k = 0; k < SHA1_DIGEST_SIZE; k++) {
|
for (k = 0; k < alg->digest_size; k++) {
|
||||||
digest[k] ^= tmp[k];
|
digest[k] ^= tmp[k];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCRAM_SHA1_ClientKey(const uint8_t *password,
|
void SCRAM_ClientKey(const struct hash_alg *alg,
|
||||||
size_t len,
|
const uint8_t *password,
|
||||||
const uint8_t *salt,
|
size_t len,
|
||||||
size_t salt_len,
|
const uint8_t *salt,
|
||||||
uint32_t i,
|
size_t salt_len,
|
||||||
uint8_t *key)
|
uint32_t i,
|
||||||
|
uint8_t *key)
|
||||||
{
|
{
|
||||||
uint8_t salted[SHA1_DIGEST_SIZE];
|
uint8_t salted[SHA1_DIGEST_SIZE];
|
||||||
|
|
||||||
/* XXX: Normalize(password) is omitted */
|
/* XXX: Normalize(password) is omitted */
|
||||||
|
|
||||||
SCRAM_SHA1_Hi(password, len, salt, salt_len, i, salted);
|
SCRAM_Hi(alg, password, len, salt, salt_len, i, salted);
|
||||||
crypto_HMAC_SHA1(salted, SHA1_DIGEST_SIZE, (uint8_t *)"Client Key",
|
crypto_HMAC(alg, salted, alg->digest_size, (uint8_t *)"Client Key",
|
||||||
strlen("Client Key"), key);
|
strlen("Client Key"), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCRAM_SHA1_ClientSignature(const uint8_t *ClientKey,
|
void SCRAM_ClientSignature(const struct hash_alg *alg,
|
||||||
const uint8_t *AuthMessage,
|
const uint8_t *ClientKey,
|
||||||
size_t len,
|
const uint8_t *AuthMessage,
|
||||||
uint8_t *sign)
|
size_t len,
|
||||||
|
uint8_t *sign)
|
||||||
{
|
{
|
||||||
uint8_t stored[SHA1_DIGEST_SIZE];
|
uint8_t stored[SHA1_DIGEST_SIZE];
|
||||||
|
|
||||||
crypto_SHA1(ClientKey, SHA1_DIGEST_SIZE, stored);
|
alg->hash(ClientKey, alg->digest_size, stored);
|
||||||
crypto_HMAC_SHA1(stored, SHA1_DIGEST_SIZE, AuthMessage, len, sign);
|
crypto_HMAC(alg, stored, alg->digest_size, AuthMessage, len, sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SCRAM_SHA1_ClientProof(const uint8_t *ClientKey,
|
void SCRAM_ClientProof(const struct hash_alg *alg,
|
||||||
const uint8_t *ClientSignature,
|
const uint8_t *ClientKey,
|
||||||
uint8_t *proof)
|
const uint8_t *ClientSignature,
|
||||||
|
uint8_t *proof)
|
||||||
{
|
{
|
||||||
int i;
|
size_t i;
|
||||||
for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
|
for (i = 0; i < alg->digest_size; i++) {
|
||||||
proof[i] = ClientKey[i] ^ ClientSignature[i];
|
proof[i] = ClientKey[i] ^ ClientSignature[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
41
src/scram.h
41
src/scram.h
@@ -19,22 +19,35 @@
|
|||||||
/* make sure the stdint.h types are available */
|
/* make sure the stdint.h types are available */
|
||||||
#include "ostypes.h"
|
#include "ostypes.h"
|
||||||
|
|
||||||
#include "sha1.h"
|
struct hash_alg {
|
||||||
|
const char *scram_name;
|
||||||
|
int mask;
|
||||||
|
size_t digest_size;
|
||||||
|
void (*hash)(const uint8_t *, size_t, uint8_t *);
|
||||||
|
void (*init)(void *);
|
||||||
|
void (*update)(void *, const uint8_t *, size_t);
|
||||||
|
void (*final)(void *, uint8_t *);
|
||||||
|
};
|
||||||
|
|
||||||
void SCRAM_SHA1_ClientKey(const uint8_t *password,
|
extern const struct hash_alg scram_sha1;
|
||||||
size_t len,
|
|
||||||
const uint8_t *salt,
|
|
||||||
size_t salt_len,
|
|
||||||
uint32_t i,
|
|
||||||
uint8_t *key);
|
|
||||||
|
|
||||||
void SCRAM_SHA1_ClientSignature(const uint8_t *ClientKey,
|
void SCRAM_ClientKey(const struct hash_alg *alg,
|
||||||
const uint8_t *AuthMessage,
|
const uint8_t *password,
|
||||||
size_t len,
|
size_t len,
|
||||||
uint8_t *sign);
|
const uint8_t *salt,
|
||||||
|
size_t salt_len,
|
||||||
|
uint32_t i,
|
||||||
|
uint8_t *key);
|
||||||
|
|
||||||
void SCRAM_SHA1_ClientProof(const uint8_t *ClientKey,
|
void SCRAM_ClientSignature(const struct hash_alg *alg,
|
||||||
const uint8_t *ClientSignature,
|
const uint8_t *ClientKey,
|
||||||
uint8_t *proof);
|
const uint8_t *AuthMessage,
|
||||||
|
size_t len,
|
||||||
|
uint8_t *sign);
|
||||||
|
|
||||||
|
void SCRAM_ClientProof(const struct hash_alg *alg,
|
||||||
|
const uint8_t *ClientKey,
|
||||||
|
const uint8_t *ClientSignature,
|
||||||
|
uint8_t *proof);
|
||||||
|
|
||||||
#endif /* __LIBSTROPHE_SCRAM_H__ */
|
#endif /* __LIBSTROPHE_SCRAM_H__ */
|
||||||
|
|||||||
@@ -67,9 +67,9 @@ static void test_df(void)
|
|||||||
printf("Derivation function tests (SCRAM_SHA1_Hi).\n");
|
printf("Derivation function tests (SCRAM_SHA1_Hi).\n");
|
||||||
for (i = 0; i < ARRAY_SIZE(df_vectors); ++i) {
|
for (i = 0; i < ARRAY_SIZE(df_vectors); ++i) {
|
||||||
printf("Test #%d: ", (int)i + 1);
|
printf("Test #%d: ", (int)i + 1);
|
||||||
SCRAM_SHA1_Hi((uint8_t *)df_vectors[i].P, df_vectors[i].P_len,
|
SCRAM_Hi(&scram_sha1, (uint8_t *)df_vectors[i].P, df_vectors[i].P_len,
|
||||||
(uint8_t *)df_vectors[i].S, df_vectors[i].S_len,
|
(uint8_t *)df_vectors[i].S, df_vectors[i].S_len,
|
||||||
df_vectors[i].c, dk);
|
df_vectors[i].c, dk);
|
||||||
s = test_bin_to_hex(dk, sizeof(dk));
|
s = test_bin_to_hex(dk, sizeof(dk));
|
||||||
COMPARE(df_vectors[i].DK, s);
|
COMPARE(df_vectors[i].DK, s);
|
||||||
printf("ok\n");
|
printf("ok\n");
|
||||||
@@ -119,10 +119,11 @@ static void test_scram(void)
|
|||||||
scram_vectors[i].challenge, scram_vectors[i].response);
|
scram_vectors[i].challenge, scram_vectors[i].response);
|
||||||
test_hex_to_bin(scram_vectors[i].salt, salt, &salt_len);
|
test_hex_to_bin(scram_vectors[i].salt, salt, &salt_len);
|
||||||
|
|
||||||
SCRAM_SHA1_ClientKey((uint8_t *)scram_vectors[i].password,
|
SCRAM_ClientKey(&scram_sha1, (uint8_t *)scram_vectors[i].password,
|
||||||
strlen(scram_vectors[i].password), salt, salt_len,
|
strlen(scram_vectors[i].password), salt, salt_len,
|
||||||
scram_vectors[i].i, key);
|
scram_vectors[i].i, key);
|
||||||
SCRAM_SHA1_ClientSignature(key, (uint8_t *)auth, strlen(auth), sign);
|
SCRAM_ClientSignature(&scram_sha1, key, (uint8_t *)auth, strlen(auth),
|
||||||
|
sign);
|
||||||
for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
|
for (j = 0; j < SHA1_DIGEST_SIZE; j++) {
|
||||||
sign[j] ^= key[j];
|
sign[j] ^= key[j];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user