Skip to content

Commit

Permalink
remove bias
Browse files Browse the repository at this point in the history
  • Loading branch information
henrygab committed Jul 24, 2023
1 parent d1630b5 commit b6a7db8
Showing 1 changed file with 47 additions and 7 deletions.
54 changes: 47 additions & 7 deletions passgen.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <furi.h>
#include <furi_hal_random.h>
#include <gui/gui.h>
#include <gui/elements.h>
#include <input/input.h>
Expand Down Expand Up @@ -66,11 +67,16 @@ typedef struct {
NotificationApp* notify;
const char* alphabet;
char password[PASSGEN_MAX_LENGTH+1];
int length;
int length; // must be <= PASSGEN_MAX_LENGTH
int level;
} PassGen;

void state_free(PassGen* app) {
// NOTE: would have preferred if a "safe" memset() was available...
// but, since cannot prevent optimization from removing
// memset(), fill with random data instead.
furi_hal_random_fill_buf((void*)(app->password), PASSGEN_MAX_LENGTH);

gui_remove_view_port(app->gui, app->view_port);
furi_record_close(RECORD_GUI);
view_port_free(app->view_port);
Expand Down Expand Up @@ -128,6 +134,7 @@ void build_alphabet(PassGen* app)

PassGen* state_init() {
PassGen* app = malloc(sizeof(PassGen));
_Static_assert(8 <= PASSGEN_MAX_LENGTH, "app->length must be set <= PASSGEN_MAX_LENGTH");
app->length = 8;
app->level = 2;
build_alphabet(app);
Expand All @@ -146,13 +153,46 @@ PassGen* state_init() {

void generate(PassGen* app)
{
int hi = strlen(app->alphabet);
for (int i=0; i<app->length; i++)
{
int x = rand() % hi;
app->password[i]=app->alphabet[x];
memset(app->password, 0, PASSGEN_MAX_LENGTH+1);

int char_option_count = strlen(app->alphabet);
if (char_option_count < 0) {
return;
}

// determine largest character value that avoids bias
char ceil = CHAR_MAX - (CHAR_MAX % char_option_count) - 1;

// iteratively fill the password buffer with random values
// then keep only values that are in-range (no bias)
void* remaining_buffer = app->password;
size_t remaining_length = (app->length * sizeof(char));

while (remaining_length != 0) {
// fewer calls to hardware TRNG is more efficient
furi_hal_random_fill_buf(remaining_buffer, remaining_length);

// keep only values that are in-range (no bias)
char* target = remaining_buffer;
char* source = remaining_buffer;
size_t valid_count = 0;

for (size_t i = 0; i < remaining_length; i++) {
int v = *source;
// if the generated random value is in range, keep it
if (v < ceil) {
v %= char_option_count;
*target = app->alphabet[v];
// increment target pointer and count of valid items found
target++;
valid_count++;
}
// always increment the source pointer
source++;
}
remaining_length -= valid_count;
remaining_buffer = target;
}
app->password[app->length] = '\0';
}

void update_password(PassGen* app, bool vibro)
Expand Down

0 comments on commit b6a7db8

Please sign in to comment.