mirror of
https://github.com/urbit/shrub.git
synced 2024-12-25 13:04:17 +03:00
argon2
This commit is contained in:
parent
fe1375ef6b
commit
6fdc65dea6
@ -16,7 +16,7 @@ let
|
||||
|
||||
urcrypt = import ./urcrypt {
|
||||
inherit pkgs ge-additions;
|
||||
inherit (deps) ed25519;
|
||||
inherit (deps) ed25519 argon2;
|
||||
};
|
||||
|
||||
libaes_siv = import ./libaes_siv {
|
||||
|
@ -1,9 +1,9 @@
|
||||
{ pkgs, ge-additions, ed25519 }:
|
||||
{ pkgs, ed25519, ge-additions, argon2 }:
|
||||
|
||||
pkgs.stdenv.mkDerivation rec {
|
||||
name = "urcrypt";
|
||||
builder = ./builder.sh;
|
||||
src = ../../../pkg/urcrypt;
|
||||
|
||||
buildInputs = [ pkgs.openssl ed25519 ge-additions ];
|
||||
buildInputs = [ pkgs.openssl ed25519 ge-additions argon2 ];
|
||||
}
|
||||
|
@ -2,104 +2,124 @@
|
||||
**
|
||||
*/
|
||||
#include "all.h"
|
||||
|
||||
#include <argon2.h>
|
||||
#include <urcrypt.h>
|
||||
|
||||
/* helpers
|
||||
*/
|
||||
|
||||
int argon2_alloc(uint8_t** output, size_t bytes)
|
||||
static c3_t
|
||||
_cqear_unpack_word(c3_w *out, u3_atom in)
|
||||
{
|
||||
*output = u3a_malloc(bytes);
|
||||
return (NULL != output);
|
||||
if ( u3r_met(5, in) > 1 ) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
*out = u3r_word(0, in);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void argon2_free(uint8_t* memory, size_t bytes)
|
||||
static c3_t
|
||||
_cqear_unpack_size(size_t *out, u3_atom in)
|
||||
{
|
||||
u3a_free(memory);
|
||||
c3_w out_w;
|
||||
if ( _cqear_unpack_word(&out_w, in) ) {
|
||||
*out = out_w;
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static c3_t
|
||||
_cqear_unpack_type(urcrypt_argon2_type *out, u3_atom in)
|
||||
{
|
||||
switch ( in ) {
|
||||
default:
|
||||
return 0;
|
||||
case c3__d:
|
||||
*out = urcrypt_argon2_d;
|
||||
return 1;
|
||||
case c3__i:
|
||||
*out = urcrypt_argon2_i;
|
||||
return 1;
|
||||
case c3__id:
|
||||
*out = urcrypt_argon2_id;
|
||||
return 1;
|
||||
case c3__u:
|
||||
*out = urcrypt_argon2_u;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static c3_y*
|
||||
_cqear_unpack_bytes(size_t size, u3_atom in)
|
||||
{
|
||||
c3_y* out = u3a_malloc(size);
|
||||
u3r_bytes(0, (c3_w) size, out, in);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* functions
|
||||
*/
|
||||
|
||||
u3_noun
|
||||
u3qe_argon2( // configuration params,
|
||||
static u3_atom
|
||||
_cqe_argon2( // configuration params,
|
||||
u3_atom out, u3_atom type, u3_atom version,
|
||||
u3_atom threads, u3_atom mem_cost, u3_atom time_cost,
|
||||
u3_atom wik, u3_atom key, u3_atom wix, u3_atom extra,
|
||||
// input params
|
||||
u3_atom wid, u3_atom dat, u3_atom wis, u3_atom sat )
|
||||
{
|
||||
c3_assert( _(u3a_is_cat(out)) && _(u3a_is_cat(type)) &&
|
||||
_(u3a_is_cat(version)) && _(u3a_is_cat(threads)) &&
|
||||
_(u3a_is_cat(mem_cost)) && _(u3a_is_cat(time_cost)) &&
|
||||
_(u3a_is_cat(wik)) && _(u3a_is_cat(wix)) &&
|
||||
_(u3a_is_cat(wid)) && _(u3a_is_cat(wis)) );
|
||||
size_t out_sz, key_sz, ex_sz, dat_sz, sat_sz;
|
||||
c3_w ver_w, ted_w, mem_w, tim_w;
|
||||
urcrypt_argon2_type typ_u;
|
||||
|
||||
// flip endianness for argon2
|
||||
key = u3qc_rev(3, wik, key);
|
||||
extra = u3qc_rev(3, wix, extra);
|
||||
dat = u3qc_rev(3, wid, dat);
|
||||
sat = u3qc_rev(3, wis, sat);
|
||||
if ( !(_cqear_unpack_size(&out_sz, out) &&
|
||||
_cqear_unpack_type(&typ_u, type) &&
|
||||
_cqear_unpack_word(&ver_w, version) &&
|
||||
_cqear_unpack_word(&ted_w, threads) &&
|
||||
_cqear_unpack_word(&mem_w, mem_cost) &&
|
||||
_cqear_unpack_word(&tim_w, time_cost) &&
|
||||
_cqear_unpack_size(&key_sz, wik) &&
|
||||
_cqear_unpack_size(&ex_sz, wix) &&
|
||||
_cqear_unpack_size(&dat_sz, wid) &&
|
||||
_cqear_unpack_size(&sat_sz, wis)) ) {
|
||||
u3l_log("%s\r\n", "argon2-punt");
|
||||
return u3_none;
|
||||
}
|
||||
else {
|
||||
u3_atom ret;
|
||||
c3_y *key_y = _cqear_unpack_bytes(key_sz, key),
|
||||
*ex_y = _cqear_unpack_bytes(ex_sz, extra),
|
||||
*dat_y = _cqear_unpack_bytes(dat_sz, dat),
|
||||
*sat_y = _cqear_unpack_bytes(sat_sz, sat),
|
||||
*out_y = u3a_malloc(out_sz);
|
||||
const c3_c* err_c = urcrypt_argon2(
|
||||
typ_u, ver_w, ted_w, mem_w, tim_w,
|
||||
key_sz, key_y,
|
||||
ex_sz, ex_y,
|
||||
dat_sz, dat_y,
|
||||
sat_sz, sat_y,
|
||||
out_sz, out_y);
|
||||
|
||||
// atoms to byte arrays
|
||||
c3_y bytes_key[wik];
|
||||
u3r_bytes(0, wik, bytes_key, key);
|
||||
c3_y bytes_extra[wix];
|
||||
u3r_bytes(0, wix, bytes_extra, extra);
|
||||
c3_y bytes_dat[wid];
|
||||
u3r_bytes(0, wid, bytes_dat, dat);
|
||||
c3_y bytes_sat[wis];
|
||||
u3r_bytes(0, wis, bytes_sat, sat);
|
||||
u3a_free(key_y);
|
||||
u3a_free(ex_y);
|
||||
u3a_free(dat_y);
|
||||
u3a_free(sat_y);
|
||||
|
||||
c3_y outhash[out];
|
||||
argon2_context context = {
|
||||
outhash, // output array, at least [digest length] in size
|
||||
out, // digest length
|
||||
bytes_dat, // password array
|
||||
wid, // password length
|
||||
bytes_sat, // salt array
|
||||
wis, // salt length
|
||||
bytes_key, wik, // optional secret data
|
||||
bytes_extra, wix, // optional associated data
|
||||
time_cost, mem_cost, threads, threads, // performance cost configuration
|
||||
version, // algorithm version
|
||||
argon2_alloc, // custom memory allocation function
|
||||
argon2_free, // custom memory deallocation function
|
||||
ARGON2_DEFAULT_FLAGS // by default only internal memory is cleared
|
||||
};
|
||||
|
||||
int argon_res;
|
||||
switch ( type ) {
|
||||
default:
|
||||
u3l_log("\nunjetted argon2 variant %i\n", type);
|
||||
u3m_bail(c3__exit);
|
||||
break;
|
||||
//
|
||||
case c3__d:
|
||||
argon_res = argon2d_ctx(&context);
|
||||
break;
|
||||
//
|
||||
case c3__i:
|
||||
argon_res = argon2i_ctx(&context);
|
||||
break;
|
||||
//
|
||||
case c3__id:
|
||||
argon_res = argon2id_ctx(&context);
|
||||
break;
|
||||
//
|
||||
case c3__u:
|
||||
argon_res = argon2u_ctx(&context);
|
||||
break;
|
||||
if ( NULL == err_c ) {
|
||||
ret = u3i_bytes(out_sz, out_y);
|
||||
}
|
||||
else {
|
||||
ret = u3_none;
|
||||
u3l_log("argon2-punt: %s\r\n", err_c);
|
||||
}
|
||||
|
||||
if ( ARGON2_OK != argon_res ) {
|
||||
u3l_log("\nargon2 error: %s\n", argon2_error_message(argon_res));
|
||||
u3m_bail(c3__exit);
|
||||
u3a_free(out_y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u3z(key); u3z(extra); u3z(dat); u3z(sat);
|
||||
return u3kc_rev(3, out, u3i_bytes(out, outhash));
|
||||
}
|
||||
|
||||
u3_noun
|
||||
@ -138,7 +158,7 @@
|
||||
return u3m_bail(c3__exit);
|
||||
}
|
||||
else {
|
||||
return u3qe_argon2(out, type, version,
|
||||
return _cqe_argon2(out, type, version,
|
||||
threads, mem_cost, time_cost,
|
||||
wik, key, wix, extra,
|
||||
wid, dat, wis, sat);
|
||||
|
@ -16,7 +16,7 @@ liburcrypt.a: $(SOURCES)
|
||||
liburcrypt.so: $(SOURCES)
|
||||
$(CC) $(CFLAGS) -fPIC -c urcrypt.c -o urcrypt-shared.o
|
||||
$(CC) -shared urcrypt-shared.o -o liburcrypt.so \
|
||||
-led25519 -lge-additions -lssl \
|
||||
-led25519 -lge-additions -lssl -largon2 \
|
||||
-Wl,--no-undefined
|
||||
|
||||
all: liburcrypt.a liburcrypt.so
|
||||
|
@ -249,6 +249,14 @@ _urcrypt_reverse_copy(size_t size, const uint8_t *in, uint8_t *out) {
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
_urcrypt_reverse_alloc(size_t size, const uint8_t *in)
|
||||
{
|
||||
uint8_t *out = urcrypt_malloc(size);
|
||||
_urcrypt_reverse_copy(size, in, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
static void
|
||||
_urcrypt_reverse_inplace(size_t size, uint8_t *ptr) {
|
||||
size_t i, j;
|
||||
@ -572,3 +580,109 @@ urcrypt_aes_cbcc_de(const uint8_t *message,
|
||||
out_length);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_urcrypt_argon2_alloc(uint8_t** output, size_t bytes)
|
||||
{
|
||||
*output = urcrypt_malloc(bytes);
|
||||
return (NULL != output);
|
||||
}
|
||||
|
||||
static void
|
||||
_urcrypt_argon2_free(uint8_t* memory, size_t bytes)
|
||||
{
|
||||
urcrypt_free(memory);
|
||||
}
|
||||
|
||||
// library convention is to have sizes in size_t, but argon2 wants them
|
||||
// in uint32_t, so here's a helper macro for ensuring equivalence.
|
||||
#define SZ_32(s) ( sizeof(size_t) <= sizeof(uint32_t) || s <= 0xFFFFFFFF )
|
||||
|
||||
// returns a constant error message string or NULL for success
|
||||
// (so user doesn't have to call argon2_error_message)
|
||||
const char*
|
||||
urcrypt_argon2(urcrypt_argon2_type type,
|
||||
uint32_t version,
|
||||
uint32_t threads,
|
||||
uint32_t memory_cost,
|
||||
uint32_t time_cost,
|
||||
size_t secret_length,
|
||||
const uint8_t *secret,
|
||||
size_t associated_length,
|
||||
const uint8_t *associated,
|
||||
size_t password_length,
|
||||
const uint8_t *password,
|
||||
size_t salt_length,
|
||||
const uint8_t *salt,
|
||||
size_t out_length,
|
||||
uint8_t *out)
|
||||
{
|
||||
if ( !( SZ_32(secret_length) &&
|
||||
SZ_32(associated_length) &&
|
||||
SZ_32(password_length) &&
|
||||
SZ_32(salt_length) &&
|
||||
SZ_32(out_length) ) ) {
|
||||
return "length > 32 bits";
|
||||
}
|
||||
else {
|
||||
int (*f)(argon2_context*);
|
||||
int result;
|
||||
uint8_t *rsecret, *rassoc, *rpassword, *rsalt;
|
||||
|
||||
switch ( type ) {
|
||||
default:
|
||||
return "unknown type";
|
||||
case urcrypt_argon2_d:
|
||||
f = &argon2d_ctx;
|
||||
break;
|
||||
case urcrypt_argon2_i:
|
||||
f = &argon2i_ctx;
|
||||
break;
|
||||
case urcrypt_argon2_id:
|
||||
f = &argon2id_ctx;
|
||||
break;
|
||||
case urcrypt_argon2_u:
|
||||
f = &argon2u_ctx;
|
||||
break;
|
||||
}
|
||||
|
||||
rsecret = _urcrypt_reverse_alloc(secret_length, secret);
|
||||
rassoc = _urcrypt_reverse_alloc(associated_length, associated);
|
||||
rpassword = _urcrypt_reverse_alloc(password_length, password);
|
||||
rsalt = _urcrypt_reverse_alloc(salt_length, salt);
|
||||
argon2_context context = {
|
||||
out, // output array, at least [digest length] in size
|
||||
out_length, // digest length
|
||||
rpassword, // password array
|
||||
password_length, // password length
|
||||
rsalt, // salt array
|
||||
salt_length, // salt length
|
||||
rsecret, // optional secret data
|
||||
secret_length,
|
||||
rassoc, // optional associated data
|
||||
associated_length,
|
||||
time_cost, // performance cost configuration
|
||||
memory_cost,
|
||||
threads,
|
||||
threads,
|
||||
version, // algorithm version
|
||||
&_urcrypt_argon2_alloc,// custom memory allocation function
|
||||
&_urcrypt_argon2_free, // custom memory deallocation function
|
||||
ARGON2_DEFAULT_FLAGS // by default only internal memory is cleared
|
||||
};
|
||||
|
||||
result = (*f)(&context);
|
||||
urcrypt_free(rsecret);
|
||||
urcrypt_free(rassoc);
|
||||
urcrypt_free(rpassword);
|
||||
urcrypt_free(rsalt);
|
||||
|
||||
if ( ARGON2_OK != result ) {
|
||||
return argon2_error_message(result);
|
||||
}
|
||||
else {
|
||||
_urcrypt_reverse_inplace(out_length, out);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#include <argon2.h>
|
||||
|
||||
typedef void *(*urcrypt_malloc_t)(size_t);
|
||||
typedef void *(*urcrypt_realloc_t)(void*, size_t);
|
||||
typedef void (*urcrypt_free_t)(void*);
|
||||
@ -104,4 +106,27 @@ uint8_t* urcrypt_aes_cbcc_de(const uint8_t *message,
|
||||
const uint8_t ivec[16],
|
||||
size_t *out_length);
|
||||
|
||||
typedef enum urcrypt_argon2_type {
|
||||
urcrypt_argon2_d = 0,
|
||||
urcrypt_argon2_i = 1,
|
||||
urcrypt_argon2_id = 2,
|
||||
urcrypt_argon2_u = 10,
|
||||
} urcrypt_argon2_type;
|
||||
|
||||
const char* urcrypt_argon2(urcrypt_argon2_type type,
|
||||
uint32_t version,
|
||||
uint32_t threads,
|
||||
uint32_t memory_cost,
|
||||
uint32_t time_cost,
|
||||
size_t secret_length,
|
||||
const uint8_t *secret,
|
||||
size_t associated_length,
|
||||
const uint8_t *associated,
|
||||
size_t password_length,
|
||||
const uint8_t *password,
|
||||
size_t salt_length,
|
||||
const uint8_t *salt,
|
||||
size_t out_length,
|
||||
uint8_t *out);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user