aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--LICENSE2
-rw-r--r--README4
-rw-r--r--config.mk10
-rw-r--r--libar2simplified.714
-rw-r--r--libar2simplified_decode_r.c15
-rw-r--r--libar2simplified_init_context.36
-rw-r--r--libar2simplified_init_context.c72
7 files changed, 76 insertions, 47 deletions
diff --git a/LICENSE b/LICENSE
index 63ecdfe..e669c54 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
ISC License
-© 2022 Mattias Andrée <m@maandree.se>
+© 2022, 2023, 2026 Mattias Andrée <m@maandree.se>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/README b/README
index 647e9ad..1bd8b65 100644
--- a/README
+++ b/README
@@ -2,8 +2,8 @@ NAME
libar2simplified - Simplified interface for libar2
DESCRIPTION
- libar2simplified is façade for the libar2 C library that
- implements the family of Argon2 key derivation function,
+ libar2simplified is a façade for the libar2 C library that
+ implements the family of Argon2 key derivation functions,
including Argon2d, Argon2i, and Argon2id, as well as
Argon2ds which was not part of the submission to the
Password Hashing Competition of 2013, which Argon2 won in
diff --git a/config.mk b/config.mk
index 5445241..310da09 100644
--- a/config.mk
+++ b/config.mk
@@ -3,6 +3,12 @@ MANPREFIX = $(PREFIX)/share/man
CC = cc
+COMMON_SANITIZE = -fsanitize=alignment,shift,signed-integer-overflow,object-size,null,undefined,bounds,address
+CLANG_SANITIZE = -O1 $(COMMON_SANITIZE),cfi -flto -fvisibility=hidden -fno-sanitize-trap=cfi
+GCC_SANITIZE = -O1 $(COMMON_SANITIZE)
+#SANITIZE = $(CLANG_SANITIZE)
+#SANITIZE = $(GCC_SANITIZE)
+
CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
-CFLAGS = -std=c11 -Wall -g -pthread
-LDFLAGS = -lar2 -lblake -pthread
+CFLAGS = $(SANITIZE) -std=c11 -Wall -g -pthread
+LDFLAGS = $(SANITIZE) -lar2 -lblake -pthread
diff --git a/libar2simplified.7 b/libar2simplified.7
index 809ba1e..0a156e1 100644
--- a/libar2simplified.7
+++ b/libar2simplified.7
@@ -1,21 +1,21 @@
-.TH LIBAR2SIMPLIFIED 7 LIBAR2
+.TH LIBAR2SIMPLIFIED 7 LIBAR2SIMPLIFIED
.SH NAME
libar2simplified - Simplified interface for libar2
.SH DESCRIPTION
.B libar2simplified
-is façade for the
+is a façade for the
.BR libar2 (7)
C library that implements the family of Argon2 key
-derivation function, including Argon2d, Argon2i, and
+derivation functions, including Argon2d, Argon2i, and
Argon2id, as well as Argon2ds which was not part of
the submission to the Password Hashing Competition
of 2013, which Argon2 won in 2015. As a key derivation
function, Argon2 is well-suited for cryptographically
-hashing (one-way encrypting) passwords. Where as the
+hashing (one-way encrypting) passwords. Whereas the
.BR libar2 (7)
-library is suitable in any code-base, as long as it
-some standard C functions are avaible, since it does
+library is suitable for any code-base, as long as it has
+some standard C functions available, since it does
not interact with the operating system,
.B libar2simplified
can only be used in fully hosted environments, since
@@ -40,7 +40,7 @@ output the password hash in binary without prepending
the parameters.
.SH SEE ALSO
-.BR libar2simplified (7),
+.BR libar2 (7),
.BR libar2simplified_crypt (3),
.BR libar2simplified_decode (3),
.BR libar2simplified_decode_r (3),
diff --git a/libar2simplified_decode_r.c b/libar2simplified_decode_r.c
index 545ecde..fa37aac 100644
--- a/libar2simplified_decode_r.c
+++ b/libar2simplified_decode_r.c
@@ -47,7 +47,8 @@ random_salt(char *out, size_t n, int (*random_byte_generator)(char *out, size_t
ssize_t r;
# ifdef AT_RANDOM
uintptr_t raddr_;
- uint16_t *raddr;
+ const unsigned char *raddr;
+ size_t j;
# endif
#endif
@@ -70,15 +71,9 @@ random_salt(char *out, size_t n, int (*random_byte_generator)(char *out, size_t
#if defined(__linux__) && defined(AT_RANDOM)
raddr_ = (uintptr_t)getauxval(AT_RANDOM);
if (raddr_) {
- raddr = (void *)raddr_;
- seed ^= (unsigned)raddr[0];
- seed ^= (unsigned)raddr[1];
- seed ^= (unsigned)raddr[2];
- seed ^= (unsigned)raddr[3];
- seed ^= (unsigned)raddr[4];
- seed ^= (unsigned)raddr[5];
- seed ^= (unsigned)raddr[6];
- seed ^= (unsigned)raddr[7];
+ raddr = (const void *)raddr_;
+ for (j = 0; j < 16; j++)
+ ((unsigned char *)&seed)[j % sizeof(seed)] ^= raddr[j];
}
#endif
srand(seed);
diff --git a/libar2simplified_init_context.3 b/libar2simplified_init_context.3
index c190c86..de22fac 100644
--- a/libar2simplified_init_context.3
+++ b/libar2simplified_init_context.3
@@ -23,10 +23,10 @@ function, provided via the
parameter, with all auto-erase options
turned off.
.PP
-This function provides a dynamic memory
+This function provides dynamic memory
management functions that erase memory
-before it is deallocated. It also also
-provides a multi-threading support using
+before it is deallocated. It also
+provides multi-threading support using
a thread pool.
.PP
This function is used internally by the
diff --git a/libar2simplified_init_context.c b/libar2simplified_init_context.c
index 9dcbfb0..814e182 100644
--- a/libar2simplified_init_context.c
+++ b/libar2simplified_init_context.c
@@ -2,6 +2,7 @@
#include "common.h"
#include <pthread.h>
#include <semaphore.h>
+#include <stdatomic.h>
struct user_data;
@@ -11,7 +12,7 @@ struct thread_data {
struct user_data *master;
pthread_t thread;
sem_t semaphore;
- int error;
+ _Atomic int error;
void (*function)(void *data);
void *function_input;
};
@@ -50,14 +51,15 @@ alignedalloc(size_t num, size_t size, size_t extra, size_t alignment)
static void *
allocate(size_t num, size_t size, size_t alignment, struct libar2_context *ctx)
{
- size_t pad = (alignment - ((2 * sizeof(size_t)) & (alignment - 1))) & (alignment - 1);
- char *ptr = alignedalloc(num, size, pad + 2 * sizeof(size_t), alignment);
+ size_t extra = 2 * sizeof(size_t);
+ size_t pad = -extra & (alignment - 1);
+ char *ptr = alignedalloc(num, size, pad + extra, alignment);
if (ptr) {
- ptr = &ptr[pad];
- *(size_t *)ptr = pad;
- ptr = &ptr[sizeof(size_t)];
- *(size_t *)ptr = num * size;
- ptr = &ptr[sizeof(size_t)];
+ ptr += pad;
+ memcpy(ptr, &pad, sizeof(size_t));
+ ptr += sizeof(size_t);
+ memcpy(ptr, &(size_t){num * size}, sizeof(size_t));
+ ptr += sizeof(size_t);
}
(void) ctx;
return ptr;
@@ -68,10 +70,13 @@ static void
deallocate(void *ptr, struct libar2_context *ctx)
{
char *p = ptr;
+ size_t size, pad;
p -= sizeof(size_t);
- libar2_erase(ptr, *(size_t *)p);
+ memcpy(&size, p, sizeof(size_t));
p -= sizeof(size_t);
- p -= *(size_t *)p;
+ memcpy(&pad, p, sizeof(size_t));
+ p -= pad;
+ libar2_erase(p, size + pad + 2u * sizeof(size_t));
free(p);
(void) ctx;
}
@@ -81,31 +86,44 @@ static void *
thread_loop(void *data_)
{
struct thread_data *data = data_;
+ void (*function)(void *data);
+ void *function_input;
int err;
for (;;) {
if (sem_wait(&data->semaphore)) {
if (errno == EINTR)
continue;
- data->error = errno;
+ atomic_store(&data->error, errno);
return NULL;
}
- if (!data->function) {
- data->error = ENOTRECOVERABLE;
+ err = pthread_mutex_lock(&data->master->mutex);
+ if (err) {
+ atomic_store(&data->error, err);
+ return NULL;
+ }
+ function = data->function;
+ function_input = data->function_input;
+ if (!function) {
+ atomic_store(&data->error, ENOTRECOVERABLE);
+ pthread_mutex_unlock(&data->master->mutex);
return NULL;
}
- data->function(data->function_input);
+ pthread_mutex_unlock(&data->master->mutex);
+
+ function(function_input);
err = pthread_mutex_lock(&data->master->mutex);
if (err) {
- data->error = err;
+ atomic_store(&data->error, err);
return NULL;
}
data->master->resting[data->index / 64] |= (uint_least64_t)1 << (data->index % 64);
+
pthread_mutex_unlock(&data->master->mutex);
if (sem_post(&data->master->semaphore)) {
- data->error = errno;
+ atomic_store(&data->error, errno);
return NULL;
}
}
@@ -124,15 +142,17 @@ run_thread(size_t index, void (*function)(void *arg), void *arg, struct libar2_c
return -1;
}
data->resting[index / 64] ^= (uint_least64_t)1 << (index % 64);
- pthread_mutex_unlock(&data->mutex);
- if (data->threads[index].error) {
- errno = data->threads[index].error;
+ err = atomic_load(&data->threads[index].error);
+ if (err) {
+ pthread_mutex_unlock(&data->mutex);
+ errno = err;
return -1;
}
data->threads[index].function = function;
data->threads[index].function_input = arg;
+ pthread_mutex_unlock(&data->mutex);
if (sem_post(&data->threads[index].semaphore))
return -1;
@@ -145,15 +165,16 @@ destroy_thread_pool(struct libar2_context *ctx)
{
struct user_data *data = ctx->user_data;
size_t i;
- int ret = 0;
+ int err, ret = 0;
for (i = data->nthreads; i--;)
if (run_thread(i, pthread_exit, NULL, ctx))
return -1;
for (i = data->nthreads; i--;) {
pthread_join(data->threads[i].thread, NULL);
sem_destroy(&data->threads[i].semaphore);
- if (data->threads[i].error)
- ret = data->threads[i].error;
+ err = atomic_load(&data->threads[i].error);
+ if (err)
+ ret = err;
}
sem_destroy(&data->semaphore);
pthread_mutex_destroy(&data->mutex);
@@ -244,6 +265,7 @@ init_thread_pool(size_t desired, size_t *createdp, struct libar2_context *ctx)
for (i = 0; i < data->nthreads; i++) {
memset(&data->threads[i], 0, sizeof(data->threads[i]));
+ atomic_init(&data->threads[i].error, 0);
data->threads[i].master = data;
data->threads[i].index = i;
data->resting[i / 64] |= (uint_least64_t)1 << (i % 64);
@@ -290,6 +312,11 @@ await_threads(size_t *indices, size_t n, size_t require, struct libar2_context *
memset(data->joined, 0, (data->nthreads + 63) / 64 * sizeof(*data->joined));
+ err = pthread_mutex_lock(&data->mutex);
+ if (err) {
+ errno = err;
+ return 0;
+ }
for (i = 0; i < data->nthreads; i += 64) {
for (;;) {
one = data->resting[i / 64];
@@ -302,6 +329,7 @@ await_threads(size_t *indices, size_t n, size_t require, struct libar2_context *
indices[ret - 1] = i + lb(one);
}
}
+ pthread_mutex_unlock(&data->mutex);
for (;;) {
if (ret < require) {