import/impl static ffi infrastructure for crypto
This commit is contained in:
parent
5a94dc3751
commit
05736756ec
|
@ -3,5 +3,6 @@
|
||||||
.\#*
|
.\#*
|
||||||
*.zo
|
*.zo
|
||||||
*.dep
|
*.dep
|
||||||
|
*.so
|
||||||
/crossfire/compiled/
|
/crossfire/compiled/
|
||||||
/crossfire/doc/
|
/crossfire/doc/
|
||||||
|
|
10
Makefile
10
Makefile
|
@ -15,7 +15,7 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all check clean monocypher
|
||||||
|
|
||||||
all:
|
all:
|
||||||
raco setup ./crossfire/
|
raco setup ./crossfire/
|
||||||
|
@ -24,4 +24,10 @@ check:
|
||||||
raco check-requires -- crossfire/*.rkt
|
raco check-requires -- crossfire/*.rkt
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) -r crossfire/doc crossfire/compiled crossfire/scribblings/compiled
|
$(RM) -r crossfire/doc crossfire/compiled crossfire/scribblings/compiled lib/
|
||||||
|
|
||||||
|
monocypher: lib/monocypher.so
|
||||||
|
|
||||||
|
lib/monocypher.so: /usr/include/monocypher/monocypher.c /usr/include/monocypher/monocypher-ed25519.c
|
||||||
|
[ -d lib ] || mkdir lib
|
||||||
|
$(CC) -o $@ -O3 -pipe -shared $^
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#lang racket/base
|
||||||
|
;; crossfire: distributed brute force infrastructure
|
||||||
|
;;
|
||||||
|
;; Copyright (C) 2020 haskal
|
||||||
|
;;
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU Affero General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
;;
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU Affero General Public License for more details.
|
||||||
|
;;
|
||||||
|
;; You should have received a copy of the GNU Affero General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
(require ffi/vector ffi/unsafe racket/random
|
||||||
|
"static-support.rkt"
|
||||||
|
(for-syntax racket/base racket/string racket/syntax)
|
||||||
|
(only-in racket/contract provide/contract)
|
||||||
|
;; MATTHIAS
|
||||||
|
;; WHY
|
||||||
|
(rename-in racket/contract [-> contract:->]))
|
||||||
|
|
||||||
|
;; why not use the crypto package?
|
||||||
|
;; this needs to work in a static binary, and potentially without any crypto libraries available to
|
||||||
|
;; link for the agent
|
||||||
|
;; therefore we support monocypher via statically exported functions or by dynamic linking
|
||||||
|
|
||||||
|
;; thanks iitalics uwu
|
||||||
|
(define ((bytes-len/c len) bs)
|
||||||
|
(and bytes? bs) (= len (bytes-length bs)))
|
||||||
|
|
||||||
|
(define monocypher (ffi-lib/runtime "monocypher"))
|
||||||
|
|
||||||
|
(define-syntax (define/ffi stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ name type)
|
||||||
|
(with-syntax ([c-name
|
||||||
|
(datum->syntax
|
||||||
|
stx (string-replace (symbol->string (syntax->datum #'name)) "-" "_"))])
|
||||||
|
#'(define name (get-ffi-obj/runtime c-name monocypher type)))]))
|
||||||
|
|
||||||
|
(define/ffi crypto-sign-public-key
|
||||||
|
(_fun (pubkey : (_u8vector o 32)) (seckey : _u8vector) -> _void -> pubkey))
|
||||||
|
(provide/contract [crypto-sign-public-key (contract:-> (bytes-len/c 32) (bytes-len/c 32))])
|
|
@ -0,0 +1,80 @@
|
||||||
|
#lang racket/base
|
||||||
|
;; crossfire: distributed brute force infrastructure
|
||||||
|
;;
|
||||||
|
;; Copyright (C) 2020 haskal
|
||||||
|
;;
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU Affero General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
;;
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU Affero General Public License for more details.
|
||||||
|
;;
|
||||||
|
;; You should have received a copy of the GNU Affero General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
(require ffi/unsafe racket/bool racket/string)
|
||||||
|
(provide get-ffi-obj/static static-ffi-available?
|
||||||
|
ffi-lib/runtime get-ffi-obj/runtime)
|
||||||
|
|
||||||
|
;; this module provides utility functions for interacting with static ffi tables provided by an
|
||||||
|
;; embedding runtime, and for deferring either to the regular dynamic linking ffi or the static ffi
|
||||||
|
;; as the current runtime allows
|
||||||
|
;;
|
||||||
|
;; a static ffi table is a C array of structs of string and uintptr_t that define symbol exports
|
||||||
|
;; from an embedding runtime that is statically compiled (and therefore has no other usual dynamic
|
||||||
|
;; symbol table)
|
||||||
|
;;
|
||||||
|
;; applications compiled with static glibc libdl can actually still link in dynamic libraries, but
|
||||||
|
;; only if the same glibc version is available as a dynamic library during runtime. to avoid making
|
||||||
|
;; any runtime assumptions, i have created static ffi infrastructure that allows ffi calls into
|
||||||
|
;; statically compiled code exported by the embedding runtime
|
||||||
|
|
||||||
|
;; the embedding runtime provides a table in this format
|
||||||
|
(define _fun-opaque (_cpointer 'static-ffi:fun-opaque))
|
||||||
|
(define-cstruct _static-table ([name _string] [fun _fun-opaque]))
|
||||||
|
|
||||||
|
;; checks if the current runtime provides a static ffi table
|
||||||
|
(define (static-ffi-available?)
|
||||||
|
(with-handlers ([exn? (lambda (ex) #f)])
|
||||||
|
(dynamic-require ''#%static-ffi 'table)
|
||||||
|
#t))
|
||||||
|
|
||||||
|
;; try to load a library dynamically, but if dynamic linking is not available return #f
|
||||||
|
;; the result can be used in get-ffi-obj/runtime
|
||||||
|
(define (ffi-lib/runtime path [version #f])
|
||||||
|
(define fail (if (static-ffi-available?) (lambda () #f) #f))
|
||||||
|
(ffi-lib path version #:fail fail))
|
||||||
|
|
||||||
|
;; try to load an ffi object dynamically, but if lib is #f and static ffi is available, retrieve
|
||||||
|
;; the object from the static ffi table
|
||||||
|
(define (get-ffi-obj/runtime name lib type)
|
||||||
|
(when (and (false? lib) (not (static-ffi-available?)))
|
||||||
|
(error "no lib provided and static ffi not available"))
|
||||||
|
(if (false? lib)
|
||||||
|
(get-ffi-obj/static name type)
|
||||||
|
(get-ffi-obj name lib type)))
|
||||||
|
|
||||||
|
;; retrieve an object of a given name and type from the static ffi table, if it exists
|
||||||
|
;; otherwise raise error
|
||||||
|
(define (get-ffi-obj/static name type)
|
||||||
|
;; magic primitives
|
||||||
|
(define table-addr (dynamic-require ''#%static-ffi 'table))
|
||||||
|
(define table-size (dynamic-require ''#%static-ffi 'table-size))
|
||||||
|
|
||||||
|
(define table (cast table-addr _uint64 _static-table-pointer))
|
||||||
|
|
||||||
|
(define ent
|
||||||
|
(for/fold ([res #f]) ([i (in-range table-size)])
|
||||||
|
(define ent (ptr-ref table _static-table i))
|
||||||
|
(if (string=? (static-table-name ent) name)
|
||||||
|
(static-table-fun ent)
|
||||||
|
res)))
|
||||||
|
|
||||||
|
(when (false? ent)
|
||||||
|
(error "static ffi entry not found" name))
|
||||||
|
|
||||||
|
(cast ent _fun-opaque type))
|
|
@ -0,0 +1,3 @@
|
||||||
|
*.o
|
||||||
|
*.zo
|
||||||
|
/run
|
|
@ -0,0 +1,52 @@
|
||||||
|
# crossfire: distributed brute force infrastructure
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020 haskal
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
.PHONY: all clean
|
||||||
|
|
||||||
|
APP_NAME=run
|
||||||
|
RKT_NAME=$(APP_NAME).rkt
|
||||||
|
|
||||||
|
MONOCYPHER_INC=/usr/include/monocypher
|
||||||
|
|
||||||
|
####################################################################################################
|
||||||
|
|
||||||
|
LIBS=-ldl -lm
|
||||||
|
# for musl
|
||||||
|
#LIBS=-lffi -lucontext
|
||||||
|
|
||||||
|
all: $(APP_NAME)
|
||||||
|
|
||||||
|
# main build
|
||||||
|
$(APP_NAME): main_bc.c app.o monocypher.o monocypher-ed25519.o
|
||||||
|
$(CC) -o $@ -pipe -fPIC -O3 -DAPP_NAME='"$(APP_NAME)"' -I$(MONOCYPHER_INC) -static $^ \
|
||||||
|
-lracket3m -lrktio $(LIBS)
|
||||||
|
|
||||||
|
monocypher.o: $(MONOCYPHER_INC)/monocypher.c
|
||||||
|
$(CC) -o $@ -pipe -fPIC -O3 -I$(MONOCYPHER_INC) -c $^
|
||||||
|
monocypher-ed25519.o: $(MONOCYPHER_INC)/monocypher-ed25519.c
|
||||||
|
$(CC) -o $@ -pipe -fPIC -O3 -I$(MONOCYPHER_INC) -c $^
|
||||||
|
|
||||||
|
# this is faster than --c-mods by a lot
|
||||||
|
# it's less portable but like, we're containerized already so it'll work
|
||||||
|
app.o: app.zo
|
||||||
|
$(LD) -r -b binary $< -o $@
|
||||||
|
|
||||||
|
app.zo: $(RKT_NAME)
|
||||||
|
raco ctool --mods $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(APP_NAME) *.zo *.o
|
|
@ -0,0 +1,112 @@
|
||||||
|
// crossfire: distributed brute force infrastructure
|
||||||
|
//
|
||||||
|
// Copyright (C) 2020 haskal
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#define MZ_PRECISE_GC
|
||||||
|
|
||||||
|
#include <racket/scheme.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <monocypher.h>
|
||||||
|
|
||||||
|
extern const char _binary_app_zo_start;
|
||||||
|
extern const char _binary_app_zo_end;
|
||||||
|
|
||||||
|
// ffi defs
|
||||||
|
typedef struct {
|
||||||
|
const char* name;
|
||||||
|
uintptr_t ptr;
|
||||||
|
} ffi_ent;
|
||||||
|
|
||||||
|
#define STR(x) #x
|
||||||
|
#define FFI_ENT(name) {STR(name), (uintptr_t) name}
|
||||||
|
|
||||||
|
static const ffi_ent ffi_table[] = {
|
||||||
|
FFI_ENT(crypto_sign_public_key)
|
||||||
|
};
|
||||||
|
static const size_t ffi_table_size = sizeof(ffi_table)/sizeof(ffi_ent);
|
||||||
|
|
||||||
|
// setup ffi table to be passed to racket
|
||||||
|
static void bc_setup_ffi_table(Scheme_Env* parent) {
|
||||||
|
Scheme_Env* mod = NULL;
|
||||||
|
Scheme_Object* table = NULL;
|
||||||
|
Scheme_Object* table_size = NULL;
|
||||||
|
|
||||||
|
MZ_GC_DECL_REG(4);
|
||||||
|
MZ_GC_VAR_IN_REG(0, parent);
|
||||||
|
MZ_GC_VAR_IN_REG(1, mod);
|
||||||
|
MZ_GC_VAR_IN_REG(2, table);
|
||||||
|
MZ_GC_VAR_IN_REG(3, table_size);
|
||||||
|
MZ_GC_REG();
|
||||||
|
|
||||||
|
mod = scheme_primitive_module(scheme_intern_symbol("#%static-ffi"), parent);
|
||||||
|
table = scheme_make_integer(&ffi_table[0]);
|
||||||
|
scheme_add_global("table", table, mod);
|
||||||
|
table_size = scheme_make_integer(ffi_table_size);
|
||||||
|
scheme_add_global("table-size", table_size, mod);
|
||||||
|
scheme_finish_primitive_module(mod);
|
||||||
|
|
||||||
|
MZ_GC_UNREG();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int run_bc(Scheme_Env* e, int argc, char* argv[]) {
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
volatile mz_jmp_buf* save;
|
||||||
|
mz_jmp_buf fresh;
|
||||||
|
int rv = 0;
|
||||||
|
size_t load_size = ((uintptr_t) &_binary_app_zo_end) - ((uintptr_t) &_binary_app_zo_start);
|
||||||
|
Scheme_Object* l = NULL;
|
||||||
|
Scheme_Object* a[2] = { NULL, NULL };
|
||||||
|
|
||||||
|
// gc setup
|
||||||
|
MZ_GC_DECL_REG(5);
|
||||||
|
MZ_GC_VAR_IN_REG(0, e);
|
||||||
|
MZ_GC_VAR_IN_REG(1, l);
|
||||||
|
MZ_GC_ARRAY_VAR_IN_REG(2, a, 2);
|
||||||
|
MZ_GC_REG();
|
||||||
|
|
||||||
|
bc_setup_ffi_table(e);
|
||||||
|
|
||||||
|
scheme_register_embedded_load(load_size, &_binary_app_zo_start);
|
||||||
|
scheme_embedded_load(load_size, &_binary_app_zo_start, 1);
|
||||||
|
|
||||||
|
l = scheme_make_null();
|
||||||
|
l = scheme_make_pair(scheme_intern_symbol(APP_NAME), l);
|
||||||
|
l = scheme_make_pair(scheme_intern_symbol("quote"), l);
|
||||||
|
|
||||||
|
a[0] = l;
|
||||||
|
a[1] = scheme_false;
|
||||||
|
|
||||||
|
save = scheme_current_thread->error_buf;
|
||||||
|
scheme_current_thread->error_buf = &fresh;
|
||||||
|
|
||||||
|
if (scheme_setjmp(scheme_error_buf)) {
|
||||||
|
fprintf(stderr, "[WRAPPER] encountered top-level racket error. aborting\n");
|
||||||
|
rv = -1;
|
||||||
|
} else {
|
||||||
|
scheme_dynamic_require(2, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
scheme_current_thread->error_buf = (mz_jmp_buf*) save;
|
||||||
|
MZ_GC_UNREG();
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
return scheme_main_setup(1, run_bc, argc, argv);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#lang racket/base
|
||||||
|
;; crossfire: distributed brute force infrastructure
|
||||||
|
;;
|
||||||
|
;; Copyright (C) 2020 haskal
|
||||||
|
;;
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU Affero General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
;;
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU Affero General Public License for more details.
|
||||||
|
;;
|
||||||
|
;; You should have received a copy of the GNU Affero General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
(require "../crossfire/not-crypto.rkt")
|
||||||
|
|
||||||
|
(crypto-sign-public-key #"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
|
Loading…
Reference in New Issue