crossfire/crossfire/not-crypto.rkt

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)