Merge branch 'const-memeq'
Introduce constant time memory comparing functions for cryptographic purposes, and a tool to test such functions or crypto transforms relying on them.
This commit is contained in:
commit
aa9b74931f
|
@ -15,3 +15,4 @@ pubkey_speed
|
||||||
settings-test
|
settings-test
|
||||||
thread_analysis
|
thread_analysis
|
||||||
tls_test
|
tls_test
|
||||||
|
timeattack
|
||||||
|
|
|
@ -5,7 +5,7 @@ AM_CPPFLAGS = \
|
||||||
|
|
||||||
noinst_PROGRAMS = bin2array bin2sql id2sql key2keyid keyid2sql oid2der \
|
noinst_PROGRAMS = bin2array bin2sql id2sql key2keyid keyid2sql oid2der \
|
||||||
thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch \
|
thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch \
|
||||||
dnssec malloc_speed aes-test settings-test
|
dnssec malloc_speed aes-test settings-test timeattack
|
||||||
|
|
||||||
if USE_TLS
|
if USE_TLS
|
||||||
noinst_PROGRAMS += tls_test
|
noinst_PROGRAMS += tls_test
|
||||||
|
@ -28,6 +28,7 @@ hash_burn_SOURCES = hash_burn.c
|
||||||
malloc_speed_SOURCES = malloc_speed.c
|
malloc_speed_SOURCES = malloc_speed.c
|
||||||
fetch_SOURCES = fetch.c
|
fetch_SOURCES = fetch.c
|
||||||
dnssec_SOURCES = dnssec.c
|
dnssec_SOURCES = dnssec.c
|
||||||
|
timeattack_SOURCES = timeattack.c
|
||||||
id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
|
@ -41,6 +42,7 @@ fetch_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
|
timeattack_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
|
||||||
|
|
||||||
key2keyid.o : $(top_builddir)/config.status
|
key2keyid.o : $(top_builddir)/config.status
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,418 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <library.h>
|
||||||
|
|
||||||
|
typedef bool (*attackfn_t)(void *subj, u_char *data, size_t len);
|
||||||
|
|
||||||
|
static void start_timing(struct timespec *start)
|
||||||
|
{
|
||||||
|
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_int64_t end_timing(struct timespec *start)
|
||||||
|
{
|
||||||
|
struct timespec end;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
|
||||||
|
return (end.tv_nsec - start->tv_nsec) +
|
||||||
|
(end.tv_sec - start->tv_sec) * 1000000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intcmp(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
return *(u_int64_t*)a - *(u_int64_t*)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u_int64_t median(u_int64_t *m, int count)
|
||||||
|
{
|
||||||
|
qsort(m, count, sizeof(u_int64_t), intcmp);
|
||||||
|
return m[count / 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool timeattack(attackfn_t attackfn, void *subj, size_t dlen,
|
||||||
|
u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
struct timespec start;
|
||||||
|
u_char test[dlen];
|
||||||
|
u_int64_t mini, maxi, t[256], m[256][10];
|
||||||
|
float fastdist = 0, slowdist = 0;
|
||||||
|
int i, j, k, l, byte, limit, retry = 0;
|
||||||
|
int fastest = 0, slowest = 0;
|
||||||
|
|
||||||
|
memset(test, 0, dlen);
|
||||||
|
|
||||||
|
/* do some iterations to fill caches */
|
||||||
|
for (i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
attackfn(subj, test, dlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (byte = 0; byte < dlen;)
|
||||||
|
{
|
||||||
|
memset(t, 0, sizeof(t));
|
||||||
|
memset(m, 0, sizeof(m));
|
||||||
|
|
||||||
|
limit = iterations * (retry + 1);
|
||||||
|
|
||||||
|
/* measure timing for all patterns in next byte */
|
||||||
|
for (k = 0; k < 10; k++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
for (l = 0; l < 100; l++)
|
||||||
|
{
|
||||||
|
test[byte] = j;
|
||||||
|
start_timing(&start);
|
||||||
|
for (i = 0; i < limit; i++)
|
||||||
|
{
|
||||||
|
attackfn(subj, test, dlen);
|
||||||
|
}
|
||||||
|
m[j][k] += end_timing(&start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
t[j] = median(m[j], countof(m[j]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find fastest/slowest runs */
|
||||||
|
mini = ~0;
|
||||||
|
maxi = 0;
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
if (t[j] < mini)
|
||||||
|
{
|
||||||
|
mini = min(t[j], mini);
|
||||||
|
fastest = j;
|
||||||
|
}
|
||||||
|
if (t[j] > maxi)
|
||||||
|
{
|
||||||
|
maxi = max(t[j], maxi);
|
||||||
|
slowest = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* calculate distance to next result */
|
||||||
|
mini = ~0;
|
||||||
|
maxi = 0;
|
||||||
|
for (j = 0; j < 256; j++)
|
||||||
|
{
|
||||||
|
if (fastest != j && t[j] < mini)
|
||||||
|
{
|
||||||
|
mini = min(t[j], mini);
|
||||||
|
fastdist = (float)(t[j] - t[fastest]) / distance;
|
||||||
|
}
|
||||||
|
if (slowest != j && t[j] > maxi)
|
||||||
|
{
|
||||||
|
maxi = max(t[j], maxi);
|
||||||
|
slowdist = (float)(t[slowest] - t[j]) / distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fastdist > 1.0f)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "byte %02d: %02x (fastest, dist %02.2f)\n",
|
||||||
|
byte, fastest, fastdist);
|
||||||
|
test[byte] = fastest;
|
||||||
|
retry = 0;
|
||||||
|
byte++;
|
||||||
|
}
|
||||||
|
else if (slowdist > 1.0f)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "byte %02d: %02x (slowest, dist %02.2f)\n",
|
||||||
|
byte, slowest, slowdist);
|
||||||
|
test[byte] = slowest;
|
||||||
|
retry = 0;
|
||||||
|
byte++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (retry++ > 5 && byte > 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "distance fastest %02.2f (%02x), "
|
||||||
|
"slowest %02.2f (%02x), stepping back\n",
|
||||||
|
fastdist, fastest, slowdist, slowest);
|
||||||
|
test[byte--] = 0;
|
||||||
|
}
|
||||||
|
else if (retry < 10)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "distance fastest %02.2f (%02x), "
|
||||||
|
"slowest %02.2f (%02x), retrying (%d)\n",
|
||||||
|
fastdist, fastest, slowdist, slowest, retry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("attack failed, giving up\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attackfn(subj, test, dlen))
|
||||||
|
{
|
||||||
|
printf("attack successful with %b\n", test, dlen);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
printf("attack failed with %b\n", test, dlen);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_memeq1, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return memeq(data, subj, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_memeq2, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return memeq(subj, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_memeq3, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (subj[i] != data[i])
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_memeq4, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
int i, m = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
m |= subj[i] != data[i];
|
||||||
|
}
|
||||||
|
return !m;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_memeq5, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return memeq_const(subj, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool attack_memeq(char *name, u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
attackfn_t fn;
|
||||||
|
} attacks[] = {
|
||||||
|
{ "memeq1", attack_memeq1 },
|
||||||
|
{ "memeq2", attack_memeq2 },
|
||||||
|
{ "memeq3", attack_memeq3 },
|
||||||
|
{ "memeq4", attack_memeq4 },
|
||||||
|
{ "memeq5", attack_memeq5 },
|
||||||
|
};
|
||||||
|
u_char exp[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
srandom(time(NULL));
|
||||||
|
for (i = 0; i < sizeof(exp); i++)
|
||||||
|
{
|
||||||
|
exp[i] = random();
|
||||||
|
}
|
||||||
|
fprintf(stderr, "attacking %b\n", exp, sizeof(exp));
|
||||||
|
|
||||||
|
for (i = 0; i < countof(attacks); i++)
|
||||||
|
{
|
||||||
|
if (streq(name, attacks[i].name))
|
||||||
|
{
|
||||||
|
return timeattack(attacks[i].fn, exp, sizeof(exp),
|
||||||
|
iterations, distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_chunk1, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return chunk_equals(chunk_create(subj, len), chunk_create(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_chunk2, bool,
|
||||||
|
u_char *subj, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return chunk_equals_const(chunk_create(subj, len), chunk_create(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool attack_chunk(char *name, u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
char *name;
|
||||||
|
attackfn_t fn;
|
||||||
|
} attacks[] = {
|
||||||
|
{ "chunk1", attack_chunk1 },
|
||||||
|
{ "chunk2", attack_chunk2 },
|
||||||
|
};
|
||||||
|
u_char exp[16];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
srandom(time(NULL));
|
||||||
|
for (i = 0; i < sizeof(exp); i++)
|
||||||
|
{
|
||||||
|
exp[i] = random();
|
||||||
|
}
|
||||||
|
fprintf(stderr, "attacking %b\n", exp, sizeof(exp));
|
||||||
|
|
||||||
|
for (i = 0; i < countof(attacks); i++)
|
||||||
|
{
|
||||||
|
if (streq(name, attacks[i].name))
|
||||||
|
{
|
||||||
|
return timeattack(attacks[i].fn, exp, sizeof(exp),
|
||||||
|
iterations, distance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_aead, bool,
|
||||||
|
aead_t *aead, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
u_char iv[aead->get_iv_size(aead)];
|
||||||
|
|
||||||
|
memset(iv, 0, sizeof(iv));
|
||||||
|
return aead->decrypt(aead, chunk_create(data, len), chunk_empty,
|
||||||
|
chunk_from_thing(iv), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool attack_aeads(encryption_algorithm_t alg, size_t key_size,
|
||||||
|
u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
u_char buf[64];
|
||||||
|
aead_t *aead;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
aead = lib->crypto->create_aead(lib->crypto, alg, key_size, 0);
|
||||||
|
if (!aead)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "creating AEAD %N failed\n",
|
||||||
|
encryption_algorithm_names, alg);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(buf, 0xe3, sizeof(buf));
|
||||||
|
if (!aead->set_key(aead, chunk_create(buf, aead->get_key_size(aead))))
|
||||||
|
{
|
||||||
|
aead->destroy(aead);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(buf, 0, aead->get_iv_size(aead));
|
||||||
|
if (!aead->encrypt(aead, chunk_create(buf, 0), chunk_empty,
|
||||||
|
chunk_create(buf, aead->get_iv_size(aead)), NULL))
|
||||||
|
{
|
||||||
|
aead->destroy(aead);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "attacking %b\n", buf, aead->get_icv_size(aead));
|
||||||
|
|
||||||
|
res = timeattack(attack_aead, aead, aead->get_icv_size(aead),
|
||||||
|
iterations, distance);
|
||||||
|
aead->destroy(aead);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK(attack_signer, bool,
|
||||||
|
signer_t *signer, u_char *data, size_t len)
|
||||||
|
{
|
||||||
|
return signer->verify_signature(signer, chunk_empty, chunk_create(data, len));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool attack_signers(integrity_algorithm_t alg,
|
||||||
|
u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
u_char buf[64];
|
||||||
|
signer_t *signer;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
signer = lib->crypto->create_signer(lib->crypto, alg);
|
||||||
|
if (!signer)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "creating signer %N failed\n",
|
||||||
|
integrity_algorithm_names, alg);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(buf, 0xe3, sizeof(buf));
|
||||||
|
if (!signer->set_key(signer, chunk_create(buf, signer->get_key_size(signer))))
|
||||||
|
{
|
||||||
|
signer->destroy(signer);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!signer->get_signature(signer, chunk_empty, buf))
|
||||||
|
{
|
||||||
|
signer->destroy(signer);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "attacking %b\n", buf, signer->get_block_size(signer));
|
||||||
|
|
||||||
|
res = timeattack(attack_signer, signer, signer->get_block_size(signer),
|
||||||
|
iterations, distance);
|
||||||
|
signer->destroy(signer);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool attack_transform(char *name, u_int iterations, u_int distance)
|
||||||
|
{
|
||||||
|
const proposal_token_t *token;
|
||||||
|
|
||||||
|
token = lib->proposal->get_token(lib->proposal, name);
|
||||||
|
if (!token)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "algorithm '%s' unknown\n", name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (token->type)
|
||||||
|
{
|
||||||
|
case ENCRYPTION_ALGORITHM:
|
||||||
|
if (encryption_algorithm_is_aead(token->algorithm))
|
||||||
|
{
|
||||||
|
return attack_aeads(token->algorithm, token->keysize / 8,
|
||||||
|
iterations, distance);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "can't attack a crypter\n");
|
||||||
|
return FALSE;
|
||||||
|
case INTEGRITY_ALGORITHM:
|
||||||
|
return attack_signers(token->algorithm, iterations, distance);
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "can't attack a %N\n", transform_type_names, token->type);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
library_init(NULL, "timeattack");
|
||||||
|
atexit(library_deinit);
|
||||||
|
lib->plugins->load(lib->plugins, getenv("PLUGINS") ?: PLUGINS);
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "usage: %s <attack> <iterations> <distance>\n", argv[0]);
|
||||||
|
fprintf(stderr, " <attack>: memeq[1-5] / chunk[1-2] / aead / signer\n");
|
||||||
|
fprintf(stderr, " <iterations>: number of invocations * 1000\n");
|
||||||
|
fprintf(stderr, " <distance>: time difference in ns for a hit\n");
|
||||||
|
fprintf(stderr, " example: %s memeq1 100 500\n", argv[0]);
|
||||||
|
fprintf(stderr, " example: %s aes128gcm16 100 4000\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (strpfx(argv[1], "memeq"))
|
||||||
|
{
|
||||||
|
return !attack_memeq(argv[1], atoi(argv[2]), atoi(argv[3]));
|
||||||
|
}
|
||||||
|
if (strpfx(argv[1], "chunk"))
|
||||||
|
{
|
||||||
|
return !attack_chunk(argv[1], atoi(argv[2]), atoi(argv[3]));
|
||||||
|
}
|
||||||
|
return !attack_transform(argv[1], atoi(argv[2]), atoi(argv[3]));
|
||||||
|
}
|
|
@ -2625,7 +2625,7 @@ METHOD(message_t, parse_body, status_t,
|
||||||
other_hash = hash_payload->get_hash(hash_payload);
|
other_hash = hash_payload->get_hash(hash_payload);
|
||||||
DBG3(DBG_ENC, "HASH received %B\nHASH expected %B",
|
DBG3(DBG_ENC, "HASH received %B\nHASH expected %B",
|
||||||
&other_hash, &hash);
|
&other_hash, &hash);
|
||||||
if (!chunk_equals(hash, other_hash))
|
if (!chunk_equals_const(hash, other_hash))
|
||||||
{
|
{
|
||||||
DBG1(DBG_ENC, "received HASH payload does not match");
|
DBG1(DBG_ENC, "received HASH payload does not match");
|
||||||
chunk_free(&hash);
|
chunk_free(&hash);
|
||||||
|
|
|
@ -247,7 +247,7 @@ static bool cookie_verify(private_receiver_t *this, message_t *message,
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (chunk_equals(reference, cookie))
|
if (chunk_equals_const(reference, cookie))
|
||||||
{
|
{
|
||||||
chunk_free(&reference);
|
chunk_free(&reference);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -425,7 +425,7 @@ static status_t process_challenge(private_eap_aka_server_t *this,
|
||||||
enumerator->destroy(enumerator);
|
enumerator->destroy(enumerator);
|
||||||
|
|
||||||
/* compare received RES against stored XRES */
|
/* compare received RES against stored XRES */
|
||||||
if (!chunk_equals(res, this->xres))
|
if (!chunk_equals_const(res, this->xres))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received RES does not match XRES");
|
DBG1(DBG_IKE, "received RES does not match XRES");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
@ -486,7 +486,7 @@ static status_t process_reauthentication(private_eap_aka_server_t *this,
|
||||||
this->crypto->clear_keys(this->crypto);
|
this->crypto->clear_keys(this->crypto);
|
||||||
return challenge(this, out);
|
return challenge(this, out);
|
||||||
}
|
}
|
||||||
if (!chunk_equals(counter, this->counter))
|
if (!chunk_equals_const(counter, this->counter))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received counter does not match");
|
DBG1(DBG_IKE, "received counter does not match");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
@ -730,4 +730,3 @@ eap_aka_server_t *eap_aka_server_create(identification_t *server,
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
|
||||||
{
|
{
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
if (!memeq(mac, xmac, AKA_MAC_LEN))
|
if (!memeq_const(mac, xmac, AKA_MAC_LEN))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received MAC does not match XMAC");
|
DBG1(DBG_IKE, "received MAC does not match XMAC");
|
||||||
DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
|
DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
|
||||||
|
@ -184,4 +184,3 @@ eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ METHOD(simaka_provider_t, resync, bool,
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!memeq(macs, xmacs, AKA_MAC_LEN))
|
if (!memeq_const(macs, xmacs, AKA_MAC_LEN))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received MACS does not match XMACS");
|
DBG1(DBG_IKE, "received MACS does not match XMACS");
|
||||||
DBG3(DBG_IKE, "MACS %b XMACS %b",
|
DBG3(DBG_IKE, "MACS %b XMACS %b",
|
||||||
|
@ -205,4 +205,3 @@ eap_aka_3gpp2_provider_t *eap_aka_3gpp2_provider_create(
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ METHOD(eap_method_t, process_server, status_t,
|
||||||
}
|
}
|
||||||
response = chunk_create(data.ptr + 6, data.ptr[5]);
|
response = chunk_create(data.ptr + 6, data.ptr[5]);
|
||||||
if (response.len < expected.len ||
|
if (response.len < expected.len ||
|
||||||
!memeq(response.ptr, expected.ptr, expected.len))
|
!memeq_const(response.ptr, expected.ptr, expected.len))
|
||||||
{
|
{
|
||||||
chunk_free(&expected);
|
chunk_free(&expected);
|
||||||
DBG1(DBG_IKE, "EAP-MD5 verification failed");
|
DBG1(DBG_IKE, "EAP-MD5 verification failed");
|
||||||
|
@ -299,4 +299,3 @@ eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer)
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -812,7 +812,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chunk_equals(this->auth_response, auth_string))
|
if (!chunk_equals_const(this->auth_response, auth_string))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
|
DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -1087,7 +1087,7 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
|
||||||
userid->destroy(userid);
|
userid->destroy(userid);
|
||||||
chunk_clear(&nt_hash);
|
chunk_clear(&nt_hash);
|
||||||
|
|
||||||
if (memeq(res->response.nt_response, this->nt_response.ptr,
|
if (memeq_const(res->response.nt_response, this->nt_response.ptr,
|
||||||
this->nt_response.len))
|
this->nt_response.len))
|
||||||
{
|
{
|
||||||
chunk_t hex;
|
chunk_t hex;
|
||||||
|
@ -1267,4 +1267,3 @@ eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identificatio
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -310,7 +310,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
|
||||||
/* excepting two or three RAND, each 16 bytes. We require two valid
|
/* excepting two or three RAND, each 16 bytes. We require two valid
|
||||||
* and different RANDs */
|
* and different RANDs */
|
||||||
if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
|
if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
|
||||||
memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
|
memeq_const(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "no valid AT_RAND received");
|
DBG1(DBG_IKE, "no valid AT_RAND received");
|
||||||
if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
|
if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
|
||||||
|
@ -734,4 +734,3 @@ eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,7 +262,7 @@ static status_t process_reauthentication(private_eap_sim_server_t *this,
|
||||||
this->crypto->clear_keys(this->crypto);
|
this->crypto->clear_keys(this->crypto);
|
||||||
return initiate(this, out);
|
return initiate(this, out);
|
||||||
}
|
}
|
||||||
if (!chunk_equals(counter, this->counter))
|
if (!chunk_equals_const(counter, this->counter))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "received counter does not match");
|
DBG1(DBG_IKE, "received counter does not match");
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
@ -644,4 +644,3 @@ eap_sim_server_t *eap_sim_server_create(identification_t *server,
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ METHOD(simaka_card_t, get_triplet, bool,
|
||||||
c_rand, SIM_RAND_LEN, c_sres, SIM_SRES_LEN, c_kc, SIM_KC_LEN);
|
c_rand, SIM_RAND_LEN, c_sres, SIM_SRES_LEN, c_kc, SIM_KC_LEN);
|
||||||
if (id->matches(id, cand))
|
if (id->matches(id, cand))
|
||||||
{
|
{
|
||||||
if (memeq(c_rand, rand, SIM_RAND_LEN))
|
if (memeq_const(c_rand, rand, SIM_RAND_LEN))
|
||||||
{
|
{
|
||||||
DBG2(DBG_CFG, " => triplet matches");
|
DBG2(DBG_CFG, " => triplet matches");
|
||||||
memcpy(sres, c_sres, SIM_SRES_LEN);
|
memcpy(sres, c_sres, SIM_SRES_LEN);
|
||||||
|
@ -105,4 +105,3 @@ eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets)
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ METHOD(xauth_method_t, process_server, status_t,
|
||||||
SHARED_EAP, this->server, this->peer);
|
SHARED_EAP, this->server, this->peer);
|
||||||
while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
|
while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
|
||||||
{
|
{
|
||||||
if (chunk_equals(shared->get_key(shared), pass))
|
if (chunk_equals_const(shared->get_key(shared), pass))
|
||||||
{
|
{
|
||||||
status = SUCCESS;
|
status = SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -124,7 +124,7 @@ METHOD(authenticator_t, process, status_t,
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
free(dh.ptr);
|
free(dh.ptr);
|
||||||
if (chunk_equals(hash, hash_payload->get_hash(hash_payload)))
|
if (chunk_equals_const(hash, hash_payload->get_hash(hash_payload)))
|
||||||
{
|
{
|
||||||
free(hash.ptr);
|
free(hash.ptr);
|
||||||
if (!this->hybrid)
|
if (!this->hybrid)
|
||||||
|
|
|
@ -464,7 +464,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
recv_auth_data = auth_payload->get_data(auth_payload);
|
recv_auth_data = auth_payload->get_data(auth_payload);
|
||||||
if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
|
if (!auth_data.len || !chunk_equals_const(auth_data, recv_auth_data))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
|
DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
|
||||||
this->msk.ptr ? "" : "out");
|
this->msk.ptr ? "" : "out");
|
||||||
|
|
|
@ -123,7 +123,7 @@ METHOD(authenticator_t, process, status_t,
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
|
if (auth_data.len && chunk_equals_const(auth_data, recv_auth_data))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
|
DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
|
||||||
other_id, auth_method_names, AUTH_PSK);
|
other_id, auth_method_names, AUTH_PSK);
|
||||||
|
|
|
@ -537,7 +537,7 @@ METHOD(task_t, process_i, status_t,
|
||||||
cookie2 = this->cookie2;
|
cookie2 = this->cookie2;
|
||||||
this->cookie2 = chunk_empty;
|
this->cookie2 = chunk_empty;
|
||||||
process_payloads(this, message);
|
process_payloads(this, message);
|
||||||
if (!chunk_equals(cookie2, this->cookie2))
|
if (!chunk_equals_const(cookie2, this->cookie2))
|
||||||
{
|
{
|
||||||
chunk_free(&cookie2);
|
chunk_free(&cookie2);
|
||||||
DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
|
DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
|
||||||
|
|
|
@ -181,7 +181,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
|
||||||
DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
|
DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
|
||||||
keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
|
keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
|
||||||
if (session->get_device_id(session, &device_id) &&
|
if (session->get_device_id(session, &device_id) &&
|
||||||
chunk_equals(keyid_hex, device_id))
|
chunk_equals_const(keyid_hex, device_id))
|
||||||
{
|
{
|
||||||
trusted = session->get_device_trust(session);
|
trusted = session->get_device_trust(session);
|
||||||
}
|
}
|
||||||
|
@ -446,7 +446,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!chunk_equals(pcr_comp, pcr_composite))
|
if (!chunk_equals_const(pcr_comp, pcr_composite))
|
||||||
{
|
{
|
||||||
DBG1(DBG_IMV, "received PCR Composite does not match "
|
DBG1(DBG_IMV, "received PCR Composite does not match "
|
||||||
"constructed one");
|
"constructed one");
|
||||||
|
@ -564,4 +564,3 @@ quote_error:
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,7 @@ static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
|
||||||
}
|
}
|
||||||
if (pcr_ok)
|
if (pcr_ok)
|
||||||
{
|
{
|
||||||
success = chunk_equals(boot_aggregate, measurement);
|
success = chunk_equals_const(boot_aggregate, measurement);
|
||||||
DBG1(DBG_PTS, "boot aggregate value is %scorrect",
|
DBG1(DBG_PTS, "boot aggregate value is %scorrect",
|
||||||
success ? "":"in");
|
success ? "":"in");
|
||||||
return success;
|
return success;
|
||||||
|
@ -693,7 +693,7 @@ METHOD(pts_component_t, verify, status_t,
|
||||||
status = FAILED;
|
status = FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (chunk_equals(measurement, hash))
|
if (chunk_equals_const(measurement, hash))
|
||||||
{
|
{
|
||||||
status = SUCCESS;
|
status = SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
@ -748,7 +748,7 @@ METHOD(pts_component_t, verify, status_t,
|
||||||
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
||||||
if (has_pcr_info)
|
if (has_pcr_info)
|
||||||
{
|
{
|
||||||
if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
|
if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, pcr)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
|
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
|
||||||
pcr);
|
pcr);
|
||||||
|
@ -911,4 +911,3 @@ pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ METHOD(pts_component_t, verify, status_t,
|
||||||
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
||||||
if (has_pcr_info)
|
if (has_pcr_info)
|
||||||
{
|
{
|
||||||
if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
|
if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
|
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
|
||||||
extended_pcr);
|
extended_pcr);
|
||||||
|
@ -354,4 +354,3 @@ pts_component_t *pts_ita_comp_tboot_create(u_int32_t depth,
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ METHOD(pts_component_t, verify, status_t,
|
||||||
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
|
||||||
if (has_pcr_info)
|
if (has_pcr_info)
|
||||||
{
|
{
|
||||||
if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
|
if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
|
DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,7 +187,7 @@ METHOD(pts_database_t, add_file_measurement, status_t,
|
||||||
}
|
}
|
||||||
if (e->enumerate(e, &hash_id, &hash_value))
|
if (e->enumerate(e, &hash_id, &hash_value))
|
||||||
{
|
{
|
||||||
if (!chunk_equals(measurement, hash_value))
|
if (!chunk_equals_const(measurement, hash_value))
|
||||||
{
|
{
|
||||||
/* update hash measurement value */
|
/* update hash measurement value */
|
||||||
if (this->db->execute(this->db, &hash_id,
|
if (this->db->execute(this->db, &hash_id,
|
||||||
|
@ -289,7 +289,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
|
||||||
|
|
||||||
while (e->enumerate(e, &hash))
|
while (e->enumerate(e, &hash))
|
||||||
{
|
{
|
||||||
if (chunk_equals(hash, measurement))
|
if (chunk_equals_const(hash, measurement))
|
||||||
{
|
{
|
||||||
status = SUCCESS;
|
status = SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -133,7 +133,7 @@ METHOD(pts_file_meas_t, check, bool,
|
||||||
{
|
{
|
||||||
while (e->enumerate(e, &hash))
|
while (e->enumerate(e, &hash))
|
||||||
{
|
{
|
||||||
if (chunk_equals(entry->measurement, hash))
|
if (chunk_equals_const(entry->measurement, hash))
|
||||||
{
|
{
|
||||||
status = SUCCESS;
|
status = SUCCESS;
|
||||||
break;
|
break;
|
||||||
|
@ -234,7 +234,7 @@ METHOD(pts_file_meas_t, verify, bool,
|
||||||
|
|
||||||
if (found && !match)
|
if (found && !match)
|
||||||
{
|
{
|
||||||
if (chunk_equals(measurement, entry->measurement))
|
if (chunk_equals_const(measurement, entry->measurement))
|
||||||
{
|
{
|
||||||
match = TRUE;
|
match = TRUE;
|
||||||
DBG2(DBG_PTS, " %#B for '%s' is ok",
|
DBG2(DBG_PTS, " %#B for '%s' is ok",
|
||||||
|
|
|
@ -86,7 +86,7 @@ METHOD(sasl_mechanism_t, process_server, status_t,
|
||||||
DBG1(DBG_CFG, "no shared secret found for '%Y'", this->client);
|
DBG1(DBG_CFG, "no shared secret found for '%Y'", this->client);
|
||||||
return FAILED;
|
return FAILED;
|
||||||
}
|
}
|
||||||
if (!chunk_equals(shared->get_key(shared), password))
|
if (!chunk_equals_const(shared->get_key(shared), password))
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "shared secret for '%Y' does not match", this->client);
|
DBG1(DBG_CFG, "shared secret for '%Y' does not match", this->client);
|
||||||
shared->destroy(shared);
|
shared->destroy(shared);
|
||||||
|
|
|
@ -536,7 +536,7 @@ METHOD(radius_message_t, verify, bool,
|
||||||
/* verify Response-Authenticator */
|
/* verify Response-Authenticator */
|
||||||
if (!hasher->get_hash(hasher, msg, NULL) ||
|
if (!hasher->get_hash(hasher, msg, NULL) ||
|
||||||
!hasher->get_hash(hasher, secret, buf) ||
|
!hasher->get_hash(hasher, secret, buf) ||
|
||||||
!memeq(buf, res_auth, HASH_SIZE_MD5))
|
!memeq_const(buf, res_auth, HASH_SIZE_MD5))
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
|
DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -85,7 +85,7 @@ METHOD(signer_t, verify_signature, bool,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return this->mac->get_mac(this->mac, data, mac) &&
|
return this->mac->get_mac(this->mac, data, mac) &&
|
||||||
memeq(signature.ptr, mac, this->truncation);
|
memeq_const(signature.ptr, mac, this->truncation);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(signer_t, get_key_size, size_t,
|
METHOD(signer_t, get_key_size, size_t,
|
||||||
|
@ -136,4 +136,3 @@ signer_t *mac_signer_create(mac_t *mac, size_t len)
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,7 @@ METHOD(signer_t, verify_signature, bool,
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
return memeq(signature.ptr, sig, signature.len);
|
return memeq_const(signature.ptr, sig, signature.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(signer_t, get_key_size, size_t,
|
METHOD(signer_t, get_key_size, size_t,
|
||||||
|
|
|
@ -256,7 +256,7 @@ static bool verify_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
|
||||||
char buf[this->icv_size];
|
char buf[this->icv_size];
|
||||||
|
|
||||||
return create_icv(this, plain, assoc, iv, buf) &&
|
return create_icv(this, plain, assoc, iv, buf) &&
|
||||||
memeq(buf, icv, this->icv_size);
|
memeq_const(buf, icv, this->icv_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(aead_t, encrypt, bool,
|
METHOD(aead_t, encrypt, bool,
|
||||||
|
|
|
@ -276,7 +276,7 @@ static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
|
||||||
char tmp[this->icv_size];
|
char tmp[this->icv_size];
|
||||||
|
|
||||||
return create_icv(this, assoc, crypt, j, tmp) &&
|
return create_icv(this, assoc, crypt, j, tmp) &&
|
||||||
memeq(tmp, icv, this->icv_size);
|
memeq_const(tmp, icv, this->icv_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(aead_t, encrypt, bool,
|
METHOD(aead_t, encrypt, bool,
|
||||||
|
|
|
@ -187,7 +187,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||||
" %u bytes", em.len, data.len);
|
" %u bytes", em.len, data.len);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
success = memeq(em.ptr, data.ptr, data.len);
|
success = memeq_const(em.ptr, data.ptr, data.len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* IKEv2 and X.509 certificate signatures */
|
{ /* IKEv2 and X.509 certificate signatures */
|
||||||
|
@ -258,7 +258,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||||
goto end_parser;
|
goto end_parser;
|
||||||
}
|
}
|
||||||
hasher->destroy(hasher);
|
hasher->destroy(hasher);
|
||||||
success = memeq(object.ptr, hash.ptr, hash.len);
|
success = memeq_const(object.ptr, hash.ptr, hash.len);
|
||||||
free(hash.ptr);
|
free(hash.ptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -500,4 +500,3 @@ gmp_rsa_public_key_t *gmp_rsa_public_key_load(key_type_t type, va_list args)
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -305,7 +305,7 @@ static bool verify_digest(CMS_ContentInfo *cms, CMS_SignerInfo *si, int hash_oid
|
||||||
}
|
}
|
||||||
hasher->destroy(hasher);
|
hasher->destroy(hasher);
|
||||||
|
|
||||||
if (!chunk_equals(digest, hash))
|
if (!chunk_equals_const(digest, hash))
|
||||||
{
|
{
|
||||||
free(hash.ptr);
|
free(hash.ptr);
|
||||||
DBG1(DBG_LIB, "invalid messageDigest");
|
DBG1(DBG_LIB, "invalid messageDigest");
|
||||||
|
|
|
@ -74,7 +74,7 @@ static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
|
||||||
RSA_PKCS1_PADDING);
|
RSA_PKCS1_PADDING);
|
||||||
if (len != -1)
|
if (len != -1)
|
||||||
{
|
{
|
||||||
valid = chunk_equals(data, chunk_create(buf, len));
|
valid = chunk_equals_const(data, chunk_create(buf, len));
|
||||||
}
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,7 +356,7 @@ static bool verify_mac(hash_algorithm_t hash, chunk_t salt,
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (chunk_equals(mac, calculated))
|
if (chunk_equals_const(mac, calculated))
|
||||||
{
|
{
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -269,7 +269,7 @@ METHOD(enumerator_t, enumerate, bool,
|
||||||
hasher->destroy(hasher);
|
hasher->destroy(hasher);
|
||||||
DBG3(DBG_LIB, "hash: %B", &hash);
|
DBG3(DBG_LIB, "hash: %B", &hash);
|
||||||
|
|
||||||
valid = chunk_equals(chunk, hash);
|
valid = chunk_equals_const(chunk, hash);
|
||||||
free(hash.ptr);
|
free(hash.ptr);
|
||||||
if (!valid)
|
if (!valid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,6 +60,32 @@ START_TEST(test_chunk_equals)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* equals_const
|
||||||
|
*/
|
||||||
|
|
||||||
|
START_TEST(test_chunk_equals_const)
|
||||||
|
{
|
||||||
|
chunk_t chunk = chunk_from_str("chunk");
|
||||||
|
chunk_t chunk_a, chunk_b;
|
||||||
|
|
||||||
|
chunk_a = chunk_empty;
|
||||||
|
chunk_b = chunk_empty;
|
||||||
|
ck_assert(!chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
|
||||||
|
chunk_a = chunk;
|
||||||
|
ck_assert(!chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
chunk_b = chunk;
|
||||||
|
ck_assert(chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
|
||||||
|
chunk_b = chunk_from_str("asdf");
|
||||||
|
ck_assert(!chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
|
||||||
|
chunk_b = chunk_from_str("chunk");
|
||||||
|
ck_assert(chunk_equals_const(chunk_a, chunk_b));
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* chunk_compare test
|
* chunk_compare test
|
||||||
*/
|
*/
|
||||||
|
@ -1013,6 +1039,7 @@ Suite *chunk_suite_create()
|
||||||
|
|
||||||
tc = tcase_create("equals");
|
tc = tcase_create("equals");
|
||||||
tcase_add_test(tc, test_chunk_equals);
|
tcase_add_test(tc, test_chunk_equals);
|
||||||
|
tcase_add_test(tc, test_chunk_equals_const);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("chunk_compare");
|
tc = tcase_create("chunk_compare");
|
||||||
|
|
|
@ -306,6 +306,48 @@ START_TEST(test_memxor_aligned)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* memeq/const
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *a;
|
||||||
|
char *b;
|
||||||
|
size_t n;
|
||||||
|
bool res;
|
||||||
|
} memeq_data[] = {
|
||||||
|
{NULL, NULL, 0, TRUE},
|
||||||
|
{"a", "b", 0, TRUE},
|
||||||
|
{"", "", 1, TRUE},
|
||||||
|
{"abcdefgh", "abcdefgh", 8, TRUE},
|
||||||
|
{"a", "b", 1, FALSE},
|
||||||
|
{"A", "a", 1, FALSE},
|
||||||
|
{"\0a", "\0b", 2, FALSE},
|
||||||
|
{"abc", "abd", 3, FALSE},
|
||||||
|
{"abc", "dbd", 3, FALSE},
|
||||||
|
{"abcdefgh", "abcdffgh", 8, FALSE},
|
||||||
|
{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
|
||||||
|
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, TRUE},
|
||||||
|
{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
|
||||||
|
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyy", 52, FALSE},
|
||||||
|
{"bbcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
|
||||||
|
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, FALSE},
|
||||||
|
};
|
||||||
|
|
||||||
|
START_TEST(test_memeq)
|
||||||
|
{
|
||||||
|
ck_assert(memeq(memeq_data[_i].a, memeq_data[_i].b,
|
||||||
|
memeq_data[_i].n) == memeq_data[_i].res);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_memeq_const)
|
||||||
|
{
|
||||||
|
ck_assert(memeq_const(memeq_data[_i].a, memeq_data[_i].b,
|
||||||
|
memeq_data[_i].n) == memeq_data[_i].res);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* memstr
|
* memstr
|
||||||
*/
|
*/
|
||||||
|
@ -779,6 +821,11 @@ Suite *utils_suite_create()
|
||||||
tcase_add_test(tc, test_memxor_aligned);
|
tcase_add_test(tc, test_memxor_aligned);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("memeq");
|
||||||
|
tcase_add_loop_test(tc, test_memeq, 0, countof(memeq_data));
|
||||||
|
tcase_add_loop_test(tc, test_memeq_const, 0, countof(memeq_data));
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
tc = tcase_create("memstr");
|
tc = tcase_create("memstr");
|
||||||
tcase_add_loop_test(tc, test_memstr, 0, countof(memstr_data));
|
tcase_add_loop_test(tc, test_memstr, 0, countof(memstr_data));
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
|
@ -309,6 +309,19 @@ static inline bool chunk_equals(chunk_t a, chunk_t b)
|
||||||
a.len == b.len && memeq(a.ptr, b.ptr, a.len);
|
a.len == b.len && memeq(a.ptr, b.ptr, a.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two chunks for equality, constant time for cryptographic purposes.
|
||||||
|
*
|
||||||
|
* Note that this function is constant time only for chunks with the same
|
||||||
|
* length, i.e. it does not protect against guessing the length of one of the
|
||||||
|
* chunks.
|
||||||
|
*/
|
||||||
|
static inline bool chunk_equals_const(chunk_t a, chunk_t b)
|
||||||
|
{
|
||||||
|
return a.ptr != NULL && b.ptr != NULL &&
|
||||||
|
a.len == b.len && memeq_const(a.ptr, b.ptr, a.len);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare two chunks (given as pointers) for equality (useful as callback),
|
* Compare two chunks (given as pointers) for equality (useful as callback),
|
||||||
* NULL chunks are never equal.
|
* NULL chunks are never equal.
|
||||||
|
|
|
@ -109,6 +109,25 @@ void memwipe_noinline(void *ptr, size_t n)
|
||||||
memwipe_inline(ptr, n);
|
memwipe_inline(ptr, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
bool memeq_const(const void *x, const void *y, size_t len)
|
||||||
|
{
|
||||||
|
const u_char *a, *b;
|
||||||
|
u_int bad = 0;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
a = (const u_char*)x;
|
||||||
|
b = (const u_char*)y;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
bad |= a[i] != b[i];
|
||||||
|
}
|
||||||
|
return !bad;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Described in header.
|
* Described in header.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -184,6 +184,11 @@ static inline bool memeq(const void *x, const void *y, size_t len)
|
||||||
return memcmp(x, y, len) == 0;
|
return memcmp(x, y, len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as memeq(), but with a constant runtime, safe for cryptographic use.
|
||||||
|
*/
|
||||||
|
bool memeq_const(const void *x, const void *y, size_t len);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calling memcpy() with NULL pointers, even with n == 0, results in undefined
|
* Calling memcpy() with NULL pointers, even with n == 0, results in undefined
|
||||||
* behavior according to the C standard. This version is guaranteed to not
|
* behavior according to the C standard. This version is guaranteed to not
|
||||||
|
|
|
@ -641,7 +641,7 @@ static status_t process_finished(private_tls_peer_t *this, bio_reader_t *reader)
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (!chunk_equals(received, chunk_from_thing(buf)))
|
if (!chunk_equals_const(received, chunk_from_thing(buf)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received server finished invalid");
|
DBG1(DBG_TLS, "received server finished invalid");
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||||
|
|
|
@ -607,7 +607,7 @@ static status_t process_finished(private_tls_server_t *this,
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
|
||||||
return NEED_MORE;
|
return NEED_MORE;
|
||||||
}
|
}
|
||||||
if (!chunk_equals(received, chunk_from_thing(buf)))
|
if (!chunk_equals_const(received, chunk_from_thing(buf)))
|
||||||
{
|
{
|
||||||
DBG1(DBG_TLS, "received client finished invalid");
|
DBG1(DBG_TLS, "received client finished invalid");
|
||||||
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
|
||||||
|
|
Loading…
Reference in New Issue