import/impl static ffi infrastructure for crypto
This commit is contained in:
parent
5a94dc3751
commit
05736756ec
|
@ -3,5 +3,6 @@
|
|||
.\#*
|
||||
*.zo
|
||||
*.dep
|
||||
*.so
|
||||
/crossfire/compiled/
|
||||
/crossfire/doc/
|
||||
|
|
10
Makefile
10
Makefile
|
@ -15,7 +15,7 @@
|
|||
# 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
|
||||
.PHONY: all check clean monocypher
|
||||
|
||||
all:
|
||||
raco setup ./crossfire/
|
||||
|
@ -24,4 +24,10 @@ check:
|
|||
raco check-requires -- crossfire/*.rkt
|
||||
|
||||
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