140 lines
5.7 KiB
Racket
140 lines
5.7 KiB
Racket
#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/bool racket/random
|
|
"static-support.rkt"
|
|
(for-syntax racket/base racket/string)
|
|
(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 "libmonocypher"))
|
|
|
|
(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)))]))
|
|
|
|
;; public key signatures
|
|
|
|
(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))])
|
|
|
|
(define/ffi crypto-sign
|
|
(_fun (signature : (_u8vector o 64)) (seckey : _u8vector) (pubkey : _u8vector)
|
|
(message : _u8vector) (msgsize : _size = (u8vector-length message))
|
|
-> _void -> signature))
|
|
(provide/contract [crypto-sign (contract:-> (bytes-len/c 32) (bytes-len/c 32) bytes?
|
|
(bytes-len/c 64))])
|
|
|
|
(define/ffi crypto-check
|
|
(_fun (signature : _u8vector) (pubkey : _u8vector) (message : _u8vector)
|
|
(msgsize : _size = (u8vector-length message))
|
|
-> (result : _int) -> (zero? result)))
|
|
(provide/contract [crypto-check (contract:-> (bytes-len/c 64) (bytes-len/c 32) bytes? boolean?)])
|
|
|
|
(define (crypto-sign-make-key)
|
|
(crypto-random-bytes 32))
|
|
(provide crypto-sign-make-key)
|
|
|
|
;; key exchange
|
|
|
|
;; XXX : in monocypher crypto_key_exchange_public_key is actually crypto_x25519_public_key
|
|
(define/ffi crypto-x25519-public-key
|
|
(_fun (pubkey : (_u8vector o 32)) (seckey : _u8vector) -> _void -> pubkey))
|
|
(define crypto-key-exchange-public-key crypto-x25519-public-key)
|
|
(provide/contract [crypto-key-exchange-public-key (contract:-> (bytes-len/c 32) (bytes-len/c 32))])
|
|
|
|
(define/ffi crypto-key-exchange
|
|
(_fun (outkey : (_u8vector o 32)) (yourseckey : _u8vector) (theirpubkey : _u8vector)
|
|
-> _void -> outkey))
|
|
(provide/contract [crypto-key-exchange (contract:-> (bytes-len/c 32) (bytes-len/c 32)
|
|
(bytes-len/c 32))])
|
|
|
|
(define (crypto-key-exchange-make-key)
|
|
(crypto-random-bytes 32))
|
|
(provide crypto-key-exchange-make-key)
|
|
|
|
;; authenticated encryption
|
|
|
|
(define/ffi crypto-lock
|
|
(_fun (mac : (_u8vector o 16)) (ct : (_u8vector o textsize)) (key : _u8vector) (nonce : _u8vector)
|
|
(pt : _u8vector) (textsize : _size = (u8vector-length pt))
|
|
-> _void -> (values ct mac)))
|
|
(provide/contract [crypto-lock (contract:-> (bytes-len/c 32) (bytes-len/c 24) bytes?
|
|
(values bytes? (bytes-len/c 16)))])
|
|
|
|
(define/ffi crypto-unlock
|
|
(_fun (pt : (_u8vector o textsize)) (key : _u8vector) (nonce : _u8vector) (mac : _u8vector)
|
|
(ct : _u8vector) (textsize : _size = (u8vector-length ct))
|
|
-> (res : _int) -> (if (zero? res) pt #f)))
|
|
(provide/contract [crypto-unlock (contract:-> (bytes-len/c 32) (bytes-len/c 24) (bytes-len/c 16)
|
|
bytes? (or/c false? bytes?))])
|
|
|
|
(define (crypto-lock-make-key)
|
|
(crypto-random-bytes 32))
|
|
(define (crypto-lock-make-nonce)
|
|
(crypto-random-bytes 24))
|
|
(provide crypto-lock-make-key crypto-lock-make-nonce)
|
|
|
|
;; hashing
|
|
;; we use the size of crypto_blake2b_ctx on 64-bit platforms, as this should be large enough even on
|
|
;; 32-bit platforms
|
|
;; this should be more robust tbh but without pulling in the whole C header parsing library idk how
|
|
;; else we can know the size of this struct without just hardcoding it
|
|
(define *crypto-blake2b-ctx-size* 224)
|
|
;; default hash output size
|
|
(define *crypto-blake2b-hash-size* 64)
|
|
;; opaque datatype yeet
|
|
(struct crypto-blake2b-ctx [data])
|
|
|
|
(define/ffi crypto-blake2b-init
|
|
(_fun (ctx : (_u8vector o *crypto-blake2b-ctx-size*)) -> _void -> (crypto-blake2b-ctx ctx)))
|
|
(provide crypto-blake2b-init)
|
|
|
|
(define/ffi crypto-blake2b-update
|
|
(_fun (ctx-obj : _?) (ctx : _u8vector = (crypto-blake2b-ctx-data ctx-obj))
|
|
(msg : _u8vector) (msgsize : _size = (u8vector-length msg))
|
|
-> _void))
|
|
(provide/contract [crypto-blake2b-update (contract:-> crypto-blake2b-ctx? bytes? void?)])
|
|
|
|
(define/ffi crypto-blake2b-final
|
|
(_fun (ctx-obj : _?) (ctx : _u8vector = (crypto-blake2b-ctx-data ctx-obj))
|
|
(hash : (_u8vector o *crypto-blake2b-hash-size*)) -> _void -> hash))
|
|
(provide/contract [crypto-blake2b-final (contract:-> crypto-blake2b-ctx? bytes?)])
|
|
|
|
;; misc
|
|
|
|
(define/ffi crypto-wipe
|
|
(_fun (buf : _u8vector) (sz : _size = (u8vector-length buf)) -> _void))
|
|
(provide crypto-wipe)
|