Merge branch 'jb/urcrypt' into jb/next-gen-term

* jb/urcrypt: (187 commits)
  test: removes obsolete scrypt test comment
  u3: renames secp init/stop functions, fixes comment
  u3: fixes sample deconstruction error handling in scrypt jets
  u3: fixes u3kc_bex() refcount, updates style
  build: adds urcrypt to top-level shell.nix
  urcrypt: restores pkg-config api versioning scheme
  build: restore division between pkg-config and regular deps
  mingw: sets libh2o install dir (for accurate pkg-config info)
  pmnsh: adds support for pkg-config
  build: update mingw CI to use "ares" cachix cache
  build: fixes urbit+urcrypt mingw build
  build: remove obsolete (urcrypt-vendored) dependencies
  build: normalize our use of pkg-config, rename urcrypt config
  build: implements static builds in urbit ./configure, prunes deps
  build: hack urbit configure for static linking
  build: force static urcrypt on darwin
  urcrypt: updates libaes_siv link test, supplying -lcrypto
  urcrypt: updates shared-library build test, accounts for mangling
  build: gitignore urcrypt build results
  build: gitignore library binaries
  ...
This commit is contained in:
Joe Bryan 2021-08-20 16:59:33 -04:00
commit 4320e5e8ee
271 changed files with 105882 additions and 3964 deletions

View File

@ -116,3 +116,24 @@ jobs:
- run: nix-build -A hs.urbit-king.components.exes.urbit-king --arg enableStatic true
- run: nix-build -A hs-checks
- run: nix-build shell.nix
mingw:
runs-on: windows-latest
defaults:
run:
shell: C:\msys64\msys2_shell.cmd -mingw64 -defterm -no-start -here -c ". <(cygpath '{0}')"
working-directory: ./pkg/urbit
steps:
- uses: actions/checkout@v2
with:
lfs: true
# echo suppresses pacman prompt
- run: echo|./configure --enable-static
env:
CACHIX_CACHE: ares
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
- run: make build/urbit build/urbit-worker
- run: build/urbit -l -d -B ../../bin/solid.pill -F bus && curl -f --data '{"source":{"dojo":"+hood/exit"},"sink":{"app":"hood"}}' http://localhost:12321

4
.gitignore vendored
View File

@ -55,7 +55,11 @@ release/
dist/
out/
work/
pkg/*/*.a
*.o
*.so
*.dll
*.dylib
# Landscape Dev
urbitrc

View File

@ -85,19 +85,11 @@ let
# Local vendored packages defined in ./pkg.
# For non-vendored nixpkgs specific package overrides, see ./nix/overlays.
pkgsLocal = {
argon2u = callPackage ./nix/pkgs/argon2u { };
ca-bundle = callPackage ./nix/pkgs/ca-bundle { };
ed25519 = callPackage ./nix/pkgs/ed25519 { };
ent = callPackage ./nix/pkgs/ent { };
ge-additions = callPackage ./nix/pkgs/ge-additions { };
libaes_siv = callPackage ./nix/pkgs/libaes_siv { };
libscrypt = callPackage ./nix/pkgs/libscrypt { };
libaes_siv = callPackage ./nix/pkgs/libaes_siv { inherit (pkgsNative) cmake; };
murmur3 = callPackage ./nix/pkgs/murmur3 { };
@ -115,6 +107,8 @@ let
urbit = callPackage ./nix/pkgs/urbit { inherit enableStatic; };
urcrypt = callPackage ./nix/pkgs/urcrypt { inherit enableStatic; };
docker-image = callPackage ./nix/pkgs/docker-image { };
hs = callPackage ./nix/pkgs/hs {

View File

@ -11,6 +11,11 @@ in {
outputs = [ "out" "dev" "lib" ];
});
secp256k1 = prev.secp256k1.overrideAttrs (_attrs: {
version = final.sources.secp256k1.rev;
src = final.sources.secp256k1;
});
libsigsegv = prev.libsigsegv.overrideAttrs (attrs: {
patches = optionalList attrs.patches ++ [
../pkgs/libsigsegv/disable-stackvma_fault-linux-arm.patch

View File

@ -1,30 +0,0 @@
{ stdenv, sources, enableParallelBuilding ? true }:
stdenv.mkDerivation {
pname = "argon2u";
version = sources.argon2u.rev;
src = sources.argon2u;
postPatch = ''
substituteInPlace Makefile --replace 'ar rcs' '$(AR) rcs'
'';
buildPhase = ''
make libargon2.a
'';
installPhase = ''
mkdir -p $out/{lib,include}
cp libargon2.a $out/lib/
cp include/argon2.h $out/include/
cp ./src/blake2/*.h $out/include/
'';
makeFlags = [
"AR=${stdenv.cc.targetPrefix}ar" # Fix cross-compilation
];
NO_THREADS = true;
inherit enableParallelBuilding;
}

View File

@ -1,21 +0,0 @@
{ stdenv, sources }:
stdenv.mkDerivation {
pname = "ed25519";
version = sources.ed25519.rev;
src = sources.ed25519;
buildPhase = ''
CFLAGS="-O3 -Wall -I$src/src"
for f in $(find src -type f -name '*.c'); do
$CC $CFLAGS -c $f -o "''${f//\//_}.o"
done
'';
installPhase = ''
mkdir -p $out/{lib,include}
$AR rcs $out/lib/libed25519.a *.o
cp $src/src/*.h $out/include/
'';
}

View File

@ -1,13 +0,0 @@
{ lib, stdenv, ed25519, enableParallelBuilding ? true }:
stdenv.mkDerivation {
name = "ge-additions";
src = lib.cleanSource ../../../pkg/ge-additions;
buildInputs = [ ed25519 ];
installFlags = [ "PREFIX=$(out)" ];
inherit enableParallelBuilding;
}

View File

@ -0,0 +1,34 @@
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,6 +5,8 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "")
set(CMAKE_BUILD_TYPE Release)
endif("${CMAKE_BUILD_TYPE}" STREQUAL "")
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
+
include(GNUInstallDirs)
# Warning: don't use the UB sanitizer in production builds. It can introduce timing side-channels
@@ -31,10 +33,12 @@ endif(NOT DISABLE_DOCS)
configure_file(config.h.in config.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
+if(BUILD_SHARED_LIBS)
add_library(aes_siv SHARED aes_siv.c)
target_include_directories(aes_siv PUBLIC ${OPENSSL_INCLUDE_DIR})
target_link_libraries(aes_siv ${OPENSSL_CRYPTO_LIBRARY})
set_target_properties(aes_siv PROPERTIES VERSION "1.0.1" SOVERSION 1)
+endif()
add_library(aes_siv_static STATIC aes_siv.c)
target_include_directories(aes_siv_static PUBLIC ${OPENSSL_INCLUDE_DIR})
@@ -63,7 +67,9 @@ endif(ENABLE_SANITIZER)
add_executable(bench EXCLUDE_FROM_ALL bench.c)
target_link_libraries(bench aes_siv_static)
+if(BUILD_SHARED_LIBS)
install(TARGETS aes_siv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+endif()
install(TARGETS aes_siv_static ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES aes_siv.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View File

@ -1,12 +1,17 @@
{ lib, stdenv, openssl, enableParallelBuilding ? true }:
{ stdenv, sources, cmake, openssl, enableParallelBuilding ? true }:
stdenv.mkDerivation {
name = "libaes_siv";
src = lib.cleanSource ../../../pkg/libaes_siv;
version = sources.libaes_siv.rev;
src = sources.libaes_siv;
patches = [ ./cmakefiles_static.patch ];
nativeBuildInputs = [ cmake ];
buildInputs = [ openssl ];
installFlags = [ "PREFIX=$(out)" ];
cmakeFlags = [
"-DBUILD_SHARED_LIBS=OFF"
];
inherit enableParallelBuilding;
}

View File

@ -1,35 +0,0 @@
{ stdenv, sources }:
stdenv.mkDerivation {
pname = "libscrypt";
version = sources.libscrypt.rev;
src = sources.libscrypt;
buildPhase = ''
sources=" \
crypto_scrypt-check \
crypto_scrypt-hash \
crypto_scrypt-hexconvert \
crypto_scrypt-nosse \
crypto-mcf \
crypto-scrypt-saltgen \
slowequals \
sha256 \
b64 \
"
CFLAGS="-I$src -Wall -ffast-math -O3 -D_FORTIFY_SOURCE=2 -fstack-protector"
for s in $sources; do
$CC $CFLAGS -c $src/$s.c -o $s.o
done
$AR rcs libscrypt.a *.o
'';
installPhase = ''
mkdir -p $out/{lib,include}
cp libscrypt.a $out/lib
cp $src/*.h $out/include/
'';
}

View File

@ -1,8 +1,12 @@
{ lib, stdenv, coreutils, pkgconfig, argon2u, cacert, ca-bundle, curlMinimal
, ed25519, ent, ge-additions, gmp, h2o, herb, ivory, libaes_siv, libscrypt
, libsigsegv, libuv, lmdb, murmur3, openssl, secp256k1, softfloat3, zlib
, enableStatic ? stdenv.hostPlatform.isStatic, enableDebug ? false
, doCheck ? true, enableParallelBuilding ? true, dontStrip ? true }:
{ lib, stdenv, coreutils, pkgconfig # build/env
, cacert, ca-bundle, ivory # codegen
, curlMinimal, ent, gmp, h2o, libsigsegv, libuv, lmdb # libs
, murmur3, openssl, softfloat3, urcrypt, zlib #
, enableStatic ? stdenv.hostPlatform.isStatic # opts
, enableDebug ? false
, doCheck ? true
, enableParallelBuilding ? true
, dontStrip ? true }:
let
@ -19,30 +23,23 @@ in stdenv.mkDerivation {
nativeBuildInputs = [ pkgconfig ];
buildInputs = [
argon2u
cacert
ca-bundle
curlMinimal
ed25519
ent
ge-additions
gmp
h2o
ivory.header
libaes_siv
libscrypt
libsigsegv
libuv
lmdb
murmur3
openssl
secp256k1
softfloat3
urcrypt
zlib
];
checkInputs = [ herb ];
# Ensure any `/usr/bin/env bash` shebang is patched.
postPatch = ''
patchShebangs ./configure
@ -56,9 +53,14 @@ in stdenv.mkDerivation {
cp ./build/urbit-worker $out/bin/urbit-worker
'';
dontDisableStatic = enableStatic;
configureFlags = if enableStatic
then [ "--disable-shared" "--enable-static" ]
else [];
CFLAGS = [ (if enableDebug then "-O0" else "-O3") "-g" ]
++ lib.optionals (!enableDebug) [ "-Werror" ]
++ lib.optionals enableStatic [ "-static" ];
++ lib.optionals (!enableDebug) [ "-Werror" ];
MEMORY_DEBUG = enableDebug;
CPU_DEBUG = enableDebug;

View File

@ -0,0 +1,21 @@
{ stdenv, autoreconfHook, pkgconfig
, libaes_siv, openssl, secp256k1
, enableStatic ? stdenv.hostPlatform.isStatic }:
stdenv.mkDerivation rec {
name = "urcrypt";
src = ../../../pkg/urcrypt;
# XX why are these required for darwin?
dontDisableStatic = enableStatic;
configureFlags = if enableStatic
then [ "--disable-shared" "--enable-static" ]
else [];
nativeBuildInputs =
[ autoreconfHook pkgconfig ];
propagatedBuildInputs =
[ openssl secp256k1 libaes_siv ];
}

65
nix/sources-pmnsh.json Normal file
View File

@ -0,0 +1,65 @@
{
"curl": {
"branch": "master",
"description": "A command line tool and library for transferring data with URL syntax",
"homepage": "http://curl.se/",
"pmnsh": {
"include": "include",
"lib": "lib/.libs",
"prepare": "autoreconf -vfi && ./configure --disable-shared --disable-ldap --disable-rtsp --without-brotli --without-libidn2 --without-libpsl --without-nghttp2 --with-openssl",
"make": "-C lib libcurl.la"
},
"owner": "curl",
"repo": "curl",
"rev": "curl-7_77_0",
"type": "tarball",
"url": "https://github.com/curl/curl/archive/curl-7_77_0.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"lmdb": {
"branch": "mdb.master",
"description": "LMDB library",
"homepage": "http://www.lmdb.tech/",
"pmnsh": {
"strip": 2,
"make": "liblmdb.a"
},
"owner": "LMDB",
"repo": "lmdb",
"rev": "48a7fed59a8aae623deff415dda27097198ca0c1",
"type": "tarball",
"url": "https://github.com/LMDB/lmdb/archive/48a7fed59a8aae623deff415dda27097198ca0c1.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"uv": {
"branch": "v1.x",
"description": "Cross-platform asynchronous I/O",
"homepage": "http://libuv.org/",
"pmnsh": {
"include": "include",
"lib": ".libs",
"prepare": "./autogen.sh && ./configure --disable-shared",
"make": "libuv.la",
"compat": {
"m1brew": false
}
},
"owner": "libuv",
"repo": "libuv",
"rev": "v1.40.0",
"type": "tarball",
"url": "https://github.com/libuv/libuv/archive/v1.40.0.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"ent": {
"pmnsh": {
"prepare": "./configure"
}
},
"urcrypt": {
"pmnsh": {
"prepare": "./autogen.sh && ./configure --disable-shared PKG_CONFIG_PATH=../secp256k1 CFLAGS=\"-I../secp256k1/include -I../libaes_siv\" LDFLAGS=-L../libaes_siv",
"make": "install"
}
}
}

View File

@ -1,38 +1,24 @@
{
"argon2u": {
"branch": "master",
"description": "With argon2u. Based off https://github.com/P-H-C/phc-winner-argon2",
"homepage": "",
"owner": "urbit",
"repo": "argon2",
"rev": "4da94a611ee62bad87ab2b131ffda3bcc0723d9c",
"sha256": "0bqq1hg367l4jkb6cqhxlblpvdbwz3l586qsfakwzfd9wdvnm3yc",
"type": "tarball",
"url": "https://github.com/urbit/argon2/archive/4da94a611ee62bad87ab2b131ffda3bcc0723d9c.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"ed25519": {
"branch": "master",
"description": "Submodule included by Urbit",
"homepage": null,
"owner": "urbit",
"repo": "ed25519",
"rev": "76385f2ebbbc9580a9c236952d68d11d73a6135c",
"sha256": "0s1spif4s9lgcwcny3fl2fvpbw6acqn3s8r6qxnrmkd9icgyw4cp",
"type": "tarball",
"url": "https://github.com/urbit/ed25519/archive/76385f2ebbbc9580a9c236952d68d11d73a6135c.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"h2o": {
"branch": "master",
"description": "H2O - the optimized HTTP/1, HTTP/2, HTTP/3 server",
"homepage": "https://h2o.examp1e.net",
"pmnsh": {
"include": "include",
"prepare": "cmake .",
"make": "libh2o",
"compat": {
"mingw": {
"prepare": "cmake -G\"MSYS Makefiles\" -DCMAKE_INSTALL_PREFIX=. ."
}
}
},
"owner": "h2o",
"repo": "h2o",
"rev": "v2.2.4",
"sha256": "0176x0bzjry19zs074a9i5vhncc842xikmx43wj61jky318nq4w4",
"rev": "v2.2.6",
"sha256": "0qni676wqvxx0sl0pw9j0ph7zf2krrzqc1zwj73mgpdnsr8rsib7",
"type": "tarball",
"url": "https://github.com/h2o/h2o/archive/v2.2.4.tar.gz",
"url": "https://github.com/h2o/h2o/archive/v2.2.6.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"hackage.nix": {
@ -59,22 +45,37 @@
"url": "https://github.com/input-output-hk/haskell.nix/archive/bbb34dcdf7b90d478002f91713531f418ddf1b53.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"libscrypt": {
"libaes_siv": {
"branch": "master",
"description": null,
"homepage": null,
"owner": "urbit",
"repo": "libscrypt",
"rev": "029693ff1cbe4f69d3a2da87d0f4f034f92cc0c2",
"sha256": "17pcxypzjmmrvacw45cacvibm6mlr9ip30hy30l1appsnywx679n",
"pmnsh": {
"compat": {
"m1brew": {
"prepare": "cmake .",
"make": "install CFLAGS=$(pkg-config --cflags openssl)"
},
"mingw": {
"prepare": "cmake -G\"MSYS Makefiles\" -DDISABLE_DOCS:BOOL=ON .",
"make": "aes_siv_static"
}
}
},
"owner":"dfoxfranke",
"repo": "libaes_siv",
"rev": "9681279cfaa6e6399bb7ca3afbbc27fc2e19df4b",
"sha256": "1g4wy0m5wpqx7z6nillppkh5zki9fkx9rdw149qcxh7mc5vlszzi",
"type": "tarball",
"url": "https://github.com/urbit/libscrypt/archive/029693ff1cbe4f69d3a2da87d0f4f034f92cc0c2.tar.gz",
"url": "https://github.com/dfoxfranke/libaes_siv/archive/9681279cfaa6e6399bb7ca3afbbc27fc2e19df4b.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"murmur3": {
"branch": "master",
"description": null,
"homepage": null,
"pmnsh": {
"make": "static"
},
"owner": "urbit",
"repo": "murmur3",
"rev": "71a75d57ca4e7ca0f7fc2fd84abd93595b0624ca",
@ -111,6 +112,19 @@
"branch": "master",
"description": null,
"homepage": null,
"pmnsh": {
"include": "source/include",
"compat": {
"m1brew": {
"lib": "build/template-FAST_INT64",
"make": "-C build/template-FAST_INT64 libsoftfloat3.a"
},
"mingw": {
"lib": "build/Win64-MinGW-w64",
"make": "-C build/Win64-MinGW-w64 libsoftfloat3.a"
}
}
},
"owner": "urbit",
"repo": "berkeley-softfloat-3",
"rev": "ec4c7e31b32e07aad80e52f65ff46ac6d6aad986",
@ -119,6 +133,24 @@
"url": "https://github.com/urbit/berkeley-softfloat-3/archive/ec4c7e31b32e07aad80e52f65ff46ac6d6aad986.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"secp256k1": {
"branch": "master",
"description": "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1.",
"homepage": null,
"pmnsh": {
"include": "include",
"lib": ".libs",
"prepare": "./autogen.sh && ./configure --disable-shared --enable-module-recovery CFLAGS=-DSECP256K1_API=",
"make": "libsecp256k1.la"
},
"owner": "bitcoin-core",
"repo": "secp256k1",
"rev": "26de4dfeb1f1436dae1fcf17f57bdaa43540f940",
"sha256": "03i3nv8d3ci7q9y98q11rrp3rvwdqc0hc0ss0pr6xckybvizsmbb",
"type": "tarball",
"url": "https://github.com/bitcoin-core/secp256k1/archive/26de4dfeb1f1436dae1fcf17f57bdaa43540f940.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"stackage.nix": {
"branch": "master",
"description": "Automatically generated Nix expressions of Stackage snapshots",

View File

@ -21,10 +21,7 @@
!> `@ux`(hsh pw salt n r p 64)
::
++ vectors
:: TODO: until scrypt has been jetted, we can only test the
:: first vector; the others do not finish in a reasonable
:: amount of time.
%+ scag 1 ^- (list vector)
^- (list vector)
:~
:*
0x0
@ -37,8 +34,8 @@
==
::
:*
0x7061.7373.776f.7264
0x4e61.436c
`@ux`'password'
`@ux`'NaCl'
1.024 8 16
0xfdba.be1c.9d34.7200.7856.e719.0d01.e9fe.
7c6a.d7cb.c823.7830.e773.7663.4b37.3162.
@ -47,8 +44,8 @@
==
::
:*
0x70.6c65.6173.656c.6574.6d65.696e
0x536f.6469.756d.4368.6c6f.7269.6465
`@ux`'pleaseletmein'
`@ux`'SodiumChloride'
16.384 8 1
0x7023.bdcb.3afd.7348.461c.06cd.81fd.38eb.
fda8.fbba.904f.8e3e.a9b5.43f6.545d.a1f2.
@ -57,8 +54,8 @@
==
::
:*
0x70.6c65.6173.656c.6574.6d65.696e
0x536f.6469.756d.4368.6c6f.7269.6465
`@ux`'pleaseletmein'
`@ux`'SodiumChloride'
1.048.576 8 1
0x2101.cb9b.6a51.1aae.addb.be09.cf70.f881.
ec56.8d57.4a2f.fd4d.abe5.ee98.20ad.aa47.

1
pkg/ent/configure vendored
View File

@ -7,6 +7,7 @@ log () {
for impl in ENT_GETENTROPY_UNISTD \
ENT_GETENTROPY_SYSRANDOM \
ENT_GETRANDOM_SYSCALL \
ENT_GETENTROPY_BCRYPTGENRANDOM \
ENT_DEV_URANDOM
do
export IMPL=$impl

View File

@ -57,6 +57,16 @@ int ent_getentropy(void* buf, size_t len) {
return 0;
}
// Use `BCryptGenRandom` on Windows ////////////////////////////////////////////
#elif defined(ENT_GETENTROPY_BCRYPTGENRANDOM)
#include <windows.h>
#include <bcrypt.h>
int ent_getentropy(void* buf, size_t len) {
return BCryptGenRandom(NULL, (PUCHAR)buf, len, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
}
#else
#error "One of these must be set: ENT_DEV_URANDOM, ENT_GETENTROPY_UNISTD, ENT_GETENTROPY_SYSRANDOM, ENT_GETRANDOM_SYSCALL"
#error "One of these must be set: ENT_GETENTROPY_BCRYPTGENRANDOM, ENT_DEV_URANDOM, ENT_GETENTROPY_UNISTD, ENT_GETENTROPY_SYSRANDOM, ENT_GETRANDOM_SYSCALL"
#endif

View File

@ -1,20 +0,0 @@
CC ?= cc
AR ?= ar
PREFIX ?= ./out
################################################################################
.PHONY: all test install clean
all: ge-additions.c ge-additions.h
$(CC) $(CFLAGS) -O3 -Wall -Werror -pedantic -std=gnu99 -c ge-additions.c
$(AR) rcs libge-additions.a ge-additions.o
install: all
@mkdir -p $(PREFIX)/lib/
@mkdir -p $(PREFIX)/include/
cp libge-additions.a $(PREFIX)/lib/
cp ge-additions.h $(PREFIX)/include/
clean:
rm -rf ./out

View File

@ -1,8 +0,0 @@
let
pkgs = import ../../default.nix { };
in pkgs.shellFor {
name = "ge-additions";
packages = ps: [ ps.ge-additions ];
}

View File

@ -86,7 +86,7 @@ instance FromNoun Pass where
-- seed. These aren't actually private keys, but public/private keypairs which
-- can be derived from these seeds.
data Ring = Ring { ringSign :: BS.ByteString, ringCrypt :: BS.ByteString }
deriving (Eq)
deriving (Eq, Ord)
instance ToNoun Ring where
toNoun Ring{..} =
@ -118,6 +118,36 @@ data Seed = Seed
}
deriving (Eq, Show)
data Germs = Germs
{ gShip :: Ship
, gFeed :: [Germ]
}
deriving (Eq, Show)
data Germ = Germ
{ gLife :: Life
, gRing :: Ring
}
deriving (Eq, Ord, Show)
data Feed
= Feed0 Seed
| Feed1 Germs
deriving (Eq, Show)
--NOTE reify type environment
$(pure [])
instance ToNoun Feed where
toNoun = \case
Feed0 s -> $(deriveToNounFunc ''Seed) s
Feed1 s -> C (C (A 1) (A 0)) $ $(deriveToNounFunc ''Germs) s
instance FromNoun Feed where
parseNoun = \case
(C (C (A 1) (A 0)) s) -> Feed1 <$> $(deriveFromNounFunc ''Germs) s
n -> Feed0 <$> $(deriveFromNounFunc ''Seed) n
type Public = (Life, HoonMap Life Pass)
data Dnses = Dnses { dPri::Cord, dSec::Cord, dTer::Cord }
@ -146,6 +176,7 @@ data Dawn = MkDawn
deriveNoun ''Dnses
deriveNoun ''EthPoint
deriveNoun ''Seed
deriveNoun ''Germ
deriveNoun ''Dawn
@ -240,6 +271,16 @@ data BoatEv
deriveNoun ''BoatEv
-- Boat Events -----------------------------------------------------------------
data JaelEv
= JaelEvRekey () (Life, Ring)
| JaelEvCrud Path Noun
deriving (Eq, Show)
deriveNoun ''JaelEv
-- Timer Events ----------------------------------------------------------------
data BehnEv
@ -347,6 +388,7 @@ data BlipEv
| BlipEvBoat BoatEv
| BlipEvHttpClient HttpClientEv
| BlipEvHttpServer HttpServerEv
| BlipEvJael JaelEv
| BlipEvNewt NewtEv
| BlipEvSync SyncEv
| BlipEvTerm TermEv
@ -369,6 +411,7 @@ instance ToNoun Ev where
EvBlip v@BlipEvBoat{} -> reorgThroughNoun ("clay", v)
EvBlip v@BlipEvHttpClient{} -> reorgThroughNoun ("iris", v)
EvBlip v@BlipEvHttpServer{} -> reorgThroughNoun ("eyre", v)
EvBlip v@BlipEvJael{} -> reorgThroughNoun ("jael", v)
EvBlip v@BlipEvNewt{} -> reorgThroughNoun ("ames", v)
EvBlip v@BlipEvSync{} -> reorgThroughNoun ("clay", v)
EvBlip v@BlipEvTerm{} -> reorgThroughNoun ("dill", v)
@ -395,6 +438,7 @@ getSpinnerNameForEvent = \case
BlipEvBoat _ -> Just "boat"
BlipEvHttpClient _ -> Just "iris"
BlipEvHttpServer _ -> Just "eyre"
BlipEvJael _ -> Just "jael"
BlipEvNewt _ -> Just "newt"
BlipEvSync _ -> Just "clay"
BlipEvTerm (TermEvBelt _ _) -> Nothing

View File

@ -184,8 +184,9 @@ tryBootFromPill
-> Bool
-> Ship
-> LegacyBootEvent
-> Feed
-> RIO PierEnv ()
tryBootFromPill oExit pill lite ship boot = do
tryBootFromPill oExit pill lite ship boot feed = do
mStart <- newEmptyMVar
vSlog <- logSlogs
runOrExitImmediately vSlog (bootedPier vSlog) oExit mStart []
@ -193,7 +194,7 @@ tryBootFromPill oExit pill lite ship boot = do
bootedPier vSlog = do
view pierPathL >>= lockFile
rio $ logInfo "Starting boot"
sls <- Pier.booted vSlog pill lite ship boot
sls <- Pier.booted vSlog pill lite ship boot feed
rio $ logInfo "Completed boot"
pure sls
@ -395,7 +396,12 @@ testPill pax showPil showSeq = do
pill <- fromNounErr pillNoun & either (throwIO . uncurry ParseErr) pure
logInfo "Using pill to generate boot sequence."
bootSeq <- genBootSeq (Ship 0) pill False (Fake (Ship 0))
bootSeq <- genBootSeq
(Ship 0)
pill
False
(Fake (Ship 0))
(Feed1 $ Germs (Ship 0) [])
logInfo "Validate jam/cue and toNoun/fromNoun on pill value"
reJam <- validateNounVal pill
@ -500,12 +506,12 @@ newShip CLI.New{..} opts = do
let seed = mineComet (Set.fromList starList) eny
putStrLn ("boot: found comet " ++ renderShip (sShip seed))
putStrLn ("code: " ++ (tshow $ deriveCode $ sRing seed))
bootFromSeed pill seed
bootFromSeed pill $ Feed0 seed
CLI.BootFake name -> do
pill <- pillFrom nPillSource
ship <- shipFrom name
runTryBootFromPill pill name ship (Fake ship)
runTryBootFromPill pill name ship (Fake ship) (Feed1 $ Germs ship [])
CLI.BootFromKeyfile keyFile -> do
text <- readFileUtf8 keyFile
@ -514,13 +520,13 @@ newShip CLI.New{..} opts = do
Just (UW a) -> pure a
asNoun <- cueExn asAtom
seed :: Seed <- case fromNoun asNoun of
feed :: Feed <- case fromNoun asNoun of
Nothing -> error "Keyfile does not seem to contain a seed."
Just s -> pure s
pill <- pillFrom nPillSource
bootFromSeed pill seed
bootFromSeed pill feed
where
shipFrom :: Text -> RIO HostEnv Ship
@ -541,16 +547,16 @@ newShip CLI.New{..} opts = do
Nothing -> error "Urbit.ob didn't produce string with ~"
Just x -> pure x
bootFromSeed :: Pill -> Seed -> RIO HostEnv ()
bootFromSeed pill seed = do
ethReturn <- dawnVent nEthNode seed
bootFromSeed :: Pill -> Feed -> RIO HostEnv ()
bootFromSeed pill feed = do
ethReturn <- dawnVent nEthNode feed
case ethReturn of
Left x -> error $ unpack x
Right dawn -> do
let ship = sShip $ dSeed dawn
name <- nameFromShip ship
runTryBootFromPill pill name ship (Dawn dawn)
runTryBootFromPill pill name ship (Dawn dawn) feed
-- Now that we have all the information for running an application with a
-- PierConfig, do so.
@ -558,13 +564,14 @@ newShip CLI.New{..} opts = do
-> Text
-> Ship
-> LegacyBootEvent
-> Feed
-> RIO HostEnv ()
runTryBootFromPill pill name ship bootEvent = do
runTryBootFromPill pill name ship bootEvent feed = do
vKill <- view (kingEnvL . kingEnvKillSignal)
let pierConfig = toPierConfig (pierPath name) nSerfExe opts
let networkConfig = toNetworkConfig opts
runPierEnv pierConfig networkConfig vKill $
tryBootFromPill True pill nLite ship bootEvent
tryBootFromPill True pill nLite ship bootEvent feed
runShipEnv :: Maybe Text -> CLI.Run -> CLI.Opts -> TMVar () -> RIO PierEnv a
-> RIO HostEnv a
@ -642,13 +649,13 @@ checkDawn provider keyfilePath = do
Just (UW a) -> pure a
asNoun <- cueExn asAtom
seed :: Seed <- case fromNoun asNoun of
feed :: Feed <- case fromNoun asNoun of
Nothing -> error "Keyfile does not seem to contain a seed."
Just s -> pure s
print $ show seed
print $ show feed
e <- dawnVent provider seed
e <- dawnVent provider feed
print $ show e

View File

@ -335,45 +335,72 @@ retrievePoint endpoint block ship =
[x] -> pure x
_ -> error "JSON server returned multiple return values."
validateShipAndGetSponsor :: String -> TextBlockNum -> Seed -> RIO e Ship
validateShipAndGetSponsor endpoint block (Seed ship life ring oaf) =
case clanFromShip ship of
Ob.Comet -> validateComet
Ob.Moon -> validateMoon
_ -> validateRest
validateFeedAndGetSponsor :: String
-> TextBlockNum
-> Feed
-> RIO e (Seed, Ship)
validateFeedAndGetSponsor endpoint block = \case
Feed0 s -> do
r <- validateSeed s
case r of
Left e -> error e
Right r -> pure (s, r)
Feed1 s -> validateGerms s
where
validateComet = do
-- A comet address is the fingerprint of the keypair
let shipFromPass = cometFingerprint $ ringToPass ring
when (ship /= shipFromPass) $
error ("comet name doesn't match fingerprint " <> show ship <> " vs " <>
show shipFromPass)
when (life /= 1) $
error ("comet can never be re-keyed")
pure (shipSein ship)
validateGerms Germs{..} =
case gFeed of
[] -> error "no usable keys in keyfile"
(Germ{..}:f) -> do
let seed = Seed gShip gLife gRing Nothing
r :: Either String Ship
<- validateSeed seed
case r of
Left _ -> validateGerms $ Germs gShip f
Right r -> pure (seed, r)
validateMoon = do
-- TODO: The current code in zuse does nothing, but we should be able to
-- try to validate the oath against the current as exists planet on
-- chain.
pure $ shipSein ship
validateSeed (Seed ship life ring oaf) =
case clanFromShip ship of
Ob.Comet -> validateComet
Ob.Moon -> validateMoon
_ -> validateRest
where
validateComet = do
-- A comet address is the fingerprint of the keypair
let shipFromPass = cometFingerprint $ ringToPass ring
if (ship /= shipFromPass) then
pure $ Left ("comet name doesn't match fingerprint " <>
show ship <> " vs " <>
show shipFromPass)
else if (life /= 1) then
pure $ Left "comet can never be re-keyed"
else
pure $ Right (shipSein ship)
validateRest = do
putStrLn ("boot: retrieving " <> renderShip ship <> "'s public keys")
validateMoon = do
-- TODO: The current code in zuse does nothing, but we should be able
-- to try to validate the oath against the current as exists planet
-- on chain.
pure $ Right $ shipSein ship
whoP <- retrievePoint endpoint block ship
case epNet whoP of
Nothing -> error "ship not keyed"
Just (netLife, pass, contNum, (hasSponsor, who), _) -> do
when (netLife /= life) $
error ("keyfile life mismatch; keyfile claims life " <>
show life <> ", but Azimuth claims life " <>
show netLife)
when ((ringToPass ring) /= pass) $
error "keyfile does not match blockchain"
-- TODO: The hoon code does a breach check, but the C code never
-- supplies the data necessary for it to function.
pure who
validateRest = do
putStrLn ("boot: retrieving " <> renderShip ship <> "'s public keys")
--TODO could cache this lookup
whoP <- retrievePoint endpoint block ship
case epNet whoP of
Nothing -> pure $ Left "ship not keyed"
Just (netLife, pass, contNum, (hasSponsor, who), _) -> do
if (netLife /= life) then
pure $ Left ("keyfile life mismatch; keyfile claims life " <>
show life <> ", but Azimuth claims life " <>
show netLife)
else if ((ringToPass ring) /= pass) then
pure $ Left "keyfile does not match blockchain"
-- TODO: The hoon code does a breach check, but the C code never
-- supplies the data necessary for it to function.
else
pure $ Right who
-- Walk through the sponsorship chain retrieving the actual sponsorship chain
@ -402,8 +429,8 @@ getSponsorshipChain endpoint block = loop
pure $ chain <> [(ship, ethPoint)]
-- Produces either an error or a validated boot event structure.
dawnVent :: HasLogFunc e => String -> Seed -> RIO e (Either Text Dawn)
dawnVent provider dSeed@(Seed ship life ring oaf) =
dawnVent :: HasLogFunc e => String -> Feed -> RIO e (Either Text Dawn)
dawnVent provider feed =
-- The type checker can't figure this out on its own.
(onLeft tshow :: Either SomeException Dawn -> Either Text Dawn) <$> try do
putStrLn ("boot: requesting ethereum information from " <> pack provider)
@ -417,7 +444,8 @@ dawnVent provider dSeed@(Seed ship life ring oaf) =
let dBloq = hexStrToAtom hexStrBlock
putStrLn ("boot: ethereum block #" <> tshow dBloq)
immediateSponsor <- validateShipAndGetSponsor provider hexStrBlock dSeed
(dSeed, immediateSponsor)
<- validateFeedAndGetSponsor provider hexStrBlock feed
dSponsor <- getSponsorshipChain provider hexStrBlock immediateSponsor
putStrLn "boot: retrieving galaxy table"
@ -431,7 +459,7 @@ dawnVent provider dSeed@(Seed ship life ring oaf) =
let dNode = Nothing
pure $ MkDawn{..}
pure MkDawn{..}
-- Comet List ------------------------------------------------------------------

View File

@ -79,12 +79,17 @@ genEntropy :: MonadIO m => m Entropy
genEntropy = Entropy . fromIntegral . bytesAtom <$> io (Ent.getEntropy 64)
genBootSeq :: HasKingEnv e
=> Ship -> Pill -> Bool -> LegacyBootEvent -> RIO e BootSeq
genBootSeq _ PillIvory {} _ _ = throwIO CannotBootFromIvoryPill
genBootSeq ship PillPill {..} lite boot = do
=> Ship -> Pill -> Bool -> LegacyBootEvent -> Feed -> RIO e BootSeq
genBootSeq _ PillIvory {} _ _ _ = throwIO CannotBootFromIvoryPill
genBootSeq ship PillPill {..} lite boot feed = do
ent <- io genEntropy
wyr <- wyrd
let ova = preKern ent <> [wyr] <> pKernelOva <> postKern <> pUserspaceOva
let ova = preKern ent
<> [wyr]
<> pKernelOva
<> postKern
<> extraKeys
<> pUserspaceOva
pure $ BootSeq ident pBootFormulae ova
where
ident = LogIdentity ship isFake (fromIntegral $ length pBootFormulae)
@ -96,6 +101,10 @@ genBootSeq ship PillPill {..} lite boot = do
isFake = case boot of
Fake _ -> True
_ -> False
extraKeys = case feed of
Feed0 _ -> []
Feed1 Germs{..} -> fmap rekey gFeed
rekey Germ{..} = EvBlip $ BlipEvJael $ JaelEvRekey () (gLife, gRing)
-- Write to the log. -----------------------------------------------------------
@ -160,9 +169,10 @@ booted
-> Bool
-> Ship
-> LegacyBootEvent
-> Feed
-> RAcquire PierEnv (Serf, EventLog)
booted vSlog pill lite ship boot = do
rio $ bootNewShip pill lite ship boot
booted vSlog pill lite ship boot feed = do
rio $ bootNewShip pill lite ship boot feed
resumed vSlog Nothing
bootSeqJobs :: Time.Wen -> BootSeq -> [Job]
@ -183,9 +193,10 @@ bootNewShip
-> Bool
-> Ship
-> LegacyBootEvent
-> Feed
-> RIO e ()
bootNewShip pill lite ship bootEv = do
seq@(BootSeq ident x y) <- genBootSeq ship pill lite bootEv
bootNewShip pill lite ship bootEv feed = do
seq@(BootSeq ident x y) <- genBootSeq ship pill lite bootEv feed
logInfo "BootSeq Computed"
pierPath <- view pierPathL

View File

@ -1,20 +0,0 @@
CC ?= cc
AR ?= ar
PREFIX ?= ./out
################################################################################
.PHONY: all test install clean
all: aes_siv.c aes_siv.h
$(CC) $(CFLAGS) -Wall -Wextra -Wstrict-prototypes -Wconversion -O3 -fomit-frame-pointer -funroll-loops -ftree-vectorize -DNDEBUG -c aes_siv.c
$(AR) rcs libaes_siv.a aes_siv.o
install: all
@mkdir -p $(PREFIX)/lib/
@mkdir -p $(PREFIX)/include/
cp libaes_siv.a $(PREFIX)/lib/
cp aes_siv.h $(PREFIX)/include/
clean:
rm -rf ./out

View File

@ -1,197 +0,0 @@
# libaes_siv
This is an [RFC5297](https://tools.ietf.org/html/rfc5297)-compliant C
implementation of AES-SIV written by Daniel Franke on behalf of
[Akamai Technologies](https://www.akamai.com). It is published under
the [Apache License
(v2.0)](https://www.apache.org/licenses/LICENSE-2.0). It uses OpenSSL
for the underlying
[AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) and
[CMAC](https://en.wikipedia.org/wiki/One-key_MAC) implementations and
follows a similar interface style.
An AES_SIV implementation forked from libaes_siv has been [merged into
the OpenSSL master branch](https://github.com/openssl/openssl/pull/3540).
However, the two implementations are not API-compatible; see section
"OpenSSL API Comparison" below.
## Overview of SIV mode
Synthetic Initialization Vector (SIV) mode is a [block cipher mode of
operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
for [authenticated encryption with associated
data](https://en.wikipedia.org/wiki/Authenticated_encryption) designed
to be maximally resistant to accidental
[nonce](https://en.wikipedia.org/wiki/Cryptographic_nonce) reuse. If
two messages are accidentally encrypted using the same nonce and the
same associated data, the attacker learns nothing except whether or
not the plaintexts of the two messages are identical to each other.
SIV mode also permits the nonce to be intentionally omitted, resulting
in a [deterministic encryption
scheme](https://en.wikipedia.org/wiki/Deterministic_encryption).
Here are a couple common situations where AES-SIV may be an
appropriate choice of AEAD scheme:
1. You can't count on the system doing the encrypting to reliably
generate a unique nonce for every message. For example, the system
may be an embedded device with no good entropy source, or may be a
VM subject to be snapshotted and restored.
2. You want your encryption to be deterministic so that an
intermediating party such as a caching proxy, provided only with
ciphertext, can perform deduplication.
The drawback to SIV mode is that it requires two passes over its
input. This makes it potentially clumsy for use with large messages
since the entire message must be held in memory at one time. SIV mode
is also a bit slower than most widely-used block cipher modes (but
can still be quite fast — see performance numbers below).
Be aware that with *any* encryption scheme, including SIV, repeating
or omitting a nonce can still be [fatal to
security](https://xkcd.com/257) if your plaintexts have low entropy,
e.g., if each message consists only of a single bit.
Keys for SIV mode are twice the length of the keys for the underlying
block cipher. For example, keys for AES-128-SIV are 256 bits long,
and keys for AES-256-SIV are 512 bits long.
## Build instructions
Build dependencies:
* Any ISO C89 compiler (GCC or Clang recommended). No C99 language
features are required, however `<stdint.h>` must be available and
must define `uint64_t`. `char` must be 8 bits and arithmetic must be
two's complement.
* [CMake](https://cmake.org) >= 3.1
* [OpenSSL](https://openssl.org) >=1.0.1 (libcrypto only). A recent
release from the 1.0.2 branch or later is strongly recommended since
1.0.1 was EOL'ed at the end of 2016. Furthermore, OpenSSL versions prior
to 1.0.1n and 1.0.2b have known bugs which impact `libaes_siv` and
will cause failures in its test suite. LibreSSL is not supported.
* [Asciidoc](http://asciidoc.org) (only required for building man pages)
Running benchmarks requires a POSIX.1-2001 compliant OS, including
the `clock_gettime` system call.
To build and install on POSIX-like platforms:
```
cmake . &&
make &&
make test &&
sudo make install
```
NOTE: Out-of-source builds are allowed, but out-of-source manpage builds
require a2x's -D option, which may provoke an apparently bogus warning from a2x.
If you want to build on an OS X machine, install the Xcode development
environment and the command line tools, then use either the Homebrew package
manager or the MacPorts package manager to install cmake and OpenSSL.
Homebrew (https://brew.sh/):
```
brew install cmake openssl &&
cmake -DCMAKE_PREFIX_PATH=/usr/local/opt/openssl . &&
make &&
make test &&
sudo make install
```
MacPorts (https://www.macports.org/):
```
sudo port install cmake openssl &&
cmake . &&
make &&
make test &&
sudo make install
```
To create a native Windows build, you will first need to build
OpenSSL. Install Visual Studio, CMake, ActiveState Perl, and NASM, and
ensure that `nasm.exe` is somewhere in your `%PATH%`. From a VS developer
command prompt, unpack the OpenSSL sources and run
```
perl Configure VC-WIN64A
nmake
```
Then to build `libaes_siv`, run
```
cmake -G "NMake Makefiles" -DOPENSSL_ROOT_DIR=\path\to\openssl .
nmake
nmake test
```
## Usage
See the manual pages for API documentation, and the test vectors
in `tests.c` for simple usage examples. You can also use the `demo` command
line program to encrypt and decrypt data.
## OpenSSL API Comparison
In December 2018, OpenSSL merged an AES-SIV implementation derived
from libaes_siv. As of February 2019 this implementation has not been
released yet; it will appear some time post-1.1.1. However, despite
the two implementations' common ancestry, they are not API-compatible.
The OpenSSL team had to make an ugly-but-necessary compromise in order
to shoehorn SIV mode into OpenSSL's EVP API, which is a streaming API
that was never designed to support SIV's two-pass operation. When used for
SIV operations, the EVP API is forced to return an error if you invoke
`EVP_(En|De)crypt_Update` more than once for the same message.
When designing libaes_siv, I rejected this behavior as an unacceptable
breakdown of the API contract and opted to dispense with the EVP
abstraction altogether rather than permit it to leak. libaes_siv's API
remains stylistically similar to EVP, but is nonetheless distinct and
avoids the above pitfall.
## Performance
On the author's Intel Core i7-6560U laptop, libaes_siv can process
approximately 796 MiB of plaintext or ciphertext or 963 MiB of
associated data per second using 256-bit keys
(i.e., AES-128). Encrypting a zero-byte message takes approximately
990ns. To obtain numbers for your own system, run `make bench &&
./bench`.
## Software assurance
libaes_siv's test suite includes all test vectors from RFC 5297 and
achieves 100% code coverage according to
[gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html). It produces
clean output from [Valgrind](https://valgrind.org) and from Clang's
[undefined behavior
sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html),
and is verified using [ctgrind](https://github.com/agl/ctgrind) to run
in constant time.
Nonetheless, libaes_siv should at present be considered beta-quality
code. It has not yet been tested on platforms other than x86-64 Linux
or benefited from any significant amount of user feedback, and
the codebase is in need of additional review by cryptographers and
expert C programmers.
## Bugs and pull requests
Use the GitHub issue tracker. For reporting sensitive security issues,
contact the author directly. (Note: I no longer use PGP. Please
request my Signal details if necessary).
## A note on version numbers
libaes_siv version numbers are of the form `<major>.<minor>.<patch>`
and follow a semantic versioning scheme. The major version number
will be incremented with any backward-incompatible ABI change. The
minor version number will be incremented if new functionality is
added without impacting ABI backward-compatibility. The patch
version number will be incremented for releases that make no
externally-visible changes.
As a result of this scheme, on ELF platforms, the .so version will
be the same as the release version.
Version numbers indicate nothing about code quality or maturity. No
code known or suspected to be less suitable for production use than
previous releases will ever be tagged with a version number.

View File

@ -1,2 +0,0 @@
Vendoring of git@github.com:dfoxfranke/libaes_siv.git.
Code from commit 509550e92a416172b9b8255e275f3a04d5fd4545

View File

@ -1,594 +0,0 @@
/* Copyright (c) 2017-2019 Akamai Technologies, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#define _POSIX_C_SOURCE 200112L
#define _ISOC99_SOURCE 1
#include "config.h"
#include "aes_siv.h"
#include <assert.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#ifdef ENABLE_DEBUG_OUTPUT
#include <stdio.h>
#endif
#ifdef _MSC_VER
/* For _byteswap_uint64 */
#include <stdlib.h>
#endif
#include <string.h>
#include <openssl/cmac.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#ifdef ENABLE_CTGRIND
#include <ctgrind.h>
#endif
#if CHAR_BIT != 8
#error "libaes_siv requires an 8-bit char type"
#endif
#if -1 != ~0
#error "libaes_siv requires a two's-complement architecture"
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901
#undef inline
#elif defined(__GNUC__) || defined(__clang__)
#define inline __inline__
#elif defined(_MSC_VER)
#define inline __inline
#else
#define inline
#endif
#if defined(__GNUC__) || defined(__clang__)
#define LIKELY(cond) __builtin_expect(cond, 1)
#define UNLIKELY(cond) __builtin_expect(cond, 0)
#else
#define LIKELY(cond) cond
#define UNLIKELY(cond) cond
#endif
#ifndef ENABLE_CTGRIND
static inline void ct_poison(const void *data, size_t len) {
(void)data;
(void)len;
}
static inline void ct_unpoison(const void *data, size_t len) {
(void)data;
(void)len;
}
#endif
static void debug(const char *label, const unsigned char *hex, size_t len) {
/* ENABLE_CTGRIND has to override ENABLE_DEBUG_OUTPUT since sensitive data
gets printed.
*/
#if defined(ENABLE_DEBUG_OUTPUT) && !defined(ENABLE_CTGRIND)
size_t i;
printf("%16s: ", label);
for (i = 0; i < len; i++) {
if (i > 0 && i % 16 == 0) {
printf("\n ");
}
printf("%.2x", (int)hex[i]);
if (i > 0 && i % 4 == 3) {
printf(" ");
}
}
printf("\n");
#else
(void)label;
(void)hex;
(void)len;
#endif
}
typedef union block_un {
uint64_t word[2];
unsigned char byte[16];
} block;
const union {
uint64_t word;
char byte[8];
} endian = {0x0102030405060708};
#define I_AM_BIG_ENDIAN (endian.byte[0] == 1 && \
endian.byte[1] == 2 && \
endian.byte[2] == 3 && \
endian.byte[3] == 4 && \
endian.byte[4] == 5 && \
endian.byte[5] == 6 && \
endian.byte[6] == 7 && \
endian.byte[7] == 8)
#define I_AM_LITTLE_ENDIAN (endian.byte[0] == 8 && \
endian.byte[1] == 7 && \
endian.byte[2] == 6 && \
endian.byte[3] == 5 && \
endian.byte[4] == 4 && \
endian.byte[5] == 3 && \
endian.byte[6] == 2 && \
endian.byte[7] == 1)
#if defined(__GNUC__) || defined(__clang__)
static inline uint64_t bswap64(uint64_t x) { return __builtin_bswap64(x); }
#elif defined(_MSC_VER)
static inline uint64_t bswap64(uint64_t x) { return _byteswap_uint64(x); }
#else
static inline uint32_t rotl(uint32_t x) { return (x << 8) | (x >> 24); }
static inline uint32_t rotr(uint32_t x) { return (x >> 8) | (x << 24); }
static inline uint64_t bswap64(uint64_t x) {
uint32_t high = (uint32_t)(x >> 32);
uint32_t low = (uint32_t)x;
high = (rotl(high) & 0x00ff00ff) | (rotr(high) & 0xff00ff00);
low = (rotl(low) & 0x00ff00ff) | (rotr(low) & 0xff00ff00);
return ((uint64_t)low) << 32 | (uint64_t)high;
}
#endif
static inline uint64_t getword(block const *block, size_t i) {
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
if (I_AM_BIG_ENDIAN) {
return block->word[i];
} else if (I_AM_LITTLE_ENDIAN) {
return bswap64(block->word[i]);
} else {
#endif
i <<= 3;
return ((uint64_t)block->byte[i + 7]) |
((uint64_t)block->byte[i + 6] << 8) |
((uint64_t)block->byte[i + 5] << 16) |
((uint64_t)block->byte[i + 4] << 24) |
((uint64_t)block->byte[i + 3] << 32) |
((uint64_t)block->byte[i + 2] << 40) |
((uint64_t)block->byte[i + 1] << 48) |
((uint64_t)block->byte[i] << 56);
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
}
#endif
}
static inline void putword(block *block, size_t i, uint64_t x) {
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
if (I_AM_BIG_ENDIAN) {
block->word[i] = x;
} else if (I_AM_LITTLE_ENDIAN) {
block->word[i] = bswap64(x);
} else {
#endif
i <<= 3;
block->byte[i] = (unsigned char)(x >> 56);
block->byte[i + 1] = (unsigned char)((x >> 48) & 0xff);
block->byte[i + 2] = (unsigned char)((x >> 40) & 0xff);
block->byte[i + 3] = (unsigned char)((x >> 32) & 0xff);
block->byte[i + 4] = (unsigned char)((x >> 24) & 0xff);
block->byte[i + 5] = (unsigned char)((x >> 16) & 0xff);
block->byte[i + 6] = (unsigned char)((x >> 8) & 0xff);
block->byte[i + 7] = (unsigned char)(x & 0xff);
#ifndef ENABLE_DEBUG_WEIRD_ENDIAN
}
#endif
}
static inline void xorblock(block *x, block const *y) {
x->word[0] ^= y->word[0];
x->word[1] ^= y->word[1];
}
/* Doubles `block`, which is 16 bytes representing an element
of GF(2**128) modulo the irreducible polynomial
x**128 + x**7 + x**2 + x + 1. */
static inline void dbl(block *block) {
uint64_t high = getword(block, 0);
uint64_t low = getword(block, 1);
uint64_t high_carry = high & (((uint64_t)1) << 63);
uint64_t low_carry = low & (((uint64_t)1) << 63);
/* Assumes two's-complement arithmetic */
int64_t low_mask = -((int64_t)(high_carry >> 63)) & 0x87;
uint64_t high_mask = low_carry >> 63;
high = (high << 1) | high_mask;
low = (low << 1) ^ (uint64_t)low_mask;
putword(block, 0, high);
putword(block, 1, low);
}
struct AES_SIV_CTX_st {
/* d stores intermediate results of S2V; it corresponds to D from the
pseudocode in section 2.4 of RFC 5297. */
block d;
EVP_CIPHER_CTX *cipher_ctx;
/* SIV_AES_Init() sets up cmac_ctx_init. cmac_ctx is a scratchpad used
by SIV_AES_AssociateData() and SIV_AES_(En|De)cryptFinal. */
CMAC_CTX *cmac_ctx_init, *cmac_ctx;
};
void AES_SIV_CTX_cleanup(AES_SIV_CTX *ctx) {
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
EVP_CIPHER_CTX_reset(ctx->cipher_ctx);
#else
EVP_CIPHER_CTX_cleanup(ctx->cipher_ctx);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && OPENSSL_VERSION_NUMBER <= 0x10100060L
/* Workaround for an OpenSSL bug that causes a double free
if you call CMAC_CTX_cleanup() before CMAC_CTX_free().
https://github.com/openssl/openssl/pull/2798
*/
CMAC_CTX_free(ctx->cmac_ctx_init);
ctx->cmac_ctx_init = CMAC_CTX_new();
CMAC_CTX_free(ctx->cmac_ctx);
ctx->cmac_ctx = CMAC_CTX_new();
#else
CMAC_CTX_cleanup(ctx->cmac_ctx_init);
CMAC_CTX_cleanup(ctx->cmac_ctx);
#endif
OPENSSL_cleanse(&ctx->d, sizeof ctx->d);
}
void AES_SIV_CTX_free(AES_SIV_CTX *ctx) {
if (ctx) {
EVP_CIPHER_CTX_free(ctx->cipher_ctx);
/* Prior to OpenSSL 1.0.2b, CMAC_CTX_free() crashes on NULL */
if (LIKELY(ctx->cmac_ctx_init != NULL)) {
CMAC_CTX_free(ctx->cmac_ctx_init);
}
if (LIKELY(ctx->cmac_ctx != NULL)) {
CMAC_CTX_free(ctx->cmac_ctx);
}
OPENSSL_cleanse(&ctx->d, sizeof ctx->d);
OPENSSL_free(ctx);
}
}
AES_SIV_CTX *AES_SIV_CTX_new(void) {
AES_SIV_CTX *ctx = OPENSSL_malloc(sizeof(struct AES_SIV_CTX_st));
if (UNLIKELY(ctx == NULL)) {
return NULL;
}
ctx->cipher_ctx = EVP_CIPHER_CTX_new();
ctx->cmac_ctx_init = CMAC_CTX_new();
ctx->cmac_ctx = CMAC_CTX_new();
if (UNLIKELY(ctx->cipher_ctx == NULL ||
ctx->cmac_ctx_init == NULL ||
ctx->cmac_ctx == NULL)) {
AES_SIV_CTX_free(ctx);
return NULL;
}
return ctx;
}
int AES_SIV_CTX_copy(AES_SIV_CTX *dst, AES_SIV_CTX const *src) {
memcpy(&dst->d, &src->d, sizeof src->d);
if(UNLIKELY(EVP_CIPHER_CTX_copy(dst->cipher_ctx, src->cipher_ctx)
!= 1)) {
return 0;
}
if (UNLIKELY(CMAC_CTX_copy(dst->cmac_ctx_init, src->cmac_ctx_init)
!= 1)) {
return 0;
}
/* Not necessary to copy cmac_ctx since it's just temporary
* storage */
return 1;
}
int AES_SIV_Init(AES_SIV_CTX *ctx, unsigned char const *key, size_t key_len) {
static const unsigned char zero[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
size_t out_len;
int ret = 0;
ct_poison(key, key_len);
switch (key_len) {
case 32:
if (UNLIKELY(CMAC_Init(ctx->cmac_ctx_init, key, 16,
EVP_aes_128_cbc(), NULL) != 1)) {
goto done;
}
if (UNLIKELY(EVP_EncryptInit_ex(ctx->cipher_ctx,
EVP_aes_128_ctr(),
NULL, key + 16, NULL) != 1)) {
goto done;
}
break;
case 48:
if (UNLIKELY(CMAC_Init(ctx->cmac_ctx_init, key, 24,
EVP_aes_192_cbc(), NULL) != 1)) {
goto done;
}
if (UNLIKELY(EVP_EncryptInit_ex(ctx->cipher_ctx,
EVP_aes_192_ctr(),
NULL, key + 24, NULL) != 1)) {
goto done;
}
break;
case 64:
if (UNLIKELY(CMAC_Init(ctx->cmac_ctx_init, key, 32,
EVP_aes_256_cbc(), NULL) != 1)) {
goto done;
}
if (UNLIKELY(EVP_EncryptInit_ex(ctx->cipher_ctx,
EVP_aes_256_ctr(),
NULL, key + 32, NULL) != 1)) {
goto done;
}
break;
default:
goto done;
}
if (UNLIKELY(CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init) != 1)) {
goto done;
}
if (UNLIKELY(CMAC_Update(ctx->cmac_ctx, zero, sizeof zero) != 1)) {
goto done;
}
out_len = sizeof ctx->d;
if (UNLIKELY(CMAC_Final(ctx->cmac_ctx, ctx->d.byte, &out_len) != 1)) {
goto done;
}
debug("CMAC(zero)", ctx->d.byte, out_len);
ret = 1;
done:
ct_unpoison(key, key_len);
return ret;
}
int AES_SIV_AssociateData(AES_SIV_CTX *ctx, unsigned char const *data,
size_t len) {
block cmac_out;
size_t out_len = sizeof cmac_out;
int ret = 0;
ct_poison(data, len);
dbl(&ctx->d);
debug("double()", ctx->d.byte, 16);
if (UNLIKELY(CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init) != 1)) {
goto done;
}
if (UNLIKELY(CMAC_Update(ctx->cmac_ctx, data, len) != 1)) {
goto done;
}
if (UNLIKELY(CMAC_Final(ctx->cmac_ctx, cmac_out.byte, &out_len) != 1)) {
goto done;
}
assert(out_len == 16);
debug("CMAC(ad)", cmac_out.byte, 16);
xorblock(&ctx->d, &cmac_out);
debug("xor", ctx->d.byte, 16);
ret = 1;
done:
ct_unpoison(data, len);
return ret;
}
static inline int do_s2v_p(AES_SIV_CTX *ctx, block *out,
unsigned char const* in, size_t len) {
block t;
size_t out_len = sizeof out->byte;
if (UNLIKELY(CMAC_CTX_copy(ctx->cmac_ctx, ctx->cmac_ctx_init) != 1)) {
return 0;
}
if(len >= 16) {
if(UNLIKELY(CMAC_Update(ctx->cmac_ctx, in, len - 16) != 1)) {
return 0;
}
debug("xorend part 1", in, len - 16);
memcpy(&t, in + (len-16), 16);
xorblock(&t, &ctx->d);
debug("xorend part 2", t.byte, 16);
if(UNLIKELY(CMAC_Update(ctx->cmac_ctx, t.byte, 16) != 1)) {
return 0;
}
} else {
size_t i;
memcpy(&t, in, len);
t.byte[len] = 0x80;
for(i = len + 1; i < 16; i++) {
t.byte[i] = 0;
}
debug("pad", t.byte, 16);
dbl(&ctx->d);
xorblock(&t, &ctx->d);
debug("xor", t.byte, 16);
if(UNLIKELY(CMAC_Update(ctx->cmac_ctx, t.byte, 16) != 1)) {
return 0;
}
}
if(UNLIKELY(CMAC_Final(ctx->cmac_ctx, out->byte, &out_len) != 1)) {
return 0;
}
assert(out_len == 16);
debug("CMAC(final)", out->byte, 16);
return 1;
}
static inline int do_encrypt(EVP_CIPHER_CTX *ctx, unsigned char *out,
unsigned char const *in, size_t len, block *icv) {
#ifdef ENABLE_DEBUG_TINY_CHUNK_SIZE
const int chunk_size = 7;
#else
const int chunk_size = 1 << 30;
#endif
size_t len_remaining = len;
int out_len;
int ret;
if(UNLIKELY(EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, icv->byte)
!= 1)) {
return 0;
}
while(UNLIKELY(len_remaining > (size_t)chunk_size)) {
out_len = chunk_size;
if(UNLIKELY(EVP_EncryptUpdate(ctx, out, &out_len, in, out_len)
!= 1)) {
return 0;
}
assert(out_len == chunk_size);
out += out_len;
in += out_len;
len_remaining -= (size_t)out_len;
}
out_len = (int)len_remaining;
ret = EVP_EncryptUpdate(ctx, out, &out_len, in, out_len);
assert(!ret || out_len == (int)len_remaining);
return ret;
}
int AES_SIV_EncryptFinal(AES_SIV_CTX *ctx, unsigned char *v_out,
unsigned char *c_out, unsigned char const *plaintext,
size_t len) {
block q;
int ret = 0;
ct_poison(plaintext, len);
if(UNLIKELY(do_s2v_p(ctx, &q, plaintext, len) != 1)) {
goto done;
}
ct_unpoison(&q, sizeof q);
memcpy(v_out, &q, 16);
q.byte[8] &= 0x7f;
q.byte[12] &= 0x7f;
if(UNLIKELY(do_encrypt(ctx->cipher_ctx, c_out, plaintext, len, &q)
!= 1)) {
goto done;
}
ret = 1;
debug("ciphertext", c_out, len);
done:
ct_unpoison(plaintext, len);
ct_unpoison(c_out, len);
ct_unpoison(v_out, 16);
return ret;
}
int AES_SIV_DecryptFinal(AES_SIV_CTX *ctx, unsigned char *out,
unsigned char const *v, unsigned char const *c,
size_t len) {
block t, q;
size_t i;
uint64_t result;
int ret = 0;
ct_poison(c, len);
memcpy(&q, v, 16);
q.byte[8] &= 0x7f;
q.byte[12] &= 0x7f;
if(UNLIKELY(do_encrypt(ctx->cipher_ctx, out, c, len, &q) != 1)) {
goto done;
}
debug("plaintext", out, len);
if(UNLIKELY(do_s2v_p(ctx, &t, out, len) != 1)) {
goto done;
}
for (i = 0; i < 16; i++) {
t.byte[i] ^= v[i];
}
result = t.word[0] | t.word[1];
ct_unpoison(&result, sizeof result);
ret = !result;
if(ret) {
ct_unpoison(out, len);
} else {
OPENSSL_cleanse(out, len);
}
done:
ct_unpoison(c, len);
return ret;
}
int AES_SIV_Encrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *plaintext, size_t plaintext_len,
unsigned char const *ad, size_t ad_len) {
if (UNLIKELY(*out_len < plaintext_len + 16)) {
return 0;
}
*out_len = plaintext_len + 16;
if (UNLIKELY(AES_SIV_Init(ctx, key, key_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_AssociateData(ctx, ad, ad_len) != 1)) {
return 0;
}
if (nonce != NULL &&
UNLIKELY(AES_SIV_AssociateData(ctx, nonce, nonce_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_EncryptFinal(ctx, out, out + 16, plaintext,
plaintext_len) != 1)) {
return 0;
}
debug("IV || C", out, *out_len);
return 1;
}
int AES_SIV_Decrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *ciphertext, size_t ciphertext_len,
unsigned char const *ad, size_t ad_len) {
if (UNLIKELY(ciphertext_len < 16)) {
return 0;
}
if (UNLIKELY(*out_len < ciphertext_len - 16)) {
return 0;
}
*out_len = ciphertext_len - 16;
if (UNLIKELY(AES_SIV_Init(ctx, key, key_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_AssociateData(ctx, ad, ad_len) != 1)) {
return 0;
}
if (nonce != NULL &&
UNLIKELY(AES_SIV_AssociateData(ctx, nonce, nonce_len) != 1)) {
return 0;
}
if (UNLIKELY(AES_SIV_DecryptFinal(ctx, out, ciphertext, ciphertext + 16,
ciphertext_len - 16) != 1)) {
return 0;
}
debug("plaintext", out, *out_len);
return 1;
}

View File

@ -1,57 +0,0 @@
/* Copyright (c) 2017-2019 Akamai Technologies, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef AES_SIV_H_
#define AES_SIV_H_
#include <stddef.h>
#define LIBAES_SIV_VERSION_MAJOR 1
#define LIBAES_SIV_VERSION_MINOR 0
#define LIBAES_SIV_VERSION_PATCH 1
#define LIBAES_SIV_VERSION ((LIBAES_SIV_VERSION_MAJOR << 16) + \
(LIBAES_SIV_VERSION_MINOR << 8) + \
LIBAES_SIV_VERSION_PATCH)
#ifdef __cplusplus
extern "C" {
#endif
typedef struct AES_SIV_CTX_st AES_SIV_CTX;
AES_SIV_CTX *AES_SIV_CTX_new(void);
int AES_SIV_CTX_copy(AES_SIV_CTX *dst, AES_SIV_CTX const *src);
void AES_SIV_CTX_cleanup(AES_SIV_CTX *ctx);
void AES_SIV_CTX_free(AES_SIV_CTX *ctx);
int AES_SIV_Init(AES_SIV_CTX *ctx, unsigned char const *key, size_t key_len);
int AES_SIV_AssociateData(AES_SIV_CTX *ctx, unsigned char const *data,
size_t len);
int AES_SIV_EncryptFinal(AES_SIV_CTX *ctx, unsigned char *v_out,
unsigned char *c_out, unsigned char const *plaintext,
size_t len);
int AES_SIV_DecryptFinal(AES_SIV_CTX *ctx, unsigned char *out,
unsigned char const *v, unsigned char const *c,
size_t len);
int AES_SIV_Encrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *plaintext, size_t plaintext_len,
unsigned char const *ad, size_t ad_len);
int AES_SIV_Decrypt(AES_SIV_CTX *ctx, unsigned char *out, size_t *out_len,
unsigned char const *key, size_t key_len,
unsigned char const *nonce, size_t nonce_len,
unsigned char const *ciphertext, size_t ciphertext_len,
unsigned char const *ad, size_t ad_len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,19 +0,0 @@
#ifndef AES_SIV_CONFIG_H_
#define AES_SIV_CONFIG_H_
/* Enable ct_poison() and ct_unpoison() hooks for testing with
ctgrind. */
/* #undef ENABLE_CTGRIND */
/* Enable this to get test coverage for the portable versions of
putword() and getword() when you don't happen to have a PDP-11
in your test farm.
*/
/* #undef ENABLE_DEBUG_WEIRD_ENDIAN */
/* Enable this to get test coverage for the while loop in do_encrypt()
without having to have a multi-gigabyte test case that'll take
forever for Valgrind to crunch through
*/
/* #undef ENABLE_DEBUG_TINY_CHUNK_SIZE */
#endif

View File

@ -3,3 +3,4 @@
tests export-ignore
hashtable_tests export-ignore
shell.nix export-ignore
*.patch -text

View File

@ -1,3 +1,5 @@
# Configuration Result
/config.mk
/include/config.h
/include/ca-bundle.h
/include/ivory.h

View File

@ -1,4 +1,5 @@
include config.mk
include $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.mk))
jets = jets/tree.c $(wildcard jets/*/*.c)
noun = $(wildcard noun/*.c)
@ -9,7 +10,9 @@ worker = $(wildcard worker/*.c)
tests = $(wildcard tests/*.c)
bench = $(wildcard bench/*.c)
common = $(jets) $(noun) $(ur) $(vere)
compat := $(foreach dir,$(compat),$(wildcard compat/$(dir)/*.c))
common = $(jets) $(noun) $(ur) $(vere) $(compat)
headers = $(shell find include -type f)
common_objs = $(shell echo $(common) | sed 's/\.c/.o/g')
@ -29,7 +32,7 @@ CFLAGS := $(CFLAGS)
################################################################################
.PHONY: all test clean mkproper
.PHONY: all test clean mrproper
################################################################################
@ -74,9 +77,11 @@ build/urbit-worker: $(common_objs) $(worker_objs)
@mkdir -p ./build
@$(CC) $^ $(LDFLAGS) -o $@
%.o: %.c $(headers)
# CCDEPS and CCEXTRA are empty except in MingW build,
# which uses them to inject a C source transform step
%.o: %.c $(headers) $(CCDEPS)
@echo CC $<
@$(CC) -I./include $(CFLAGS) -c $< -o $@
@$(CC) -I./include $(CFLAGS) $< $(CCEXTRA) -c -o $@
tags: $(all_srcs) $(headers)
ctags $^

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
# support running off a tarball that doesn't contain binary pills
(( $($1 ../../bin/ivory.pill) > 512 )) || curl -L https://github.com/urbit/urbit/raw/urbit-v$URBIT_VERSION/bin/ivory.pill > ../../bin/ivory.pill
poor_mans_xxd () {
cch=0
echo "unsigned char $2[] = {"
while IFS='' read line
do
for i in $line
do
echo -n " 0x$i,"
cch=$((cch+1))
done
echo
done < <(od -An -v -tx1 $1)
echo "};"
echo "unsigned int $2_len = $cch;"
}
[ -e include/ca-bundle.h ] || poor_mans_xxd $2 include_ca_bundle_crt >include/ca-bundle.h
[ -e include/ivory.h ] || poor_mans_xxd ../../bin/ivory.pill u3_Ivory_pill >include/ivory.h

View File

@ -0,0 +1,14 @@
# paths to brew packages
CFLAGS := $(CFLAGS) -I/opt/homebrew/include
LDFLAGS := $(LDFLAGS) -L/opt/homebrew/lib
# force linker to use static libraries
LDFLAGS := $(shell compat/m1brew/use-static-libs.sh $(LDFLAGS))
# add extra osx libraries
LDFLAGS := $(LDFLAGS) -framework SystemConfiguration
ifdef debug
CFLAGS := $(CFLAGS) -O0 -g
else
# clang hangs on noun/allocate.c if -g is specified with -O3
CFLAGS := $(CFLAGS) -O3
endif

View File

@ -0,0 +1,12 @@
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -15,7 +15,7 @@ do
log "Trying IMPL=$IMPL"
if IMPL=$impl make >/dev/null 2>/dev/null
- then sed -i 's|$(error IMPL must be set)|IMPL='"$impl"'|' Makefile
+ then sed -i "" 's|$(error IMPL must be set)|IMPL='"$impl"'|' Makefile
log "IMPL=$IMPL works"
exit 0
else log "IMPL=$IMPL failed"

View File

@ -0,0 +1,13 @@
diff --git a/makefile b/makefile
--- a/makefile
+++ b/makefile
@@ -12,5 +12,9 @@ shared: murmur3.c murmur3.h
$(CC) -fPIC -O3 -c murmur3.c
$(CC) -shared -Wl,--export-dynamic murmur3.o -o libmurmur3.so
+static: murmur3.c murmur3.h
+ $(CC) -fPIC -O3 -c murmur3.c
+ $(AR) rcs libmurmur3.a murmur3.o
+
clean:
rm -rf example *.o *.so

View File

@ -0,0 +1,85 @@
diff --git a/build/template-FAST_INT64/Makefile b/build/template-FAST_INT64/Makefile
--- a/build/template-FAST_INT64/Makefile
+++ b/build/template-FAST_INT64/Makefile
@@ -34,28 +34,27 @@
#
#=============================================================================
-# Edit lines marked with `==>'. See "SoftFloat-source.html".
+SOURCE_DIR ?= ../../source
+SPECIALIZE_TYPE ?= 8086-SSE
-==> SOURCE_DIR ?= ../../source
-==> SPECIALIZE_TYPE ?= 8086
+SOFTFLOAT_OPTS ?= \
+ -DSOFTFLOAT_ROUND_ODD -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 \
+ -DSOFTFLOAT_FAST_DIV64TO32
-==> SOFTFLOAT_OPTS ?= \
-==> -DSOFTFLOAT_ROUND_ODD -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 \
-==> -DSOFTFLOAT_FAST_DIV64TO32
+DELETE = rm -f
+C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
+COMPILE_C = \
+ cc -c -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
+MAKELIB = ar crs $@
+LIBNAME = libsoftfloat3
-==> DELETE = rm -f
-==> C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
-==> COMPILE_C = \
-==> cc -c -DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
-==> MAKELIB = ar crs $@
+OBJ = .o
+LIB = .a
-==> OBJ = .o
-==> LIB = .a
-
-==> OTHER_HEADERS =
+OTHER_HEADERS =
.PHONY: all
-all: softfloat$(LIB)
+all: $(LIBNAME)$(LIB)
OBJS_PRIMITIVES = \
s_eq128$(OBJ) \
@@ -381,11 +380,11 @@ $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c
$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c
$(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c
-softfloat$(LIB): $(OBJS_ALL)
+$(LIBNAME)$(LIB): $(OBJS_ALL)
$(DELETE) $@
$(MAKELIB) $^
.PHONY: clean
clean:
- $(DELETE) $(OBJS_ALL) softfloat$(LIB)
+ $(DELETE) $(OBJS_ALL) $(LIBNAME)$(LIB)
diff --git a/build/template-FAST_INT64/platform.h b/build/template-FAST_INT64/platform.h
--- a/build/template-FAST_INT64/platform.h
+++ b/build/template-FAST_INT64/platform.h
@@ -34,17 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
-// Edit lines marked with `==>'. See "SoftFloat-source.html".
-
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-==> #define LITTLEENDIAN 1
+#define LITTLEENDIAN 1
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-==> #define INLINE inline
+#define INLINE inline
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
-==> #define THREAD_LOCAL _Thread_local
+#define THREAD_LOCAL _Thread_local

View File

@ -0,0 +1,23 @@
#!/bin/bash
set -euo pipefail
declare -a ldirs
for i in $@
do
case $i in
-L*) ldirs+=(${i:2});;
esac
done
for i in $@
do
case $i in
-l*)
lib=$(find ${ldirs[@]} -name lib${i:2}.a)
if [ "$lib" != "" ]
then
echo $lib
else
echo $i
fi;;
*) echo $i;;
esac
done

View File

@ -0,0 +1,355 @@
#include "c/portable.h"
#include <fcntl.h>
#include <sys/utime.h>
#include <windows.h>
// set default CRT file mode to binary
// note that mingw binmode.o does nothing
#undef _fmode
int _fmode = _O_BINARY;
// set standard I/O fds to binary too, because
// MSVCRT creates them before MingW sets _fmode
static void __attribute__ ((constructor)) _set_stdio_to_binary()
{
_setmode(0, _O_BINARY);
_setmode(1, _O_BINARY);
_setmode(2, _O_BINARY);
}
// from https://github.com/git/git/blob/master/compat/mingw.c
// -----------------------------------------------------------------------
int err_win_to_posix(DWORD winerr)
{
int error = ENOSYS;
switch(winerr) {
case ERROR_ACCESS_DENIED: error = EACCES; break;
case ERROR_ACCOUNT_DISABLED: error = EACCES; break;
case ERROR_ACCOUNT_RESTRICTION: error = EACCES; break;
case ERROR_ALREADY_ASSIGNED: error = EBUSY; break;
case ERROR_ALREADY_EXISTS: error = EEXIST; break;
case ERROR_ARITHMETIC_OVERFLOW: error = ERANGE; break;
case ERROR_BAD_COMMAND: error = EIO; break;
case ERROR_BAD_DEVICE: error = ENODEV; break;
case ERROR_BAD_DRIVER_LEVEL: error = ENXIO; break;
case ERROR_BAD_EXE_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_FORMAT: error = ENOEXEC; break;
case ERROR_BAD_LENGTH: error = EINVAL; break;
case ERROR_BAD_PATHNAME: error = ENOENT; break;
case ERROR_BAD_PIPE: error = EPIPE; break;
case ERROR_BAD_UNIT: error = ENODEV; break;
case ERROR_BAD_USERNAME: error = EINVAL; break;
case ERROR_BROKEN_PIPE: error = EPIPE; break;
case ERROR_BUFFER_OVERFLOW: error = ENAMETOOLONG; break;
case ERROR_BUSY: error = EBUSY; break;
case ERROR_BUSY_DRIVE: error = EBUSY; break;
case ERROR_CALL_NOT_IMPLEMENTED: error = ENOSYS; break;
case ERROR_CANNOT_MAKE: error = EACCES; break;
case ERROR_CANTOPEN: error = EIO; break;
case ERROR_CANTREAD: error = EIO; break;
case ERROR_CANTWRITE: error = EIO; break;
case ERROR_CRC: error = EIO; break;
case ERROR_CURRENT_DIRECTORY: error = EACCES; break;
case ERROR_DEVICE_IN_USE: error = EBUSY; break;
case ERROR_DEV_NOT_EXIST: error = ENODEV; break;
case ERROR_DIRECTORY: error = EINVAL; break;
case ERROR_DIR_NOT_EMPTY: error = ENOTEMPTY; break;
case ERROR_DISK_CHANGE: error = EIO; break;
case ERROR_DISK_FULL: error = ENOSPC; break;
case ERROR_DRIVE_LOCKED: error = EBUSY; break;
case ERROR_ENVVAR_NOT_FOUND: error = EINVAL; break;
case ERROR_EXE_MARKED_INVALID: error = ENOEXEC; break;
case ERROR_FILENAME_EXCED_RANGE: error = ENAMETOOLONG; break;
case ERROR_FILE_EXISTS: error = EEXIST; break;
case ERROR_FILE_INVALID: error = ENODEV; break;
case ERROR_FILE_NOT_FOUND: error = ENOENT; break;
case ERROR_GEN_FAILURE: error = EIO; break;
case ERROR_HANDLE_DISK_FULL: error = ENOSPC; break;
case ERROR_INSUFFICIENT_BUFFER: error = ENOMEM; break;
case ERROR_INVALID_ACCESS: error = EACCES; break;
case ERROR_INVALID_ADDRESS: error = EFAULT; break;
case ERROR_INVALID_BLOCK: error = EFAULT; break;
case ERROR_INVALID_DATA: error = EINVAL; break;
case ERROR_INVALID_DRIVE: error = ENODEV; break;
case ERROR_INVALID_EXE_SIGNATURE: error = ENOEXEC; break;
case ERROR_INVALID_FLAGS: error = EINVAL; break;
case ERROR_INVALID_FUNCTION: error = ENOSYS; break;
case ERROR_INVALID_HANDLE: error = EBADF; break;
case ERROR_INVALID_LOGON_HOURS: error = EACCES; break;
case ERROR_INVALID_NAME: error = EINVAL; break;
case ERROR_INVALID_OWNER: error = EINVAL; break;
case ERROR_INVALID_PARAMETER: error = EINVAL; break;
case ERROR_INVALID_PASSWORD: error = EPERM; break;
case ERROR_INVALID_PRIMARY_GROUP: error = EINVAL; break;
case ERROR_INVALID_SIGNAL_NUMBER: error = EINVAL; break;
case ERROR_INVALID_TARGET_HANDLE: error = EIO; break;
case ERROR_INVALID_WORKSTATION: error = EACCES; break;
case ERROR_IO_DEVICE: error = EIO; break;
case ERROR_IO_INCOMPLETE: error = EINTR; break;
case ERROR_LOCKED: error = EBUSY; break;
case ERROR_LOCK_VIOLATION: error = EACCES; break;
case ERROR_LOGON_FAILURE: error = EACCES; break;
case ERROR_MAPPED_ALIGNMENT: error = EINVAL; break;
case ERROR_META_EXPANSION_TOO_LONG: error = E2BIG; break;
case ERROR_MORE_DATA: error = EPIPE; break;
case ERROR_NEGATIVE_SEEK: error = ESPIPE; break;
case ERROR_NOACCESS: error = EFAULT; break;
case ERROR_NONE_MAPPED: error = EINVAL; break;
case ERROR_NOT_ENOUGH_MEMORY: error = ENOMEM; break;
case ERROR_NOT_READY: error = EAGAIN; break;
case ERROR_NOT_SAME_DEVICE: error = EXDEV; break;
case ERROR_NO_DATA: error = EPIPE; break;
case ERROR_NO_MORE_SEARCH_HANDLES: error = EIO; break;
case ERROR_NO_PROC_SLOTS: error = EAGAIN; break;
case ERROR_NO_SUCH_PRIVILEGE: error = EACCES; break;
case ERROR_OPEN_FAILED: error = EIO; break;
case ERROR_OPEN_FILES: error = EBUSY; break;
case ERROR_OPERATION_ABORTED: error = EINTR; break;
case ERROR_OUTOFMEMORY: error = ENOMEM; break;
case ERROR_PASSWORD_EXPIRED: error = EACCES; break;
case ERROR_PATH_BUSY: error = EBUSY; break;
case ERROR_PATH_NOT_FOUND: error = ENOENT; break;
case ERROR_PIPE_BUSY: error = EBUSY; break;
case ERROR_PIPE_CONNECTED: error = EPIPE; break;
case ERROR_PIPE_LISTENING: error = EPIPE; break;
case ERROR_PIPE_NOT_CONNECTED: error = EPIPE; break;
case ERROR_PRIVILEGE_NOT_HELD: error = EACCES; break;
case ERROR_READ_FAULT: error = EIO; break;
case ERROR_SEEK: error = EIO; break;
case ERROR_SEEK_ON_DEVICE: error = ESPIPE; break;
case ERROR_SHARING_BUFFER_EXCEEDED: error = ENFILE; break;
case ERROR_SHARING_VIOLATION: error = EACCES; break;
case ERROR_STACK_OVERFLOW: error = ENOMEM; break;
case ERROR_SUCCESS: error = 0; break;
case ERROR_SWAPERROR: error = ENOENT; break;
case ERROR_TOO_MANY_MODULES: error = EMFILE; break;
case ERROR_TOO_MANY_OPEN_FILES: error = EMFILE; break;
case ERROR_UNRECOGNIZED_MEDIA: error = ENXIO; break;
case ERROR_UNRECOGNIZED_VOLUME: error = ENODEV; break;
case ERROR_WAIT_NO_CHILDREN: error = ECHILD; break;
case ERROR_WRITE_FAULT: error = EIO; break;
case ERROR_WRITE_PROTECT: error = EROFS; break;
}
return error;
}
// from msys2 mingw-packages-dev patches
// -----------------------------------------------------------------------
static DWORD __map_mmap_prot_page(const int prot)
{
DWORD protect = 0;
if (prot == PROT_NONE)
return protect;
if ((prot & PROT_EXEC) != 0)
{
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
}
else
{
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_READWRITE : PAGE_READONLY;
}
return protect;
}
static DWORD __map_mmap_prot_file(const int prot)
{
DWORD desiredAccess = 0;
if (prot == PROT_NONE)
return desiredAccess;
if ((prot & PROT_READ) != 0)
desiredAccess |= FILE_MAP_READ;
if ((prot & PROT_WRITE) != 0)
desiredAccess |= FILE_MAP_WRITE;
if ((prot & PROT_EXEC) != 0)
desiredAccess |= FILE_MAP_EXECUTE;
return desiredAccess;
}
void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
HANDLE fm, h;
void * map = MAP_FAILED;
const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
const DWORD protect = __map_mmap_prot_page(prot);
const DWORD desiredAccess = __map_mmap_prot_file(prot);
errno = 0;
if (len == 0
/* Usupported protection combinations */
|| prot == PROT_EXEC)
{
errno = EINVAL;
return MAP_FAILED;
}
if ((flags & MAP_ANON) == 0)
{
h = (HANDLE)_get_osfhandle(fildes);
if (h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return MAP_FAILED;
}
}
else h = INVALID_HANDLE_VALUE;
fm = CreateFileMapping(h, NULL, protect, 0, len, NULL);
if (fm == NULL)
{
errno = err_win_to_posix(GetLastError());
return MAP_FAILED;
}
map = MapViewOfFileEx(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len, addr);
errno = err_win_to_posix(GetLastError());
CloseHandle(fm);
if (map == NULL)
return MAP_FAILED;
if ((flags & MAP_FIXED) != 0 && map != addr)
{
UnmapViewOfFile(map);
errno = EEXIST;
return MAP_FAILED;
}
return map;
}
int munmap(void *addr, size_t len)
{
if (UnmapViewOfFile(addr))
return 0;
errno = err_win_to_posix(GetLastError());
return -1;
}
int msync(void *addr, size_t len, int flags)
{
if (FlushViewOfFile(addr, len))
return 0;
errno = err_win_to_posix(GetLastError());
return -1;
}
// -----------------------------------------------------------------------
// vere uses kill() only to kill lockfile owner with SIGTERM or SIGKILL
// Windows does not have signals, so I handle SIGKILL as TerminateProcess()
// and return an error in all other cases
int kill(pid_t pid, int sig)
{
if (pid > 0 && sig == SIGKILL) {
HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
if (TerminateProcess(h, -1)) {
CloseHandle(h);
return 0;
}
errno = err_win_to_posix(GetLastError());
CloseHandle(h);
return -1;
}
errno = EINVAL;
return -1;
}
// libgcc built for mingw has included an implementation of mprotect
// via VirtualProtect since olden days, but it takes int rather than size_t
// and therefore fails or does unexpected things for >2GB blocks on 64-bit
// https://github.com/gcc-mirror/gcc/blob/master/libgcc/libgcc2.c
int mprotect (void *addr, size_t len, int prot)
{
DWORD np, op;
if (prot == (PROT_READ | PROT_WRITE | PROT_EXEC))
np = PAGE_EXECUTE_READWRITE;
else if (prot == (PROT_READ | PROT_EXEC))
np = PAGE_EXECUTE_READ;
else if (prot == (PROT_EXEC))
np = PAGE_EXECUTE;
else if (prot == (PROT_READ | PROT_WRITE))
np = PAGE_READWRITE;
else if (prot == (PROT_READ))
np = PAGE_READONLY;
else if (prot == 0)
np = PAGE_NOACCESS;
else
{
errno = EINVAL;
return -1;
}
if (VirtualProtect (addr, len, np, &op))
return 0;
// NB: return code of ntdll!RtlGetLastNtStatus() is useful
// for diagnosing obscure VirtualProtect failures
errno = err_win_to_posix(GetLastError());
return -1;
}
int utimes(const char *path, const struct timeval times[2])
{
struct _utimbuf utb = {.actime = times[0].tv_sec, .modtime = times[1].tv_sec};
return _utime(path, &utb);
}
int fdatasync(int fildes)
{
HANDLE h = (HANDLE)_get_osfhandle(fildes);
if (h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return -1;
}
if (FlushFileBuffers(h))
{
errno = 0;
return 0;
}
else
{
errno = err_win_to_posix(GetLastError());
return -1;
}
}
intmax_t mdb_get_filesize(HANDLE han_u)
{
LARGE_INTEGER li;
GetFileSizeEx(han_u, &li);
return li.QuadPart;
}
char *realpath(const char *path, char *resolved_path)
{
// TODO
return strdup(path);
}

View File

@ -0,0 +1,18 @@
#ifndef _MINGW_IO_H
#define _MINGW_IO_H
#define mkdir(A, B) mkdir(A)
char *realpath(const char *path, char *resolved_path);
int fdatasync(int fd);
int utimes(const char *path, const struct timeval times[2]);
int kill(pid_t pid, int signum);
#define SIGUSR1 10
#define SIGALRM 14
#define SIGVTALRM 26
#define SIGSTK 31
#define SIG_COUNT 32
#endif//_MINGW_IO_H

View File

@ -0,0 +1,17 @@
# increase default thread stack size and link Windows implibs
LDFLAGS := $(LDFLAGS) -Wl,--stack,67108864 -lbcrypt -lntdll -lws2_32
# libcurl
CFLAGS := $(CFLAGS) -DCURL_STATICLIB
LDFLAGS := $(LDFLAGS) -lzstd -lcrypt32
# libh2o
CFLAGS := $(CFLAGS) -DH2O_NO_UNIX_SOCKETS
# libuv
LDFLAGS := $(LDFLAGS) -luserenv -liphlpapi -lpsapi
# secp256k1, due to _FORTIFY_SOURCE
LDFLAGS := $(LDFLAGS) -lssp
ifdef debug
CFLAGS := $(CFLAGS) -O0 -g
else
CFLAGS := $(CFLAGS) -O3 -g
endif

View File

@ -0,0 +1,7 @@
#include <signal.h>
// initialize msvcrt signals early, otherwise Ctrl-C does nothing
static void __attribute__ ((constructor)) _init_crt_signals()
{
signal(SIGINT, SIG_DFL);
}

View File

@ -0,0 +1,116 @@
#include "all.h"
#include "vere/vere.h"
/* _dup_std_handle(): creates an inheritable duplicate of a standard handle.
*/
static BOOL
_dup_std_handle(HANDLE* new_u, DWORD typ_u)
{
DWORD dum_u;
HANDLE han_u = GetStdHandle(typ_u);
BOOL con_u = GetConsoleMode(han_u, &dum_u);
if ( con_u ) {
han_u = (HANDLE)_get_osfhandle(open(c3_dev_null, O_RDWR, 0));
}
if ( !DuplicateHandle(GetCurrentProcess(), han_u, GetCurrentProcess(), new_u, 0, TRUE, DUPLICATE_SAME_ACCESS) ) {
fprintf(stderr, "vere: DuplicateHandle(%d): %d\r\n", typ_u, GetLastError());
exit(1);
}
return con_u;
}
/* _on_boot_completed_cb: invoked when the ship has finished booting.
*/
static void _on_boot_completed_cb() {
HANDLE hin_u = GetStdHandle(STD_INPUT_HANDLE);
SetEvent(hin_u);
CloseHandle(hin_u);
}
/* u3_daemon_init(): platform-specific daemon mode initialization.
*/
void
u3_daemon_init()
{
// detect if this process is the child daemon process
//
if ( ResetEvent(GetStdHandle(STD_INPUT_HANDLE)) ) {
u3_Host.bot_f = _on_boot_completed_cb;
return;
}
STARTUPINFOW psi_u;
ZeroMemory(&psi_u, sizeof(psi_u));
psi_u.cb = sizeof(psi_u);
psi_u.dwFlags = STARTF_USESTDHANDLES;
// duplicate standard output and error handles for the child process,
// replacing any raw console handles with handles to /dev/null
// print a warning if raw console output detected
//
// On Windows, console handles become invalid once the console is
// detached. This will cause urbit terminal output to fail. libuv
// provides no way of changing the handle of an open uv_pipe_handle,
// and Windows has no equivalent of dup2() for handles, so I cannot
// substitute a /dev/null handle once the terminal is initialized.
// It is possible to create an anonymous pipe and have the child
// process take over its drain end after it signals that the ship
// has booted, but -d is intended for background operation anyway
// and does not seem to warrant the added complexity.
//
if ( _dup_std_handle(&psi_u.hStdOutput, STD_OUTPUT_HANDLE) |
_dup_std_handle(&psi_u.hStdError, STD_ERROR_HANDLE) )
{
fprintf(stderr, "vere: -d used from a Windows console without redirection\r\n"
" no output from the daemon process will be visible\r\n");
fflush(stderr);
}
// create an event for the child process to signal
// the parent that the ship has finished booting
// pass the handle as "stdin" (otherwise unused with -d)
//
SECURITY_ATTRIBUTES sa_u = {sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
if ( !(psi_u.hStdInput = CreateEvent(&sa_u, TRUE, FALSE, NULL)) ) {
fprintf(stderr, "vere: CreateEvent: %d\r\n", GetLastError());
exit(1);
}
// create the child process with the same command line as parent
// it will start, re-parse the command line, and call u3_daemon_init
//
PROCESS_INFORMATION ppi_u;
if ( !CreateProcessW(NULL, _wcsdup(GetCommandLineW()), NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &psi_u, &ppi_u) ) {
fprintf(stderr, "vere: CreateProcess: %d\r\n", GetLastError());
exit(1);
}
CloseHandle(ppi_u.hThread);
// wait for the child process to exit or to signal the event
//
DWORD exi_u;
HANDLE han_u[2] = {ppi_u.hProcess, psi_u.hStdInput};
switch ( WaitForMultipleObjects(2, han_u, FALSE, INFINITE) ) {
case WAIT_OBJECT_0:
// the child process exited prematurely, propagate its exit code
//
if ( GetExitCodeProcess(ppi_u.hProcess, &exi_u) ) {
exit(exi_u);
}
fprintf(stderr, "vere: GetExitCodeProcess: %d\r\n", GetLastError());
exit(1);
case WAIT_OBJECT_0 + 1:
// the child process has finished booting, exit normally
//
exit(0);
default:
fprintf(stderr, "vere: WaitForMultipleObjects: %d\r\n", GetLastError());
exit(1);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
diff --git a/mdb.c b/mdb.c
--- a/mdb.c
+++ b/mdb.c
@@ -1707,28 +1707,27 @@ static char *const mdb_errstr[] = {
"MDB_PROBLEM: Unexpected problem - txn should abort",
};
-char *
-mdb_strerror(int err)
+void
+mdb_logerror(FILE* f, int err, const char* fmt, ...)
{
-#ifdef _WIN32
- /** HACK: pad 4KB on stack over the buf. Return system msgs in buf.
- * This works as long as no function between the call to mdb_strerror
- * and the actual use of the message uses more than 4K of stack.
- */
-#define MSGSIZE 1024
-#define PADSIZE 4096
- char buf[MSGSIZE+PADSIZE], *ptr = buf;
-#endif
+ va_list ap;
+ va_start(ap, fmt);
+ vfprintf(f, fmt, ap);
+ va_end(ap);
+
int i;
if (!err)
- return ("Successful return: 0");
+ {
+ fprintf(stderr, ": %s\r\n", "Successful return: 0");
+ return;
+ }
if (err >= MDB_KEYEXIST && err <= MDB_LAST_ERRCODE) {
i = err - MDB_KEYEXIST;
- return mdb_errstr[i];
+ fprintf(stderr, ": %s\r\n", mdb_errstr[i]);
+ return;
}
-#ifdef _WIN32
/* These are the C-runtime error codes we use. The comment indicates
* their numeric value, and the Win32 error they would correspond to
* if the error actually came from a Win32 API. A major mess, we should
@@ -1742,18 +1741,20 @@ mdb_strerror(int err)
case EBUSY: /* 16, CURRENT_DIRECTORY */
case EINVAL: /* 22, BAD_COMMAND */
case ENOSPC: /* 28, OUT_OF_PAPER */
- return strerror(err);
+ fprintf(stderr, ": %s\r\n", strerror(err));
default:
;
}
- buf[0] = 0;
- FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ LPSTR ptr;
+ if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, err, 0, ptr, MSGSIZE, (va_list *)buf+MSGSIZE);
- return ptr;
-#else
- return strerror(err);
-#endif
+ NULL, err, 0, (LPSTR)&ptr, sizeof (LPSTR), NULL))
+ {
+ fprintf(stderr, ": %s\r\n", ptr);
+ LocalFree(ptr);
+ } else
+ fprintf(stderr, ": <%d>\r\n", err);
}
/** assert(3) variant in cursor context */

View File

@ -0,0 +1,26 @@
#ifndef _SYS_MMAN_H
#define _SYS_MMAN_H
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int munmap(void *addr, size_t length);
int msync(void *addr, size_t length, int flags);
int mprotect(void *addr, size_t len, int prot);
#define PROT_NONE 0x00 /* No access. */
#define PROT_READ 0x01 /* Pages can be read. */
#define PROT_WRITE 0x02 /* Pages can be written. */
#define PROT_EXEC 0x04 /* Pages can be executed. */
#define MAP_FILE 0x0001 /* Mapped from a file or device. */
#define MAP_ANON 0x0002 /* Allocated from anonymous virtual memory. */
#define MAP_TYPE 0x000f /* Mask for type field. */
#define MAP_SHARED 0x0010 /* Share changes. */
#define MAP_PRIVATE 0x0000 /* Changes private; copy pages on write. */
#define MAP_FIXED 0x0100 /* Map address must be exactly as requested. */
#define MAP_FAILED ((void *) -1)
#define MS_ASYNC 1 /* Sync memory asynchronously. */
#define MS_SYNC 0 /* Synchronous memory sync. */
#define MS_INVALIDATE 2 /* Invalidate the caches. */
#endif//_SYS_MMAN_H

View File

@ -0,0 +1,13 @@
diff --git a/makefile b/makefile
--- a/makefile
+++ b/makefile
@@ -12,5 +12,9 @@ shared: murmur3.c murmur3.h
$(CC) -fPIC -O3 -c murmur3.c
$(CC) -shared -Wl,--export-dynamic murmur3.o -o libmurmur3.so
+static: murmur3.c murmur3.h
+ $(CC) -fPIC -O3 -c murmur3.c
+ $(AR) rcs libmurmur3.a murmur3.o
+
clean:
rm -rf example *.o *.so

View File

@ -0,0 +1,152 @@
/* compat/mingw/ptty.c
**
*/
#include "all.h"
#include "vere/vere.h"
#include <winternl.h>
/* _ptty_get_type(): detects tty type.
*/
static DWORD
_ptty_get_type(int fd)
{
HANDLE h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE)
return FILE_TYPE_UNKNOWN;
DWORD t = GetFileType(h);
if (t != FILE_TYPE_PIPE)
return t ;
// https://github.com/fusesource/jansi-native/commit/461068c67a38647d2890e96250636fc0117074f5
ULONG result;
BYTE buffer[1024];
POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer;
PWSTR name;
/* get pipe name */
if (!NT_SUCCESS(NtQueryObject(h, ObjectNameInformation, buffer, sizeof(buffer) - sizeof(WCHAR), &result)))
return FILE_TYPE_UNKNOWN;
name = nameinfo->Name.Buffer;
name[nameinfo->Name.Length] = 0;
// check for popular terminal emulators
// that use named pipes to communicate with subprocesses
if (wcsstr(name, L"\\ConEmu") ||
(wcsstr(name, L"msys-") || wcsstr(name, L"cygwin-")) && wcsstr(name, L"-pty"))
return FILE_TYPE_PIPE;
return FILE_TYPE_UNKNOWN;
}
/* _ttyf_nop(): stub function.
*/
static c3_o
_ttyf_nop(u3_utty* uty_u)
{
return c3y;
}
/* _ttyf_start_raw_input(): ends raw input on the tty.
*/
static c3_o
_ttyf_set_normal(u3_utty* uty_u)
{
c3_i e;
if ( 0 != (e = uv_tty_set_mode(&uty_u->pin_u.tty_u, UV_TTY_MODE_NORMAL)) ) {
fprintf(stderr, "uv_tty_set_mode(UV_TTY_MODE_NORMAL) -> %d\r\n", e);
return c3n;
}
return c3y;
}
/* _ttyf_start_raw_input(): sets the tty to raw input.
*/
static c3_o
_ttyf_set_raw(u3_utty* uty_u)
{
c3_i e;
if ( 0 != (e = uv_tty_set_mode(&uty_u->pin_u.tty_u, UV_TTY_MODE_RAW)) ) {
fprintf(stderr, "uv_tty_set_mode(UV_TTY_MODE_RAW) -> %d\r\n", e);
return c3n;
}
return c3y;
}
/* _ttyf_get_winsize(): gets the tty window size.
*/
static c3_o
_ttyf_get_winsize(u3_utty* uty_u, c3_l* col_l, c3_l* row_l)
{
c3_i col_i, row_i;
if ( 0 != uv_tty_get_winsize(&uty_u->pop_u.tty_u, &col_i, &row_i) ) {
return c3n;
}
*col_l = col_i;
*row_l = row_i;
return c3y;
}
/* _ttyf_get_winsize(): gets the tty window size.
*/
static c3_o
_ttyf_nop_winsize(u3_utty* uty_u, c3_l* col_l, c3_l* row_l)
{
return c3n;
}
/* u3_ptty_init(): initialize platform-specific tty.
*/
u3_utty*
u3_ptty_init(uv_loop_t* lup_u, const c3_c** err_c)
{
DWORD pip_l = _ptty_get_type(0);
DWORD pop_l = _ptty_get_type(1);
if ( pip_l == FILE_TYPE_UNKNOWN || pop_l == FILE_TYPE_UNKNOWN) {
*err_c = "not a tty";
return NULL;
}
if ( pip_l != pop_l ) {
*err_c = "partly redirected";
return NULL;
}
c3_i e;
u3_utty* uty_u = c3_calloc(sizeof(u3_utty));
if ( pip_l == FILE_TYPE_CHAR ) {
if ( 0 == (e = uv_tty_init(lup_u, &uty_u->pin_u.tty_u, 0, 0)) &&
0 == (e = uv_tty_init(lup_u, &uty_u->pop_u.tty_u, 1, 0)) )
{
SetConsoleOutputCP(CP_UTF8);
uty_u->sta_f = _ttyf_set_raw;
uty_u->sto_f = _ttyf_set_normal;
uty_u->wsz_f = _ttyf_get_winsize;
}
} else {
if ( 0 == (e = uv_pipe_init(lup_u, &uty_u->pin_u.pop_u, 0)) &&
0 == (e = uv_pipe_init(lup_u, &uty_u->pop_u.pop_u, 0)) &&
0 == (e = uv_pipe_open(&uty_u->pin_u.pop_u, 0)) &&
0 == (e = uv_pipe_open(&uty_u->pop_u.pop_u, 1)) )
{
fprintf(stderr, "vere: running interactive in a terminal emulator is experimental\r\n"
" use -t to disable interactivity or use native Windows console\r\n") ;
uty_u->sta_f = _ttyf_nop;
uty_u->sto_f = _ttyf_nop;
uty_u->wsz_f = _ttyf_nop_winsize;
}
}
if ( e ) {
*err_c = uv_strerror(e);
c3_free(uty_u);
return NULL;
}
uty_u->fid_i = 1;
uty_u->hij_f = _ttyf_nop;
uty_u->loj_f = _ttyf_nop;
return uty_u;
}

View File

@ -0,0 +1,167 @@
#include "all.h"
#include "rsignal.h"
#include <windows.h>
int err_win_to_posix(DWORD winerr);
// The current implementation of rsignal_ is single-threaded,
// but it can be extended to multi-threaded by replacing these
// static variables with a thread id-based hash map.
//
static __p_sig_fn_t _fns[SIG_COUNT];
static volatile DWORD _tid;
static HANDLE _hvt;
void rsignal_install_handler(int sig, __p_sig_fn_t fn)
{
if (sig < 0 || sig >= SIG_COUNT)
return;
DWORD newtid = GetCurrentThreadId();
DWORD oldtid = InterlockedExchange(&_tid, newtid);
if (oldtid != 0 && oldtid != newtid) {
fprintf(stderr, "\r\nrsignal_install_handler: %u -> %u\r\n", oldtid, newtid);
return;
}
__p_sig_fn_t oldfn = InterlockedExchangePointer((PVOID*)&_fns[sig], fn);
if (fn != 0 && oldfn != 0 && oldfn != fn) {
fprintf(stderr, "\r\nrsignal_install_handler: %p -> %p\r\n", oldfn, fn);
}
}
void rsignal_deinstall_handler(int sig)
{
rsignal_install_handler(sig, 0);
}
void rsignal_raise(int sig)
{
if (sig < 0 || sig >= SIG_COUNT)
return;
__p_sig_fn_t oldfn = InterlockedExchangePointer((PVOID*)&_fns[sig], 0);
if (oldfn == 0)
return;
if (_tid == GetCurrentThreadId()) {
oldfn(sig);
return;
}
HANDLE hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, _tid);
if (!hthread) {
fprintf(stderr, "\r\nrsignal_raise: OpenThread(%u): %d\r\n", _tid, GetLastError());
return;
}
if (SuspendThread(hthread) < 0) {
fprintf(stderr, "\r\nrsignal_raise: SuspendThread(%u): %d\r\n", _tid, GetLastError());
goto cleanup;
}
oldfn(sig);
if (!ResumeThread(hthread)) {
fprintf(stderr, "\r\nrsignal_raise: ResumeThread(%u): %d\r\n", _tid, GetLastError());
// abort because the main thread is stuck
abort();
}
cleanup:
CloseHandle(hthread);
}
static void _rsignal_vt_cb(PVOID param, BOOLEAN timedOut)
{
rsignal_raise(SIGVTALRM);
}
int rsignal_setitimer(int type, struct itimerval *in, struct itimerval *out)
{
if (in == 0) {
errno = EFAULT;
return -1;
}
if (type != ITIMER_VIRTUAL || out != 0) {
errno = ENOTSUP;
return -1;
}
if (_hvt != NULL) {
DeleteTimerQueueTimer(NULL, _hvt, NULL);
_hvt = NULL;
}
if (timerisset(&in->it_value) && !CreateTimerQueueTimer(&_hvt, NULL, _rsignal_vt_cb, NULL,
in->it_value.tv_sec * 1000 + in->it_value.tv_usec / 1000,
in->it_interval.tv_sec * 1000 + in->it_interval.tv_usec / 1000, 0))
{
errno = err_win_to_posix(GetLastError());
return -1;
} else {
return 0;
}
}
// direct import from ntdll.dll
extern DWORD64 __imp_KiUserExceptionDispatcher;
static void _rsignal_longjmp(intptr_t* builtin_jb)
{
__builtin_longjmp(builtin_jb, 1);
}
void rsignal_post_longjmp(DWORD tid, intptr_t* builtin_jb)
{
HANDLE hthread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid);
if (!hthread) {
fprintf(stderr, "\r\nrsignal: OpenThread(%u): %d\r\n", tid, GetLastError());
return;
}
CONTEXT context;
context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
if (!GetThreadContext(hthread, &context)) {
fprintf(stderr, "\r\nrsignal: GetThreadContext(%u): %d\r\n", tid, GetLastError());
goto cleanup;
}
// see if the thread is currently handling a structured exception
// if so, let the handler (usually the libsigsegv handler) finish
// and set up the the signal to run at the exception resume point
// otherwise, passing a parameter to fn is completely unreliable
//
DWORD64 kibase;
PRUNTIME_FUNCTION ki = RtlLookupFunctionEntry(__imp_KiUserExceptionDispatcher, &kibase, NULL);
CONTEXT c = context;
while (1)
{
DWORD64 base, frame;
PRUNTIME_FUNCTION f = RtlLookupFunctionEntry(c.Rip, &base, NULL);
if (!f) break;
if (f == ki)
{
// KiUserExceptionDispatcher has a "bare" frame
// with $rsp pointing to the CONTEXT structure
//
((PCONTEXT)c.Rsp)->Rip = (DWORD64)_rsignal_longjmp;
((PCONTEXT)c.Rsp)->Rcx = (DWORD64)builtin_jb;
goto cleanup;
}
PVOID handler_data;
RtlVirtualUnwind(0, base, c.Rip, f, &c, &handler_data, &frame, NULL);
}
context.Rip = (DWORD64)_rsignal_longjmp;
context.Rcx = (DWORD64)builtin_jb;
if (!SetThreadContext(hthread, &context)) {
fprintf(stderr, "\r\nrsignal: SetThreadContext(%u): %d\r\n", tid, GetLastError());
goto cleanup;
}
cleanup:
CloseHandle(hthread);
}

View File

@ -0,0 +1,24 @@
#ifndef _RSIGNAL_H
#define _RSIGNAL_H
typedef struct {
jmp_buf jb;
unsigned long tid;
} rsignal_jmpbuf;
#define rsignal_setjmp(buf) (buf.tid = GetCurrentThreadId(), setjmp(buf.jb))
#define rsignal_longjmp(buf, val) if (buf.tid != GetCurrentThreadId()) {buf.jb.retval = (val); rsignal_post_longjmp(buf.tid, buf.jb.buffer);} else longjmp(buf.jb, val)
void rsignal_raise(int sig);
void rsignal_install_handler(int sig, __p_sig_fn_t fn);
void rsignal_deinstall_handler(int sig);
void rsignal_post_longjmp(unsigned long tid, intptr_t* builtin_jb);
#define ITIMER_VIRTUAL 1
struct itimerval {
struct timeval it_value, it_interval;
};
int rsignal_setitimer(int type, struct itimerval *in, struct itimerval *out);
#endif//_RSIGNAL_H

View File

@ -0,0 +1,25 @@
#include "all.h"
#include "rsignal.h"
#include "vere/vere.h"
/* _mingw_exception_filter: replaces libsigsegv on MingW
*/
EXCEPTION_DISPOSITION _mingw_exception_filter(
IN PEXCEPTION_RECORD ExceptionRecord,
IN ULONG64 EstablisherFrame,
IN OUT PCONTEXT ContextRecord,
IN OUT PDISPATCHER_CONTEXT DispatcherContext)
{
if (ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
ExceptionRecord->ExceptionInformation[0] == 1 &&
u3e_fault((void*)ExceptionRecord->ExceptionInformation[1], 1))
{
return ExceptionContinueExecution;
}
if (ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
rsignal_raise(SIGSTK);
}
return ExceptionContinueSearch;
}

View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <string.h>
enum { INIT, CPAR, DQ, DQS, SQ, SQS };
char line[1 << 16];
/* seh_handler_decorator: registers u3_exception_handler for all functions in given source file
*/
int main(int argc, const char* argv[])
{
if (argc != 2)
return 1;
int c, state = INIT, curly = 0, emit = 0;
while (fgets(line, sizeof(line), stdin))
{
if (line[0] == '#')
{
emit = !!strstr(line, argv[1]);
fputs(line, stdout);
}
else
for (int i = 0; line[i]; i++)
{
switch (state) {
case INIT:
case CPAR:
switch (line[i]) {
case ' ':
case '\t':
case '\n':
case '\r':
case '\f': break;
case '{': curly++; if (emit && curly == 1 && state == CPAR) goto emit_handler; goto reset;
case '}': curly--; goto reset;
case '"': state = DQ; break;
case '\'': state = SQ; break;
case ')': state = CPAR; break;
reset:
default: state = INIT; break;
} break;
case DQ:
switch (line[i]) {
case '\\': state = DQS; break;
case '"': state = INIT; break;
} break;
case DQS: state = DQ; break;
case SQ:
switch (line[i]) {
case '\\': state = SQS; break;
case '\'': state = INIT; break;
} break;
case SQS: state = SQ; break;
}
fputc(line[i], stdout);
continue;
emit_handler:
fputs("{__asm__(\".seh_handler _mingw_exception_filter,@except\\n\");", stdout);
state = INIT;
}
}
return 0;
}

View File

@ -0,0 +1,24 @@
# This include file injects a step that transforms vere C source to register
# a SEH exception handler for each function that is declared in a .c file.
# It inserts a .seh_handler directive into each function body with __asm__.
# This directive affects the x64 unwind tables (.pdata and .xdata sections)
# emitted by the compiler.
#
# See gas/config/obj-coff-seh.h in binutils source for .seh_handler, and
# https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64
# for a description of how stack unwinding and SEH work in x64 Windows.
#
# When this file sets CCEXTRA, the first invocation of $(CC) in Makefile
# writes preprocessor output to stdout (-E -o -), which is piped to a simple
# parser that inserts __asm__ statements to each function in the .c file
# being compiled. The second invocation of $(CC) reads transformed source
# from stdin (-x cpp-output -). $< argument to $(sehdexe) tells the parser
# which .c file is being compiled.
sehdexe := build/seh_handler_decorator.exe
CCDEPS := $(CCDEPS) $(sehdexe)
CCEXTRA = -E -o -|$(sehdexe) $<|$(CC) $(CFLAGS) -x cpp-output -
$(sehdexe): compat/mingw/seh_handler_decorator.cc
@mkdir -p ./build
@$(CC) $< -o $@

View File

@ -0,0 +1,15 @@
#ifndef _MINGW_SETJMP_H
#define _MINGW_SETJMP_H
// msvcrt setjmp/longjmp are broken on 64-bit systems, use gcc builtins
typedef struct jmp_buf {
intptr_t buffer[5];
int retval;
} jmp_buf;
#define _setjmp setjmp
#define _longjmp longjmp
#define longjmp(buf, val) {buf.retval = (val); __builtin_longjmp(buf.buffer, 1);}
#define setjmp(buf) (__builtin_setjmp(buf.buffer) ? (buf.retval) : 0)
#endif//_MINGW_SETJMP_H

View File

@ -0,0 +1,36 @@
diff --git a/build/Win64-MinGW-w64/Makefile b/build/Win64-MinGW-w64/Makefile
--- a/build/Win64-MinGW-w64/Makefile
+++ b/build/Win64-MinGW-w64/Makefile
@@ -46,7 +46,8 @@ C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
COMPILE_C = \
x86_64-w64-mingw32-gcc -c -Werror-implicit-function-declaration \
-DSOFTFLOAT_FAST_INT64 $(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
-MAKELIB = x86_64-w64-mingw32-ar crs $@
+MAKELIB = x86_64-w64-mingw32-gcc-ar crs $@
+LIBNAME = libsoftfloat3
OBJ = .o
LIB = .a
@@ -54,7 +55,7 @@ LIB = .a
OTHER_HEADERS = $(SOURCE_DIR)/include/opts-GCC.h
.PHONY: all
-all: softfloat$(LIB)
+all: $(LIBNAME)$(LIB)
OBJS_PRIMITIVES = \
s_eq128$(OBJ) \
@@ -380,11 +381,11 @@ $(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c
$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c
$(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c
-softfloat$(LIB): $(OBJS_ALL)
+$(LIBNAME)$(LIB): $(OBJS_ALL)
$(DELETE) $@
$(MAKELIB) $^
.PHONY: clean
clean:
- $(DELETE) $(OBJS_ALL) softfloat$(LIB)
+ $(DELETE) $(OBJS_ALL) $(LIBNAME)$(LIB)

View File

@ -0,0 +1,30 @@
diff --git a/src/win/pipe.c b/src/win/pipe.c
index 0f2bb869b..f81245ec6 100644
--- a/src/win/pipe.c
+++ b/src/win/pipe.c
@@ -270,6 +270,12 @@ static int uv_set_pipe_handle(uv_loop_t* loop,
if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
err = GetLastError();
+ if ((err == ERROR_INVALID_FUNCTION || err == ERROR_INVALID_PARAMETER) && (duplex_flags & UV_HANDLE_WRITABLE)) {
+ /*
+ * it's not a pipe, but simple writes should be fine
+ * let's trust callers to know what they're doing
+ */
+ } else
if (err == ERROR_ACCESS_DENIED) {
/*
* SetNamedPipeHandleState can fail if the handle doesn't have either
diff --git a/src/win/tty.c b/src/win/tty.c
index c359d5601..1b9d4f853 100644
--- a/src/win/tty.c
+++ b/src/win/tty.c
@@ -367,7 +367,7 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) {
flags = ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
break;
case UV_TTY_MODE_RAW:
- flags = ENABLE_WINDOW_INPUT;
+ flags = ENABLE_WINDOW_INPUT | ENABLE_PROCESSED_INPUT;
break;
case UV_TTY_MODE_IO:
return UV_ENOTSUP;

View File

@ -0,0 +1,152 @@
declare -a cdirs
declare -a ldirs
declare -a pdirs
declare -A hdeps
sources=(../../nix/sources.json ../../nix/sources-pmnsh.json)
patches=compat/$1
deriver=urbit-$1-build
markfil=.$1~
depdirs=
nixpath=${NIX_STORE-../build}
# LDFLAGS doesn't like absolute paths
if [ "${nixpath:0:1}" == "/" ]
then
mkdir -p $nixpath
nixpath=$(realpath --relative-to=. $nixpath)
fi
hex2nixbase32 () {
local digits='0123456789abcdfghijklmnpqrsvwxyz'
local bits=0
local left=0 # number of bits left in $bits
local i=0
while ((1))
do
while ((left>=5))
do
echo -n ${digits:$((bits&31)):1}
bits=$((bits>>5))
left=$((left-5))
done
if ((i == ${#1}))
then
break
fi
char=0x${1:i:2}
i=$((i+2))
bits=$((bits|(char<<(left))))
left=$((left+8))
done
echo -n ${digits:$bits:1}
}
buildnixdep () {
echo Building dependency $key...
local cache=https://app.cachix.org/api/v1/cache/${CACHIX_CACHE-}
local hash=
if [ -n "$url" ]
then
hash=${hdeps[$key]}
dir=$nixpath/$hash-$key
if [ -e $dir/$markfil ]
then
# dependency present, don't reupload
hash=
else
# dependency absent, check the binary cache if configured
if [ -n "${CACHIX_CACHE-}" ]
then
echo Checking binary cache for $hash-$key...
narinfo="$cache/${hash}.narinfo"
if curl -fLI "$narinfo"
then
url="$cache/$(curl -fL -H "Accept: application/json" "$narinfo"|jq -r '.url')"
echo Found $url
strip=0
hash=
fi
fi
mkdir -p $dir
pushd $dir
curl -fL "$url"|(tar --strip $strip -xzf - || true)
popd
fi
else
# local dependency
dir=../$key
fi
# patch and build the dependency if necessary
if [ ! -e $dir/$markfil ]
then
local patch=$patches/$key.patch
[ -e $patch ] && patch -d $dir -p 1 <$patch
pushd $dir
eval "$cmdprep"
eval make "$cmdmake"
touch $markfil
popd
fi
# if configured, upload freshly built dependency to binary cache
if [ -n "$hash" -a -n "${CACHIX_AUTH_TOKEN-}" ]
then
(
echo Uploading freshly built $hash-$key to binary cache...
tar -C $dir -czf $hash.tar .
local size=$(stat -c '%s' $hash.tar)
read filehash _ < <(sha256sum $hash.tar)
curl -fL -H "Content-Type: application/gzip" -H "Authorization: Bearer $CACHIX_AUTH_TOKEN" --data-binary @"$hash.tar" "$cache/nar"
curl -fL -H "Content-Type: application/json" -H "Authorization: Bearer $CACHIX_AUTH_TOKEN" --data-binary @- "$cache/${hash}.narinfo" <<EOF
{
"cStoreHash": "$hash",
"cStoreSuffix": "$key",
"cNarHash": "sha256:$(hex2nixbase32 $filehash)",
"cNarSize": $size,
"cFileHash": "$filehash",
"cFileSize": $size,
"cReferences": [],
"cDeriver": "$deriver"
}
EOF
echo Done. ) || true
rm $hash.tar || true
fi
}
# I have to go over the sources files several times
# because jq does not have a way to invoke external programs
jqprep='add|to_entries|.[]|.value.pmnsh as $p|select($p and $p.compat.'$1' != false)|(($p + $p.compat.'$1')|del(.compat)) as $o|'
# list external dependencies, create hash map and directory replacement regex
# use -j and \u0000 to work around https://github.com/stedolan/jq/issues/1870
while read -rd "" key json
do
# create 'store hash' from sources.json data and patch
patch=$patches/$key.patch
read hash _ < <((
echo -n $json
[ -e $patch ] && cat $patch)|sha256sum)
hash=$(hex2nixbase32 $hash)
hdeps[$key]=$hash
depdirs="$depdirs|gsub(\"\\\\.\\\\./$key\";\"\\(\$d)/$hash-$key\")"
done < <(jq --arg deriver "$deriver" -Sscrj "$jqprep"'select(.value.url)|.key," ",{($deriver):(.value|del(.pmnsh) + ({'$1':$o}))},"\u0000"' ${sources[@]})
# build dependencies, create include and library directory arrays
. <(jq --arg nixpath "$nixpath" -sr "$jqprep"'(if .value.url then ".." else $nixpath end) as $d|"
unset dir
key=\(.key|@sh) \\
url=\(.value.url//""|@sh) \\
strip=\($o.strip+1) \\
cmdprep=\($o.prepare//""'"$depdirs"'|@sh) \\
cmdmake=\($o.make//""'"$depdirs"'|@sh) \\
buildnixdep # sets dir
pdirs+=($dir) # XX support json override a la cdirs/pdirs
\($o.include//"."|if type == "array" then . else [.] end|map("cdirs+=(-I$dir/\(.))")|join("\n"))
\($o.lib//"."|if type == "array" then . else [.] end|map("ldirs+=(-L$dir/\(.))")|join("\n"))"' ${sources[@]})
CFLAGS="${CFLAGS-} ${cdirs[@]}"
LDFLAGS="${LDFLAGS-} ${ldirs[@]}"
PKG_CONFIG_PATH="${PKG_CONFIG_PATH-}:$(IFS=:;echo "${pdirs[*]}")"

View File

@ -0,0 +1,91 @@
#include "all.h"
#include "vere/vere.h"
#include <sys/wait.h>
/*
This is set to the the write-end of a pipe when Urbit is started in
daemon mode. It's meant to be used as a signal to the parent process
that the child process has finished booting.
*/
static c3_i _child_process_booted_signal_fd = -1;
/*
This should be called whenever the ship has been booted enough to
handle commands from automation code. Specifically, once the Eyre's
`chis` interface is up and running.
In daemon mode, this signals to the parent process that it can
exit. Otherwise, it does nothing.
Once we've sent a signal with `write`, we close the file descriptor
and overwrite the global to make it impossible to accidentally do
this twice.
*/
static void _on_boot_completed_cb() {
c3_c buf[2] = {0,0};
if ( -1 == _child_process_booted_signal_fd ) {
return;
}
if ( 0 == write(_child_process_booted_signal_fd, buf, 1) ) {
c3_assert(!"_on_boot_completed_cb: Can't write to parent FD");
}
close(_child_process_booted_signal_fd);
_child_process_booted_signal_fd = -1;
}
/* u3_daemon_init(): platform-specific daemon mode initialization.
We use a pipe to communicate between the child and the parent. The
parent waits for the child to write something to the pipe and
then exits. If the pipe is closed with nothing written to it, get
the exit status from the child process and also exit with that status.
We want the child to write to the pipe once it's booted, so we put
`_on_boot_completed_cb` into `u3_Host.bot_f`, which is NULL in
non-daemon mode. That gets called once the `chis` service is
available.
In both processes, we are good fork() citizens, and close all unused
file descriptors. Closing `pipefd[1]` in the parent process is
especially important, since the pipe needs to be closed if the child
process dies. When the pipe is closed, the read fails, and that's
how we know that something went wrong.
There are some edge cases around `WEXITSTATUS` that are not handled
here, but I don't think it matters.
*/
void
u3_daemon_init()
{
c3_i pipefd[2];
if ( 0 != pipe(pipefd) ) {
c3_assert(!"Failed to create pipe");
}
pid_t childpid = fork();
if ( 0 == childpid ) {
close(pipefd[0]);
_child_process_booted_signal_fd = pipefd[1];
u3_Host.bot_f = _on_boot_completed_cb;
return;
}
close(pipefd[1]);
close(0);
close(1);
close(2);
c3_c buf[2] = {0,0};
if ( 1 == read(pipefd[0], buf, 1) ) {
exit(0);
}
c3_i status;
wait(&status);
exit(WEXITSTATUS(status));
}

View File

@ -0,0 +1,192 @@
/* compat/posix/ptty.c
**
*/
#include "all.h"
#include "vere/vere.h"
#include <sys/ioctl.h>
#include <termios.h>
/* u3_ptty: POSIX terminal extension to u3_utty.
*/
typedef struct {
u3_utty tty_u; // common tty structure
c3_i cug_i; // blocking fcntl flags
c3_i nob_i; // nonblocking fcntl flags
struct termios bak_u; // cooked terminal state
struct termios raw_u; // raw terminal state
} u3_ptty;
/* _term_tcsetattr(): tcsetattr w/retry on EINTR.
*/
static c3_i
_term_tcsetattr(c3_i fil_i, c3_i act_i, const struct termios* tms_u)
{
c3_i ret_i = 0;
c3_w len_w = 0;
do {
// abort pathological retry loop
//
if ( 100 == ++len_w ) {
fprintf(stderr, "term: tcsetattr loop: %s\r\n", strerror(errno));
return -1;
}
ret_i = tcsetattr(fil_i, act_i, tms_u);
} while ( (-1 == ret_i) && (EINTR == errno) );
return ret_i;
}
/* _ttyf_start_raw_input(): sets the tty to raw input.
*/
static c3_o
_ttyf_start_raw_input(u3_utty* uty_u)
{
u3_ptty* pty_u = (u3_ptty*)uty_u;
if ( 0 != _term_tcsetattr(uty_u->fid_i, TCSADRAIN, &pty_u->raw_u) ) {
return c3n;
}
if ( -1 == fcntl(uty_u->fid_i, F_SETFL, pty_u->nob_i) ) {
c3_assert(!"init-fcntl");
}
return c3y;
}
/* _ttyf_start_raw_input(): ends raw input on the tty.
*/
static c3_o
_ttyf_end_raw_input(u3_utty* uty_u)
{
u3_ptty* pty_u = (u3_ptty*)uty_u;
if ( 0 != _term_tcsetattr(uty_u->fid_i, TCSADRAIN, &pty_u->bak_u) ) {
return c3n;
}
if ( -1 == fcntl(uty_u->fid_i, F_SETFL, pty_u->cug_i) ) {
c3_assert(!"exit-fcntl");
}
return c3y;
}
/* _ttyf_hija(): hijacks the tty for cooked output.
*/
static c3_o
_ttyf_hija(u3_utty* uty_u)
{
u3_ptty* pty_u = (u3_ptty*)uty_u;
if ( 0 != _term_tcsetattr(1, TCSADRAIN, &pty_u->bak_u) ) {
perror("hija-tcsetattr-1");
c3_assert(!"hija-tcsetattr");
}
if ( -1 == fcntl(1, F_SETFL, pty_u->cug_i) ) {
perror("hija-fcntl-1");
c3_assert(!"hija-fcntl");
}
if ( 0 != _term_tcsetattr(0, TCSADRAIN, &pty_u->bak_u) ) {
perror("hija-tcsetattr-0");
c3_assert(!"hija-tcsetattr");
}
if ( -1 == fcntl(0, F_SETFL, pty_u->cug_i) ) {
perror("hija-fcntl-0");
c3_assert(!"hija-fcntl");
}
return c3y;
}
/* _ttyf_loja(): releases the tty from cooked output.
*/
static c3_o
_ttyf_loja(u3_utty* uty_u)
{
u3_ptty* pty_u = (u3_ptty*)uty_u;
if ( 0 != _term_tcsetattr(1, TCSADRAIN, &pty_u->raw_u) ) {
perror("loja-tcsetattr-1");
c3_assert(!"loja-tcsetattr");
}
if ( -1 == fcntl(1, F_SETFL, pty_u->nob_i) ) {
perror("hija-fcntl-1");
c3_assert(!"loja-fcntl");
}
if ( 0 != _term_tcsetattr(0, TCSADRAIN, &pty_u->raw_u) ) {
perror("loja-tcsetattr-0");
c3_assert(!"loja-tcsetattr");
}
if ( -1 == fcntl(0, F_SETFL, pty_u->nob_i) ) {
perror("hija-fcntl-0");
c3_assert(!"loja-fcntl");
}
return c3y;
}
/* _ttyf_get_winsize(): gets the tty window size.
*/
static c3_o
_ttyf_get_winsize(u3_utty* uty_u, c3_l* col_l, c3_l* row_l)
{
struct winsize siz_u;
if ( 0 == ioctl(uty_u->fid_i, TIOCGWINSZ, &siz_u) )
{
*col_l = siz_u.ws_col;
*row_l = siz_u.ws_row;
return c3y;
} else {
return c3n;
}
}
/* u3_ptty_init(): initialize platform-specific tty.
*/
u3_utty*
u3_ptty_init(uv_loop_t* lup_u, const c3_c** err_c)
{
u3_ptty* pty_u = c3_calloc(sizeof(u3_ptty));
u3_utty* uty_u = &pty_u->tty_u;
if ( !isatty(0) || !isatty(1) ) {
*err_c = "not a tty";
c3_free(pty_u);
return NULL;
}
uv_pipe_init(lup_u, &uty_u->pin_u.pop_u, 0);
uv_pipe_init(lup_u, &uty_u->pop_u.pop_u, 0);
uv_pipe_open(&uty_u->pin_u.pop_u, 0);
uv_pipe_open(&uty_u->pop_u.pop_u, 1);
// Load old terminal state to restore.
//
{
if ( 0 != tcgetattr(uty_u->fid_i, &pty_u->bak_u) ) {
c3_assert(!"init-tcgetattr");
}
if ( -1 == fcntl(uty_u->fid_i, F_GETFL, &pty_u->cug_i) ) {
c3_assert(!"init-fcntl");
}
pty_u->cug_i &= ~O_NONBLOCK; // could fix?
pty_u->nob_i = pty_u->cug_i | O_NONBLOCK; // O_NDELAY on older unix
}
// Construct raw termios configuration.
//
// makes input available per-character, does not echo input,
// disables special input pre-processing, output post-processing.
//
{
pty_u->raw_u = pty_u->bak_u;
pty_u->raw_u.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
pty_u->raw_u.c_iflag &= ~(ICRNL | INPCK | ISTRIP);
pty_u->raw_u.c_cflag &= ~(CSIZE | PARENB);
pty_u->raw_u.c_cflag |= CS8;
pty_u->raw_u.c_oflag &= ~(OPOST);
pty_u->raw_u.c_cc[VMIN] = 0;
pty_u->raw_u.c_cc[VTIME] = 0;
}
uty_u->fid_i = 1;
uty_u->sta_f = _ttyf_start_raw_input;
uty_u->sto_f = _ttyf_end_raw_input;
uty_u->hij_f = _ttyf_hija;
uty_u->loj_f = _ttyf_loja;
uty_u->wsz_f = _ttyf_get_winsize;
return uty_u;
}

View File

@ -0,0 +1,11 @@
#ifndef _RSIGNAL_H
#define _RSIGNAL_H
#define rsignal_jmpbuf sigjmp_buf
#define rsignal_setjmp(buf) sigsetjmp((buf), 1)
#define rsignal_longjmp siglongjmp
#define rsignal_install_handler signal
#define rsignal_deinstall_handler(sig) signal((sig), SIG_IGN)
#define rsignal_setitimer setitimer
#endif//_RSIGNAL_H

145
pkg/urbit/configure vendored
View File

@ -1,16 +1,32 @@
#!/usr/bin/env bash
set -e
set -euo pipefail
URBIT_VERSION="$(cat ./version)"
deps=" \
curl gmp sigsegv argon2 ed25519 ent h2o scrypt uv murmur3 secp256k1 \
softfloat3 ssl crypto z lmdb ge-additions aes_siv pthread \
# we require pkg-config metadata to statically link these
#
pkgc_deps=" \
libcurl \
libh2o \
liburcrypt-0 \
libuv \
openssl \
"
headers=" \
ivory.h ca-bundle.h \
deps=" \
ent \
gmp \
lmdb \
murmur3 \
pthread \
sigsegv \
softfloat3 \
"
headers=" \
ca-bundle.h \
ivory.h \
"
echo '#pragma once' >include/config.h
@ -21,10 +37,47 @@ defmacro () {
defmacro URBIT_VERSION "\"$URBIT_VERSION\""
[ -n "$MEMORY_DEBUG" ] && defmacro U3_MEMORY_DEBUG 1
[ -n "$MEMORY_LOG" ] && defmacro U3_MEMORY_LOG 1
[ -n "$CPU_DEBUG" ] && defmacro U3_CPU_DEBUG 1
[ -n "$EVENT_TIME_DEBUG" ] && defmacro U3_EVENT_TIME_DEBUG 1
opt_debug=
opt_static=
while test $# != 0
do
case $1 in
--enable-debug)
opt_debug=1
;;
--disable-debug)
opt_debug=
;;
--enable-static)
opt_static=1
;;
--enable-shared)
opt_static=
;;
--disable-static)
opt_static=
;;
--disable-shared)
opt_static=1
;;
*)
echo "unrecognized option: $1"
;;
esac
shift
done
if [ -n "${opt_static-}" ]
then
CFLAGS="${CFLAGS-} -static"
fi
[ -n "${MEMORY_DEBUG-}" ] && defmacro U3_MEMORY_DEBUG 1
[ -n "${MEMORY_LOG-}" ] && defmacro U3_MEMORY_LOG 1
[ -n "${CPU_DEBUG-}" ] && defmacro U3_CPU_DEBUG 1
[ -n "${EVENT_TIME_DEBUG-}" ] && defmacro U3_EVENT_TIME_DEBUG 1
if [ -n "${HOST-}" ]
then os=$(sed 's$^[^-]*-\([^-]*\)-.*$\1$' <<< "$HOST")
@ -58,18 +111,60 @@ esac
# TODO Determine if the target cpu is little or big endian.
case $(tr A-Z a-z <<< $os) in
*mingw*)
if [ -z "${opt_static-}" ]
then
echo mingw builds are static-only
exit 1
fi
# ensure required mingw packages are installed
mpkgs=(cmake curl gcc jq make)
pacman -S --needed autoconf automake-wrapper libtool patch ${mpkgs[@]/#/mingw-w64-x86_64-}
. compat/poor-mans-nix-shell.sh mingw
compat/create-include-files.sh 'stat -c %s' /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt
defmacro U3_OS_mingw 1
deps="${deps/sigsegv}"
compat="${compat-} mingw"
;;
m1brew)
# ensure required packages are installed
brew install -q autoconf automake bash cmake coreutils gmp jq libsigsegv libtool libuv openssl pkgconfig
if (( ${BASH_VERSION%%.*} < 5 ))
then
echo Running bash version $BASH_VERSION is too low, please restart bash to use freshly installed one
exit 1
fi
# for some reason pkg-config does not pick up openssl
export PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig:${PKG_CONFIG_PATH-}"
. compat/poor-mans-nix-shell.sh m1brew
compat/create-include-files.sh 'stat -f %z' /etc/ssl/cert.pem
defmacro U3_OS_osx 1
compat="${compat-} posix m1brew"
;;
*linux*)
defmacro U3_OS_linux 1
defmacro U3_OS_PROF 1
;;
*darwin*)
defmacro U3_OS_osx 1
defmacro U3_OS_PROF 1
;;
*apple*)
defmacro U3_OS_osx 1
defmacro U3_OS_PROF 1
;;
*freebsd*)
defmacro U3_OS_bsd 1
osdeps="kvm"
deps="$deps kvm" # XX use new compat.mk pattern
;;
*openbsd*)
defmacro U3_OS_bsd 1
@ -80,19 +175,35 @@ case $(tr A-Z a-z <<< $os) in
;;
esac
for dep in ${osdeps-} $deps
do LDFLAGS="${LDFLAGS-} -l$dep"
${PKG_CONFIG-pkg-config} --cflags --libs $dep 2>/dev/null || true
PKG_CONFIG="${PKG_CONFIG-pkg-config}"
if [ -n "${opt_static-}" ]
then
PKG_CONFIG="$PKG_CONFIG --static"
fi
CFLAGS="${CFLAGS-} $($PKG_CONFIG --cflags $pkgc_deps)"
LDFLAGS="${LDFLAGS-} $($PKG_CONFIG --libs $pkgc_deps)"
for dep in $deps; do
LDFLAGS="${LDFLAGS-} -l$dep"
done
for header in $headers
do LDFLAGS="${LDFLAGS-} -I$header"
for header in $headers; do
CFLAGS="${CFLAGS-} -I$header"
done
compat="${compat-posix}"
for citem in $compat; do
CFLAGS="${CFLAGS-} -Icompat/$citem"
done
cat >config.mk <<EOF
CFLAGS := ${CFLAGS-} -funsigned-char -ffast-math -std=gnu99 -Wno-format-zero-length
CFLAGS := $CFLAGS -funsigned-char -ffast-math -fcommon -std=gnu99 -Wno-format-zero-length
LDFLAGS := $LDFLAGS
CC := ${CC-cc}
compat := $compat
debug := $opt_debug
EOF
echo == config.mk == >&2

View File

@ -1,30 +1,19 @@
/* vere/main.c
**
*/
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <limits.h>
#include <uv.h>
#define U3_GLOBAL
#define C3_GLOBAL
#include "all.h"
#include "vere/vere.h"
#if !defined(U3_OS_mingw)
#include <sigsegv.h>
#include <stdlib.h>
#include <termios.h>
#include <dirent.h>
#endif
#include <openssl/conf.h>
#include <openssl/engine.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <h2o.h>
#include <curl/curl.h>
#include <argon2.h>
#include <lmdb.h>
#define U3_GLOBAL
#define C3_GLOBAL
#include "all.h"
#include "vere/vere.h"
#include <vere/db/lmdb.h>
#include "ca-bundle.h"
@ -222,9 +211,9 @@ _main_getopt(c3_i argc, c3_c** argv)
}
}
#if defined(U3_OS_bsd)
#if !defined(U3_OS_PROF)
if (u3_Host.ops_u.pro == c3y) {
fprintf(stderr, "profiling isn't yet supported on BSD\r\n");
fprintf(stderr, "profiling isn't yet supported on your OS\r\n");
return c3n;
}
#endif
@ -307,7 +296,7 @@ _main_getopt(c3_i argc, c3_c** argv)
}
struct sockaddr_in t;
if ( u3_Host.ops_u.bin_c != 0 && inet_aton(u3_Host.ops_u.bin_c, &t.sin_addr) == 0 ) {
if ( u3_Host.ops_u.bin_c != 0 && inet_pton(AF_INET, u3_Host.ops_u.bin_c, &t.sin_addr) == 0 ) {
fprintf(stderr, "-b invalid IP address\n");
return c3n;
}
@ -373,26 +362,64 @@ _main_getopt(c3_i argc, c3_c** argv)
return c3y;
}
/* _setup_cert_store: writes our embedded certificate database to a temp file
/* _cert_store: decoded CA certificates
*/
static STACK_OF(X509_INFO)* _cert_store;
/* _setup_cert_store(): decodes embedded CA certificates
*/
static void
_setup_cert_store(char* tmp_cert_file_name)
_setup_cert_store()
{
errno = 0;
int fd = mkstemp(tmp_cert_file_name);
if (fd < 1) {
printf("boot: failed to write local ssl temporary certificate store: %s\n",
strerror(errno));
BIO* cbio = BIO_new_mem_buf(include_ca_bundle_crt, include_ca_bundle_crt_len);
if ( !cbio || !(_cert_store = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL)) ) {
u3l_log("boot: failed to decode embedded CA certificates\r\n");
exit(1);
}
if (-1 == write(fd, include_ca_bundle_crt, include_ca_bundle_crt_len)) {
printf("boot: failed to write local ssl temporary certificate store: %s\n",
strerror(errno));
exit(1);
}
BIO_free(cbio);
}
setenv("SSL_CERT_FILE", tmp_cert_file_name, 1);
/* _setup_ssl_x509(): adds embedded CA certificates to a X509_STORE
*/
static void
_setup_ssl_x509(void* arg)
{
X509_STORE* cts = arg;
int i;
for ( i = 0; i < sk_X509_INFO_num(_cert_store); i++ ) {
X509_INFO *itmp = sk_X509_INFO_value(_cert_store, i);
if(itmp->x509) {
X509_STORE_add_cert(cts, itmp->x509);
}
if(itmp->crl) {
X509_STORE_add_crl(cts, itmp->crl);
}
}
}
/* _curl_ssl_ctx_cb(): curl SSL context callback
*/
static CURLcode
_curl_ssl_ctx_cb(CURL* curl, SSL_CTX* sslctx, void* param)
{
X509_STORE* cts = SSL_CTX_get_cert_store(sslctx);
if (!cts || !_cert_store)
return CURLE_ABORTED_BY_CALLBACK;
_setup_ssl_x509(cts);
return CURLE_OK;
}
/* _setup_ssl_curl(): adds embedded CA certificates to a curl context
*/
static void
_setup_ssl_curl(void* arg)
{
CURL* curl = arg;
curl_easy_setopt(curl, CURLOPT_CAINFO, NULL);
curl_easy_setopt(curl, CURLOPT_CAPATH, NULL);
curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, _curl_ssl_ctx_cb);
}
@ -486,9 +513,11 @@ report(void)
{
printf("urbit %s\n", URBIT_VERSION);
printf("gmp: %s\n", gmp_version);
#if !defined(U3_OS_mingw)
printf("sigsegv: %d.%d\n",
(libsigsegv_version >> 8) & 0xff,
libsigsegv_version & 0xff);
#endif
printf("openssl: %s\n", SSLeay_version(SSLEAY_VERSION));
printf("libuv: %s\n", uv_version_string());
printf("libh2o: %d.%d.%d\n",
@ -503,7 +532,6 @@ report(void)
LIBCURL_VERSION_MAJOR,
LIBCURL_VERSION_MINOR,
LIBCURL_VERSION_PATCH);
printf("argon2: 0x%x\n", ARGON2_VERSION_NUMBER);
}
/* _stop_exit(): exit immediately.
@ -517,96 +545,6 @@ _stop_exit(c3_i int_i)
u3_king_bail();
}
/*
This is set to the the write-end of a pipe when Urbit is started in
daemon mode. It's meant to be used as a signal to the parent process
that the child process has finished booting.
*/
static c3_i _child_process_booted_signal_fd = -1;
/*
This should be called whenever the ship has been booted enough to
handle commands from automation code. Specifically, once the Eyre's
`chis` interface is up and running.
In daemon mode, this signals to the parent process that it can
exit. Otherwise, it does nothing.
Once we've sent a signal with `write`, we close the file descriptor
and overwrite the global to make it impossible to accidentally do
this twice.
*/
static void _on_boot_completed_cb() {
c3_c buf[2] = {0,0};
if ( -1 == _child_process_booted_signal_fd ) {
return;
}
if ( 0 == write(_child_process_booted_signal_fd, buf, 1) ) {
c3_assert(!"_on_boot_completed_cb: Can't write to parent FD");
}
close(_child_process_booted_signal_fd);
_child_process_booted_signal_fd = -1;
}
/*
In daemon mode, run the urbit as a background process, but don't
exit from the parent process until the ship is finished booting.
We use a pipe to communicate between the child and the parent. The
parent waits for the child to write something to the pipe and
then exits. If the pipe is closed with nothing written to it, get
the exit status from the child process and also exit with that status.
We want the child to write to the pipe once it's booted, so we put
`_on_boot_completed_cb` into `u3_Host.bot_f`, which is NULL in
non-daemon mode. That gets called once the `chis` service is
available.
In both processes, we are good fork() citizens, and close all unused
file descriptors. Closing `pipefd[1]` in the parent process is
especially important, since the pipe needs to be closed if the child
process dies. When the pipe is closed, the read fails, and that's
how we know that something went wrong.
There are some edge cases around `WEXITSTATUS` that are not handled
here, but I don't think it matters.
*/
static void
_fork_into_background_process()
{
c3_i pipefd[2];
if ( 0 != pipe(pipefd) ) {
c3_assert(!"Failed to create pipe");
}
pid_t childpid = fork();
if ( 0 == childpid ) {
close(pipefd[0]);
_child_process_booted_signal_fd = pipefd[1];
u3_Host.bot_f = _on_boot_completed_cb;
return;
}
close(pipefd[1]);
close(0);
close(1);
close(2);
c3_c buf[2] = {0,0};
if ( 1 == read(pipefd[0], buf, 1) ) {
exit(0);
}
c3_i status;
wait(&status);
exit(WEXITSTATUS(status));
}
/* _stop_on_boot_completed_cb(): exit gracefully after boot is complete
*/
static void
@ -659,12 +597,24 @@ main(c3_i argc,
}
// Set `u3_Host.wrk_c` to the worker executable path.
c3_i worker_exe_len = 1 + strlen(argv[0]) + strlen("-worker");
c3_i urbit_exe_len = strlen(argv[0]);
c3_i worker_exe_len = 1 + urbit_exe_len + strlen("-worker");
u3_Host.wrk_c = c3_malloc(worker_exe_len);
#if defined(U3_OS_mingw)
if ( urbit_exe_len >= 4 && !strcmp(argv[0] + urbit_exe_len - 4, ".exe")) {
snprintf(u3_Host.wrk_c, worker_exe_len, "%.*s-worker.exe", urbit_exe_len - 4, argv[0]);
} else {
snprintf(u3_Host.wrk_c, worker_exe_len, "%s-worker", argv[0]);
}
#else
snprintf(u3_Host.wrk_c, worker_exe_len, "%s-worker", argv[0]);
#endif
if ( c3y == u3_Host.ops_u.dem ) {
_fork_into_background_process();
// In daemon mode, run the urbit as a background process, but don't
// exit from the parent process until the ship is finished booting.
//
u3_daemon_init();
}
if ( c3y == u3_Host.ops_u.rep ) {
@ -688,6 +638,7 @@ main(c3_i argc,
//
// XX review, may be unnecessary due to similar in u3m_init()
//
#if defined(U3_OS_PROF)
if ( _(u3_Host.ops_u.pro) ) {
sigset_t set;
@ -698,12 +649,15 @@ main(c3_i argc,
exit(1);
}
}
#endif
#if !defined(U3_OS_mingw)
// Handle SIGTSTP as if it was SIGTERM.
//
// Configured here using signal() so as to be immediately available.
//
signal(SIGTSTP, _stop_exit);
#endif
printf("~\n");
// printf("welcome.\n");
@ -735,9 +689,6 @@ main(c3_i argc,
}
// printf("vere: hostname is %s\n", u3_Host.ops_u.nam_c);
u3K.certs_c = strdup("/tmp/urbit-ca-cert-XXXXXX");
_setup_cert_store(u3K.certs_c);
if ( c3y == u3_Host.ops_u.dem ) {
printf("boot: running as daemon\n");
}
@ -804,6 +755,23 @@ main(c3_i argc,
}
}
#if defined(U3_OS_mingw)
// Initialize event used to transmit Ctrl-C to worker process
//
{
SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
if ( NULL == (u3_Host.cev_u = CreateEvent(&sa, FALSE, FALSE, NULL)) ) {
u3l_log("boot: failed to create Ctrl-C event: %d\r\n", GetLastError());
exit(1);
}
}
#endif
// starting u3m configures OpenSSL memory functions, so we must do it
// before any OpenSSL allocations
//
u3m_boot_lite();
// Initialize OpenSSL for client and server
//
{
@ -818,6 +786,10 @@ main(c3_i argc,
exit(1);
}
_setup_cert_store();
u3K.ssl_curl_f = _setup_ssl_curl;
u3K.ssl_x509_f = _setup_ssl_x509;
u3_king_commence();
// uninitialize curl

View File

@ -72,6 +72,25 @@
# include <sys/resource.h>
# include <sys/mman.h>
# elif defined(U3_OS_mingw)
# define signal mingw_has_no_usable_signal
# define raise mingw_has_no_usable_raise
# define _POSIX
# include <inttypes.h>
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
# include <unistd.h>
# include <stdint.h>
# include <assert.h>
# include <setjmp.h>
# include <stdio.h>
# include <dirent.h>
# include <signal.h>
# include <sys/time.h>
# include "mman.h"
# include "compat.h"
# else
#error "port: headers"
# endif
@ -97,14 +116,10 @@
# define U3_OS_LoomBase 0x36000000
# endif
# define U3_OS_LoomBits 29 // ie, 2^29 words == 2GB
# elif defined(U3_OS_osx)
# ifdef __LP64__
# define U3_OS_LoomBase 0x200000000
# else
# define U3_OS_LoomBase 0x4000000
# endif
# elif defined(U3_OS_osx) && defined(U3_CPU_aarch64) || defined(U3_OS_mingw)
# define U3_OS_LoomBase 0x28000000000
# define U3_OS_LoomBits 29 // ie, 2^29 words == 2GB
# elif defined(U3_OS_bsd)
# elif defined(U3_OS_osx) || defined(U3_OS_bsd)
# ifdef __LP64__
# define U3_OS_LoomBase 0x200000000
# else
@ -153,7 +168,7 @@
/* Byte swapping.
*/
# if defined(U3_OS_linux) || defined(U3_OS_bsd)
# if defined(U3_OS_linux) || defined(U3_OS_bsd) || defined(U3_OS_mingw)
# define c3_bswap_16(x) bswap_16(x)
# define c3_bswap_32(x) bswap_32(x)
# define c3_bswap_64(x) bswap_64(x)
@ -167,7 +182,7 @@
/* Sync.
*/
# if defined(U3_OS_linux)
# if defined(U3_OS_linux) || defined(U3_OS_mingw)
# define c3_sync(fd) (fdatasync(fd))
# elif defined(U3_OS_osx)
# define c3_sync(fd) (fcntl(fd, F_FULLFSYNC, 0))
@ -182,7 +197,7 @@
# if defined(U3_OS_linux)
# include <stdio_ext.h>
# define c3_fpurge __fpurge
# elif defined(U3_OS_bsd) || defined(U3_OS_osx)
# elif defined(U3_OS_bsd) || defined(U3_OS_osx) || defined(U3_OS_mingw)
# define c3_fpurge fpurge
# else
# error "port: fpurge"
@ -190,7 +205,7 @@
/* Stat.
*/
# if defined(U3_OS_linux)
# if defined(U3_OS_linux) || defined(U3_OS_mingw)
# define c3_stat_mtime(dp) (u3_time_t_in_ts((dp)->st_mtime))
# elif defined(U3_OS_osx)
# define c3_stat_mtime(dp) (u3_time_in_ts(&((dp)->st_mtimespec)))
@ -200,6 +215,16 @@
# define lseek64 lseek
# else
# error "port: timeconvert"
# endif
/* Null.
*/
# if defined(U3_OS_linux) || defined(U3_OS_bsd) || defined(U3_OS_osx)
# define c3_dev_null "/dev/null"
# elif defined(U3_OS_mingw)
# define c3_dev_null "nul"
# else
# error "port: /dev/null"
# endif
/* Static assertion.

View File

@ -21,9 +21,16 @@
/* u3kc: tier 3 functions
*/
u3_noun
u3kc_con(u3_noun a,
u3_noun b);
/* u3kc_bex(): binary exponent.
*/
u3_noun
u3kc_bex(u3_atom);
/* u3kc_con(): binary loobean conjunction.
*/
u3_noun
u3kc_con(u3_noun a,
u3_noun b);
/* u3kc_mix(): binary xor.
*/

View File

@ -138,39 +138,12 @@
u3_noun u3qea_de(u3_atom, u3_atom);
u3_noun u3qea_en(u3_atom, u3_atom);
u3_noun u3qes_hsh(u3_atom, u3_atom, u3_atom, u3_atom, u3_atom, u3_atom);
u3_noun u3qes_hsl(u3_atom, u3_atom, u3_atom, u3_atom, u3_atom,
u3_atom, u3_atom, u3_atom);
u3_noun u3qes_pbk(u3_atom, u3_atom, u3_atom, u3_atom);
u3_noun u3qes_pbl(u3_atom, u3_atom, u3_atom, u3_atom, u3_atom, u3_atom);
u3_noun u3qe_shax(u3_atom);
u3_noun u3qe_shay(u3_atom, u3_atom);
u3_noun u3qe_shas(u3_atom, u3_atom);
u3_noun u3qe_shal(u3_atom, u3_atom);
u3_noun u3qe_sha1(u3_atom, u3_atom);
u3_atom u3qe_fein_ob(u3_atom pyn);
u3_atom u3qe_fynd_ob(u3_atom pyn);
u3_noun u3qe_hmac(u3_noun, u3_atom, u3_atom,
u3_atom, u3_atom, u3_atom, u3_atom);
u3_noun u3qe_argon2(u3_atom, u3_atom, u3_atom,
u3_atom, u3_atom, u3_atom,
u3_atom, u3_atom, u3_atom, u3_atom,
u3_atom, u3_atom, u3_atom, u3_atom);
u3_noun u3qe_blake(u3_atom wid, u3_atom dat,
u3_atom wik, u3_atom dak, u3_atom out);
u3_noun u3qe_ripe(u3_atom wid, u3_atom dat);
u3_noun u3qe_make(u3_atom has, u3_atom prv);
u3_noun u3qe_reco(u3_atom has, u3_atom sig_v, u3_atom sig_r, u3_atom sig_s);
u3_noun u3qe_sign(u3_atom has, u3_atom prv);
u3_noun u3qe_en_base16(u3_atom len, u3_atom dat);
u3_noun u3qe_de_base16(u3_atom inp);

View File

@ -2,6 +2,9 @@
**
** This file is in the public domain.
*/
#include <openssl/opensslv.h>
/** Constants.
**/
/* u3a_bits: number of bits in word-addressed pointer. 29 == 2GB.

View File

@ -2,8 +2,18 @@
**
*/
/* u3_log(): logs to stderr or redirects to configured function.
/* u3l_log(): logs to stderr or redirects to configured function.
*/
void
u3l_log(const char* format, ...)
__attribute__ ((format (printf, 1, 2)));
/* u3l_punt(): condtionally logs a named punt
* (e.g. "mint-punt" for the `name` "mint")
* when `pro` is u3_none, and returns pro.
* For use when a jet driver declines to handle
* a core, when the user should be somehow notified
* (e.g. in a cryptographic jet).
*/
u3_weak
u3l_punt(const char* name, u3_weak pro);

View File

@ -14,6 +14,10 @@
c3_d
u3m_boot_lite(void);
/* u3m_stop(): graceful shutdown cleanup. */
void
u3m_stop(void);
/* u3m_bail(): bail out. Does not return.
**
** Bail motes:

View File

@ -336,6 +336,33 @@
c3_y* c_y,
u3_atom d);
/* u3r_bytes_fit():
**
** Copy (len_w) bytes of (a) into (buf_y) if it fits, returning overage.
*/
c3_w
u3r_bytes_fit(c3_w len_w,
c3_y* buf_y,
u3_atom a);
/* u3r_bytes_alloc():
**
** Copy (len_w) bytes starting at (a_w) from (b) into a fresh allocation.
*/
c3_y*
u3r_bytes_alloc(c3_w a_w,
c3_w len_w,
u3_atom b);
/* u3r_bytes_all():
**
** Allocate and return a new byte array with all the bytes of (a),
** storing the length in (len_w).
*/
c3_y*
u3r_bytes_all(c3_w* len_w,
u3_atom a);
/* u3r_chop():
**
** Into the bloq space of `met`, from position `fum` for a
@ -374,6 +401,15 @@
u3r_word(c3_w a_w,
u3_atom b);
/* u3r_word_fit():
**
** Fill (out_w) with (a) if it fits, returning success.
*/
c3_t
u3r_word_fit(c3_w* out_w,
u3_atom a);
/* u3r_chub():
**
** Return double-word (a_w) of (b).

View File

@ -215,22 +215,40 @@
};
#endif
/* u3_utty: unix tty.
*/
struct _u3_utty;
/* u3_ustm: uv stream.
*/
typedef union _u3_ustm {
uv_pipe_t pop_u;
uv_tcp_t wax_u;
uv_tty_t tty_u;
} u3_ustm;
/* u3_ttyf: simple unix tty function.
*/
typedef c3_o (*u3_ttyf)(struct _u3_utty* uty_u);
/* u3_utty: unix tty.
*/
typedef struct _u3_utty {
union {
uv_pipe_t pop_u;
uv_tcp_t wax_u;
};
u3_ustm pin_u; // input stream
u3_ustm pop_u; // output stream
struct _u3_utty* nex_u; // next in host list
u3_ttyf sta_f; // start tty
u3_ttyf sto_f; // clean up tty
u3_ttyf hij_f; // hijack tty for cooked print
u3_ttyf loj_f; // release tty from cooked print
c3_o (*wsz_f)
(struct _u3_utty* uty_u,
c3_l* col_l,
c3_l* row_l); // return tty window size
c3_i fid_i; // file descriptor
c3_w tid_l; // terminal identity number
u3_utfo ufo_u; // escape sequences
c3_i cug_i; // blocking fcntl flags
c3_i nob_i; // nonblocking fcntl flags
u3_utat tat_u; // control state
struct termios bak_u; // cooked terminal state
struct termios raw_u; // raw terminal state
struct _u3_auto* car_u; // driver hack
} u3_utty;
@ -294,6 +312,9 @@
c3_d now_d; // event tick
uv_loop_t* lup_u; // libuv event loop
u3_usig* sig_u; // signal list
#if defined(U3_OS_mingw)
HANDLE cev_u; // Ctrl-C event handle
#endif
u3_utty* uty_u; // linked terminal list
u3_opts ops_u; // commandline options
c3_i xit_i; // exit code for shutdown
@ -635,7 +656,8 @@
/* u3_king: all executing piers.
*/
typedef struct _u3_king {
c3_c* certs_c; // ssl certificate dump
void (*ssl_curl_f)(void*); // setup ssl CAs in CURL*
void (*ssl_x509_f)(void*); // setup ssl CAs in X509_STORE*
u3_pier* pir_u; // pier list
uv_timer_t tim_u; // gc timer
} u3_king;
@ -710,7 +732,7 @@
*/
u3_atom
u3_time_in_ts(struct timespec* tim_ts);
#if defined(U3_OS_linux)
#if defined(U3_OS_linux) || defined(U3_OS_mingw)
/* u3_time_t_in_ts(): urbit time from time_t.
*/
u3_atom
@ -1097,6 +1119,11 @@
void
u3_term_log_exit(void);
/* u3_ptty_init(): initialize platform-specific tty.
*/
u3_utty*
u3_ptty_init(uv_loop_t* lup_u, const c3_c** err_c);
/** Ames, packet networking.
**/
@ -1283,7 +1310,8 @@
u3_noun who, // identity
u3_noun ven, // boot event
u3_noun pil, // type-of/path-to pill
u3_noun pax); // path to pier
u3_noun pax, // path to pier
u3_weak fed); // extra private keys
/* u3_pier_stay(): restart the new pier system.
*/
@ -1328,7 +1356,7 @@
/* u3_dawn_vent(): validated boot event
*/
u3_noun
u3_dawn_vent(u3_noun seed);
u3_dawn_vent(u3_noun ship, u3_noun seed);
/* u3_king_commence(): start the daemon
*/
@ -1365,6 +1393,11 @@
void
u3_king_grab(void* ptr_v);
/* u3_daemon_init(): platform-specific daemon mode initialization.
*/
void
u3_daemon_init();
/* u3_write_fd(): retry interrupts, continue partial writes, assert errors.
*/
void

View File

@ -32,6 +32,7 @@
}
}
}
u3_noun
u3wa_dec(u3_noun cor)
{

View File

@ -3,35 +3,33 @@
*/
#include "all.h"
u3_noun
u3qc_bex(u3_atom a)
{
mpz_t a_mp;
/* functions
*/
u3_noun
u3qc_bex(u3_atom a)
{
mpz_t a_mp;
if ( !_(u3a_is_cat(a)) ) {
return u3m_bail(c3__fail);
}
else {
mpz_init_set_ui(a_mp, 1);
mpz_mul_2exp(a_mp, a_mp, a);
return u3i_mp(a_mp);
}
if ( !_(u3a_is_cat(a)) ) {
return u3m_bail(c3__fail);
}
u3_noun
u3wc_bex(u3_noun cor)
{
u3_noun a;
else {
mpz_init_set_ui(a_mp, 1);
mpz_mul_2exp(a_mp, a_mp, a);
if ( (u3_none == (a = u3r_at(u3x_sam, cor))) ||
(c3n == u3ud(a)) )
{
return u3m_bail(c3__exit);
} else {
return u3qc_bex(a);
}
return u3i_mp(a_mp);
}
}
u3_noun
u3kc_bex(u3_atom a)
{
u3_noun b = u3qc_bex(a);
u3z(a);
return b;
}
u3_noun
u3wc_bex(u3_noun cor)
{
u3_noun a = u3x_at(u3x_sam, cor);
return u3qc_bex(u3x_atom(a));
}

View File

@ -2,85 +2,49 @@
**
*/
#include "all.h"
#include <urcrypt.h>
#include <openssl/aes.h>
/* All of the CBC hoon truncates its key and prv inputs by passing them to
* the ECB functions, which truncate them, hence the raw u3r_bytes unpacking.
*/
typedef int (*urcrypt_cbc)(c3_y**,
size_t*,
c3_y*,
c3_y*,
urcrypt_realloc_t);
/* functions
*/
u3_noun
u3qea_cbca_en(u3_atom key,
static u3_atom
_cqea_cbc_help(c3_y* key_y, u3_atom iv, u3_atom msg, urcrypt_cbc low_f)
{
u3_atom ret;
c3_w met_w;
c3_y iv_y[16];
c3_y* msg_y = u3r_bytes_all(&met_w, msg);
size_t len = met_w;
u3r_bytes(0, 16, iv_y, iv);
if ( 0 != (*low_f)(&msg_y, &len, key_y, iv_y, &u3a_realloc) ) {
ret = u3_none;
}
else {
ret = u3i_bytes(len, msg_y);
}
u3a_free(msg_y);
return ret;
}
static u3_atom
_cqea_cbca_en(u3_atom key,
u3_atom iv,
u3_atom msg)
{
c3_y key_y[16];
c3_y iv_y[16];
c3_w len_msg_w;
c3_w len_out_w;
c3_y *msg_y;
c3_y *out_y;
u3_atom out;
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 16);
c3_assert(u3r_met(3, iv) <= 16);
len_msg_w = u3r_met(3, msg);
len_out_w = (len_msg_w % 16) == 0 ? len_msg_w : len_msg_w + (16 - (len_msg_w % 16));
len_msg_w = len_out_w;
msg_y = u3a_malloc(len_msg_w);
out_y = u3a_malloc(len_out_w);
{
int i = 15;
do {
key_y[i] = u3r_byte(15-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
iv_y[i] = u3r_byte(15-i, iv);
i--;
} while (i >= 0);
}
{
int i = len_msg_w - 1;
do {
msg_y[i] = u3r_byte((len_msg_w - 1)-i, msg);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_encrypt_key(key_y, 128, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_cbc_encrypt(msg_y, out_y, len_msg_w, &key_u, iv_y, AES_ENCRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = len_out_w - 1;
int j = 0;
c3_y tmp;
do {
tmp = out_y[i];
out_y[i] = out_y[j];
out_y[j] = tmp;
i--; j++;
} while (i > j);
}
out = u3i_bytes(len_out_w, out_y);
u3a_free(msg_y);
u3a_free(out_y);
return out;
u3r_bytes(0, 16, key_y, key);
return _cqea_cbc_help(key_y, iv, msg, &urcrypt_aes_cbca_en);
}
u3_noun
@ -93,84 +57,18 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_cbca_en(a, b, c);
return u3l_punt("cbca-en", _cqea_cbca_en(a, b, c));
}
}
u3_noun
u3qea_cbca_de(u3_atom key,
static u3_atom
_cqea_cbca_de(u3_atom key,
u3_atom iv,
u3_atom msg)
{
c3_y key_y[16];
c3_y iv_y[16];
c3_w len_msg_w;
c3_w len_out_w;
c3_y *msg_y;
c3_y *out_y;
u3_atom out;
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 16);
c3_assert(u3r_met(3, iv) <= 16);
len_msg_w = u3r_met(3, msg);
len_out_w = (len_msg_w % 16) == 0 ? len_msg_w : len_msg_w + (16 - (len_msg_w % 16));
len_msg_w = len_out_w;
msg_y = u3a_malloc(len_msg_w);
out_y = u3a_malloc(len_out_w);
{
int i = 15;
do {
key_y[i] = u3r_byte(15-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
iv_y[i] = u3r_byte(15-i, iv);
i--;
} while (i >= 0);
}
{
int i = len_msg_w - 1;
do {
msg_y[i] = u3r_byte((len_msg_w - 1)-i, msg);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_decrypt_key(key_y, 128, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_cbc_encrypt(msg_y, out_y, len_msg_w, &key_u, iv_y, AES_DECRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = len_out_w - 1;
int j = 0;
c3_y tmp;
do {
tmp = out_y[i];
out_y[i] = out_y[j];
out_y[j] = tmp;
i--; j++;
} while (i > j);
}
out = u3i_bytes(len_out_w, out_y);
u3a_free(msg_y);
u3a_free(out_y);
return out;
u3r_bytes(0, 16, key_y, key);
return _cqea_cbc_help(key_y, iv, msg, &urcrypt_aes_cbca_de);
}
u3_noun
@ -183,84 +81,18 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_cbca_de(a, b, c);
return u3l_punt("cbca-de", _cqea_cbca_de(a, b, c));
}
}
u3_noun
u3qea_cbcb_en(u3_atom key,
static u3_atom
_cqea_cbcb_en(u3_atom key,
u3_atom iv,
u3_atom msg)
{
c3_y key_y[24];
c3_y iv_y[16];
c3_w len_msg_w;
c3_w len_out_w;
c3_y *msg_y;
c3_y *out_y;
u3_atom out;
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 24);
c3_assert(u3r_met(3, iv) <= 16);
len_msg_w = u3r_met(3, msg);
len_out_w = (len_msg_w % 16) == 0 ? len_msg_w : len_msg_w + (16 - (len_msg_w % 16));
len_msg_w = len_out_w;
msg_y = u3a_malloc(len_msg_w);
out_y = u3a_malloc(len_out_w);
{
int i = 23;
do {
key_y[i] = u3r_byte(23-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
iv_y[i] = u3r_byte(15-i, iv);
i--;
} while (i >= 0);
}
{
int i = len_msg_w - 1;
do {
msg_y[i] = u3r_byte((len_msg_w - 1)-i, msg);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_encrypt_key(key_y, 192, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_cbc_encrypt(msg_y, out_y, len_msg_w, &key_u, iv_y, AES_ENCRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = len_out_w - 1;
int j = 0;
c3_y tmp;
do {
tmp = out_y[i];
out_y[i] = out_y[j];
out_y[j] = tmp;
i--; j++;
} while (i > j);
}
out = u3i_bytes(len_out_w, out_y);
u3a_free(msg_y);
u3a_free(out_y);
return out;
u3r_bytes(0, 24, key_y, key);
return _cqea_cbc_help(key_y, iv, msg, &urcrypt_aes_cbcb_en);
}
u3_noun
@ -273,84 +105,18 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_cbcb_en(a, b, c);
return u3l_punt("cbcb-en", _cqea_cbcb_en(a, b, c));
}
}
u3_noun
u3qea_cbcb_de(u3_atom key,
static u3_atom
_cqea_cbcb_de(u3_atom key,
u3_atom iv,
u3_atom msg)
{
c3_y key_y[24];
c3_y iv_y[16];
c3_w len_msg_w;
c3_w len_out_w;
c3_y *msg_y;
c3_y *out_y;
u3_atom out;
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 24);
c3_assert(u3r_met(3, iv) <= 16);
len_msg_w = u3r_met(3, msg);
len_out_w = (len_msg_w % 16) == 0 ? len_msg_w : len_msg_w + (16 - (len_msg_w % 16));
len_msg_w = len_out_w;
msg_y = u3a_malloc(len_msg_w);
out_y = u3a_malloc(len_out_w);
{
int i = 23;
do {
key_y[i] = u3r_byte(23-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
iv_y[i] = u3r_byte(15-i, iv);
i--;
} while (i >= 0);
}
{
int i = len_msg_w - 1;
do {
msg_y[i] = u3r_byte((len_msg_w - 1)-i, msg);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_decrypt_key(key_y, 192, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_cbc_encrypt(msg_y, out_y, len_msg_w, &key_u, iv_y, AES_DECRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = len_out_w - 1;
int j = 0;
c3_y tmp;
do {
tmp = out_y[i];
out_y[i] = out_y[j];
out_y[j] = tmp;
i--; j++;
} while (i > j);
}
out = u3i_bytes(len_out_w, out_y);
u3a_free(msg_y);
u3a_free(out_y);
return out;
u3r_bytes(0, 24, key_y, key);
return _cqea_cbc_help(key_y, iv, msg, &urcrypt_aes_cbcb_de);
}
u3_noun
@ -363,84 +129,18 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_cbcb_de(a, b, c);
return u3l_punt("cbcb-de", _cqea_cbcb_de(a, b, c));
}
}
u3_noun
u3qea_cbcc_en(u3_atom key,
static u3_atom
_cqea_cbcc_en(u3_atom key,
u3_atom iv,
u3_atom msg)
{
c3_y key_y[32];
c3_y iv_y[16];
c3_w len_msg_w;
c3_w len_out_w;
c3_y *msg_y;
c3_y *out_y;
u3_atom out;
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 32);
c3_assert(u3r_met(3, iv) <= 16);
len_msg_w = u3r_met(3, msg);
len_out_w = (len_msg_w % 16) == 0 ? len_msg_w : len_msg_w + (16 - (len_msg_w % 16));
len_msg_w = len_out_w;
msg_y = u3a_malloc(len_msg_w);
out_y = u3a_malloc(len_out_w);
{
int i = 31;
do {
key_y[i] = u3r_byte(31-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
iv_y[i] = u3r_byte(15-i, iv);
i--;
} while (i >= 0);
}
{
int i = len_msg_w - 1;
do {
msg_y[i] = u3r_byte((len_msg_w - 1)-i, msg);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_encrypt_key(key_y, 256, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_cbc_encrypt(msg_y, out_y, len_msg_w, &key_u, iv_y, AES_ENCRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = len_out_w - 1;
int j = 0;
c3_y tmp;
do {
tmp = out_y[i];
out_y[i] = out_y[j];
out_y[j] = tmp;
i--; j++;
} while (i > j);
}
out = u3i_bytes(len_out_w, out_y);
u3a_free(msg_y);
u3a_free(out_y);
return out;
u3r_bytes(0, 32, key_y, key);
return _cqea_cbc_help(key_y, iv, msg, &urcrypt_aes_cbcc_en);
}
u3_noun
@ -453,84 +153,18 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_cbcc_en(a, b, c);
return u3l_punt("cbcc-en", _cqea_cbcc_en(a, b, c));
}
}
u3_noun
u3qea_cbcc_de(u3_atom key,
static u3_atom
_cqea_cbcc_de(u3_atom key,
u3_atom iv,
u3_atom msg)
{
c3_y key_y[32];
c3_y iv_y[16];
c3_w len_msg_w;
c3_w len_out_w;
c3_y *msg_y;
c3_y *out_y;
u3_atom out;
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 32);
c3_assert(u3r_met(3, iv) <= 16);
len_msg_w = u3r_met(3, msg);
len_out_w = (len_msg_w % 16) == 0 ? len_msg_w : len_msg_w + (16 - (len_msg_w % 16));
len_msg_w = len_out_w;
msg_y = u3a_malloc(len_msg_w);
out_y = u3a_malloc(len_out_w);
{
int i = 31;
do {
key_y[i] = u3r_byte(31-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
iv_y[i] = u3r_byte(15-i, iv);
i--;
} while (i >= 0);
}
{
int i = len_msg_w - 1;
do {
msg_y[i] = u3r_byte((len_msg_w - 1)-i, msg);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_decrypt_key(key_y, 256, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_cbc_encrypt(msg_y, out_y, len_msg_w, &key_u, iv_y, AES_DECRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = len_out_w - 1;
int j = 0;
c3_y tmp;
do {
tmp = out_y[i];
out_y[i] = out_y[j];
out_y[j] = tmp;
i--; j++;
} while (i > j);
}
out = u3i_bytes(len_out_w, out_y);
u3a_free(msg_y);
u3a_free(out_y);
return out;
u3r_bytes(0, 32, key_y, key);
return _cqea_cbc_help(key_y, iv, msg, &urcrypt_aes_cbcc_de);
}
u3_noun
@ -543,6 +177,6 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_cbcc_de(a, b, c);
return u3l_punt("cbcc-de", _cqea_cbcc_de(a, b, c));
}
}

View File

@ -2,64 +2,38 @@
**
*/
#include "all.h"
#include <urcrypt.h>
#include <openssl/aes.h>
#include "aes_siv.h"
typedef int (*urcrypt_ecb)(c3_y*, c3_y[16], c3_y[16]);
/* functions
*/
u3_noun
u3qea_ecba_en(u3_atom key,
/* All of the ECB hoon truncates its key and blk inputs with +fe, in these
* jets we unpack with an unconditional u3r_bytes */
static u3_atom
_cqea_ecb_help(c3_y* key_y, u3_atom blk, urcrypt_ecb low_f)
{
c3_y blk_y[16], out_y[16];
u3r_bytes(0, 16, blk_y, blk);
if ( 0 != (*low_f)(key_y, blk_y, out_y) ) {
return u3_none;
}
else {
return u3i_bytes(16, out_y);
}
}
static u3_atom
_cqea_ecba_en(u3_atom key,
u3_atom blk)
{
c3_y key_y[16];
c3_y blk_y[16];
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 16);
c3_assert(u3r_met(3, blk) <= 16);
{
int i = 15;
do {
key_y[i] = u3r_byte(15-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
blk_y[i] = u3r_byte(15-i, blk);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_encrypt_key(key_y, 128, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_ecb_encrypt(blk_y, blk_y, &key_u, AES_ENCRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = 15;
int j = 0;
c3_y tmp;
do {
tmp = blk_y[i];
blk_y[i] = blk_y[j];
blk_y[j] = tmp;
i--; j++;
} while (i > j);
}
return u3i_bytes(16, blk_y);
u3r_bytes(0, 16, key_y, key);
return _cqea_ecb_help(key_y, blk, &urcrypt_aes_ecba_en);
}
u3_noun
@ -72,60 +46,17 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_ecba_en(a, b);
return u3l_punt("ecba-en", _cqea_ecba_en(a, b));
}
}
u3_noun
u3qea_ecba_de(u3_atom key,
static u3_atom
_cqea_ecba_de(u3_atom key,
u3_atom blk)
{
c3_y key_y[16];
c3_y blk_y[16];
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 16);
c3_assert(u3r_met(3, blk) <= 16);
{
int i = 15;
do {
key_y[i] = u3r_byte(15-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
blk_y[i] = u3r_byte(15-i, blk);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_decrypt_key(key_y, 128, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_ecb_encrypt(blk_y, blk_y, &key_u, AES_DECRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = 15;
int j = 0;
c3_y tmp;
do {
tmp = blk_y[i];
blk_y[i] = blk_y[j];
blk_y[j] = tmp;
i--; j++;
} while (i > j);
}
return u3i_bytes(16, blk_y);
u3r_bytes(0, 16, key_y, key);
return _cqea_ecb_help(key_y, blk, &urcrypt_aes_ecba_de);
}
u3_noun
@ -138,61 +69,17 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_ecba_de(a, b);
return u3l_punt("ecba-de", _cqea_ecba_de(a, b));
}
}
u3_noun
u3qea_ecbb_en(u3_atom key,
static u3_atom
_cqea_ecbb_en(u3_atom key,
u3_atom blk)
{
c3_y key_y[24];
c3_y blk_y[16];
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 24);
c3_assert(u3r_met(3, blk) <= 16);
{
int i = 23;
do {
key_y[i] = u3r_byte(23-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
blk_y[i] = u3r_byte(15-i, blk);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_encrypt_key(key_y, 192, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_ecb_encrypt(blk_y, blk_y, &key_u, AES_ENCRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = 15;
int j = 0;
c3_y tmp;
do {
tmp = blk_y[i];
blk_y[i] = blk_y[j];
blk_y[j] = tmp;
i--; j++;
} while (i > j);
}
return u3i_bytes(16, blk_y);
u3r_bytes(0, 24, key_y, key);
return _cqea_ecb_help(key_y, blk, &urcrypt_aes_ecbb_en);
}
u3_noun
@ -205,60 +92,17 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_ecbb_en(a, b);
return u3l_punt("ecbb-en", _cqea_ecbb_en(a, b));
}
}
u3_noun
u3qea_ecbb_de(u3_atom key,
static u3_atom
_cqea_ecbb_de(u3_atom key,
u3_atom blk)
{
c3_y key_y[24];
c3_y blk_y[16];
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 24);
c3_assert(u3r_met(3, blk) <= 16);
{
int i = 23;
do {
key_y[i] = u3r_byte(23-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
blk_y[i] = u3r_byte(15-i, blk);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_decrypt_key(key_y, 192, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_ecb_encrypt(blk_y, blk_y, &key_u, AES_DECRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = 15;
int j = 0;
c3_y tmp;
do {
tmp = blk_y[i];
blk_y[i] = blk_y[j];
blk_y[j] = tmp;
i--; j++;
} while (i > j);
}
return u3i_bytes(16, blk_y);
u3r_bytes(0, 24, key_y, key);
return _cqea_ecb_help(key_y, blk, &urcrypt_aes_ecbb_de);
}
u3_noun
@ -271,61 +115,17 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_ecbb_de(a, b);
return u3l_punt("ecbb-de", _cqea_ecbb_de(a, b));
}
}
u3_noun
u3qea_ecbc_en(u3_atom key,
static u3_atom
_cqea_ecbc_en(u3_atom key,
u3_atom blk)
{
c3_y key_y[32];
c3_y blk_y[16];
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 32);
c3_assert(u3r_met(3, blk) <= 16);
{
int i = 31;
do {
key_y[i] = u3r_byte(31-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
blk_y[i] = u3r_byte(15-i, blk);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_encrypt_key(key_y, 256, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_ecb_encrypt(blk_y, blk_y, &key_u, AES_ENCRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = 15;
int j = 0;
c3_y tmp;
do {
tmp = blk_y[i];
blk_y[i] = blk_y[j];
blk_y[j] = tmp;
i--; j++;
} while (i > j);
}
return u3i_bytes(16, blk_y);
u3r_bytes(0, 32, key_y, key);
return _cqea_ecb_help(key_y, blk, &urcrypt_aes_ecbc_en);
}
u3_noun
@ -338,60 +138,17 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_ecbc_en(a, b);
return u3l_punt("ecbc-en", _cqea_ecbc_en(a, b));
}
}
u3_noun
u3qea_ecbc_de(u3_atom key,
static u3_atom
_cqea_ecbc_de(u3_atom key,
u3_atom blk)
{
c3_y key_y[32];
c3_y blk_y[16];
AES_KEY key_u;
c3_assert(u3r_met(3, key) <= 32);
c3_assert(u3r_met(3, blk) <= 16);
{
int i = 31;
do {
key_y[i] = u3r_byte(31-i, key);
i--;
} while (i >= 0);
}
{
int i = 15;
do {
blk_y[i] = u3r_byte(15-i, blk);
i--;
} while (i >= 0);
}
if ( 0 != AES_set_decrypt_key(key_y, 256, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_ecb_encrypt(blk_y, blk_y, &key_u, AES_DECRYPT);
}
/* array reverse - we can write backwards u3i_bytes *
* in the unlikely event that this becomes a problem */
{
int i = 15;
int j = 0;
c3_y tmp;
do {
tmp = blk_y[i];
blk_y[i] = blk_y[j];
blk_y[j] = tmp;
i--; j++;
} while (i > j);
}
return u3i_bytes(16, blk_y);
u3r_bytes(0, 32, key_y, key);
return _cqea_ecb_help(key_y, blk, &urcrypt_aes_ecbc_de);
}
u3_noun
@ -404,6 +161,6 @@
c3n == u3ud(b) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_ecbc_de(a, b);
return u3l_punt("ecbc-de", _cqea_ecbc_de(a, b));
}
}

View File

@ -2,175 +2,182 @@
**
*/
#include "all.h"
#include <urcrypt.h>
#include <openssl/aes.h>
#include "aes_siv.h"
typedef int (*urcrypt_siv)(c3_y*, size_t,
urcrypt_aes_siv_data*, size_t,
c3_y*, c3_y[16], c3_y*);
/* functions
*/
static void u3r_bytes_reverse(c3_w a_w,
c3_w b_w,
c3_y* c_y, /* out */
u3_atom d) /* in */
*/
// soc_w = number of items
// mat_w = size in bytes of assoc array
// dat_w = size of allocation (array + atom storage)
static void
_cqea_measure_ads(u3_noun ads, c3_w* soc_w, c3_w *mat_w, c3_w *dat_w)
{
u3r_bytes(a_w, b_w, c_y, d);
c3_w i_w;
for (i_w = 0; i_w < ((b_w - a_w) / 2) ; i_w++) {
c3_y lo = c_y[i_w];
c3_y hi = c_y[b_w - i_w - 1];
c_y[i_w] = hi;
c_y[b_w - i_w - 1] = lo;
u3_noun i, t;
c3_w a_w, b_w, tmp_w, met_w;
for ( a_w = b_w = 0, t = ads; u3_nul != t; ++a_w ) {
u3x_cell(t, &i, &t);
if ( c3n == u3ud(i) ) {
u3m_bail(c3__exit);
return;
}
else {
tmp_w = b_w;
b_w += u3r_met(3, i);
if ( b_w < tmp_w ) {
u3m_bail(c3__fail);
return;
}
}
}
return;
// check for size overflows
tmp_w = a_w * sizeof(urcrypt_aes_siv_data);
if ( (tmp_w / a_w) != sizeof(urcrypt_aes_siv_data) ) {
u3m_bail(c3__fail);
}
else if ( (*dat_w = tmp_w + b_w) < tmp_w ) {
u3m_bail(c3__fail);
}
else {
*soc_w = a_w;
*mat_w = tmp_w;
}
}
static u3_noun _siv_en(c3_y* key_y,
c3_w keysize,
u3_noun ads,
u3_atom txt)
// assumes ads is a valid (list @) because it's already been measured
static void
_cqea_encode_ads(u3_noun ads,
c3_w mat_w,
urcrypt_aes_siv_data *dat_u)
{
AES_SIV_CTX* ctx = AES_SIV_CTX_new();
if ( 0 == ctx ) {
return u3_none;
c3_w met_w;
u3_noun i, t;
urcrypt_aes_siv_data *cur_u;
c3_y *dat_y = ((c3_y*) dat_u) + mat_w;
for ( cur_u = dat_u, t = ads; u3_nul != t; t = u3t(t), ++cur_u ) {
i = u3h(t);
met_w = u3r_met(3, i);
u3r_bytes(0, met_w, dat_y, i);
cur_u->length = met_w;
cur_u->bytes = dat_y;
dat_y += met_w;
}
}
if ( 0 == AES_SIV_Init(ctx, key_y, keysize) ) {
AES_SIV_CTX_free(ctx);
return u3_none;
static void
_cqea_ads_free(urcrypt_aes_siv_data *dat_u)
{
if ( NULL != dat_u ) {
u3a_free(dat_u);
}
}
while (u3_nul != ads) {
c3_w ad_w = u3r_met(3, u3h(ads));
c3_y* ad_y = u3a_malloc(ad_w);
u3r_bytes_reverse(0, ad_w, ad_y, u3h(ads));
c3_w ret = AES_SIV_AssociateData(ctx, ad_y, ad_w);
u3a_free(ad_y);
if ( 0 == ret ) {
AES_SIV_CTX_free(ctx);
return u3_none;
}
ads = u3t(ads);
static urcrypt_aes_siv_data*
_cqea_ads_alloc(u3_noun ads, c3_w *soc_w)
{
if ( !ads ) {
*soc_w = 0;
return NULL;
}
else {
c3_w mat_w, dat_w;
urcrypt_aes_siv_data *dat_u;
c3_w txt_w = u3r_met(3, txt);
c3_y* txt_y = u3a_malloc(txt_w);
u3r_bytes_reverse(0, txt_w, txt_y, txt);
const c3_w iv_w = 16;
c3_y iv_y[iv_w];
c3_y* out_y = u3a_malloc(txt_w);
if ( 0 == AES_SIV_EncryptFinal(ctx, iv_y, out_y, txt_y, txt_w) ) {
u3a_free(out_y);
u3a_free(txt_y);
AES_SIV_CTX_free(ctx);
return u3_none;
_cqea_measure_ads(ads, soc_w, &mat_w, &dat_w);
dat_u = u3a_malloc(dat_w);
_cqea_encode_ads(ads, mat_w, dat_u);
return dat_u;
}
}
static u3_noun
_cqea_siv_en(c3_y* key_y,
c3_w key_w,
u3_noun ads,
u3_atom txt,
urcrypt_siv low_f)
{
u3_noun ret;
c3_w txt_w, soc_w;
c3_y *txt_y, *out_y, iv_y[16];
urcrypt_aes_siv_data *dat_u;
dat_u = _cqea_ads_alloc(ads, &soc_w);
txt_y = u3r_bytes_all(&txt_w, txt);
out_y = u3a_malloc(txt_w);
ret = ( 0 != (*low_f)(txt_y, txt_w, dat_u, soc_w, key_y, iv_y, out_y) )
? u3_none
: u3nt(u3i_bytes(16, iv_y),
u3i_words(1, &txt_w),
u3i_bytes(txt_w, out_y));
u3a_free(txt_y);
AES_SIV_CTX_free(ctx);
// Read the first 16 bytes as the "iv"
u3_noun iv = u3i_bytes(16, iv_y);
u3_noun msg = u3i_bytes(txt_w, out_y);
// Reverse byte order for output
u3_noun rev_iv = u3kc_rev(3, iv_w, iv);
u3_noun rev_msg = u3kc_rev(3, txt_w, msg);
u3a_free(out_y);
return u3nt(rev_iv, u3i_words(1, &txt_w), rev_msg);
_cqea_ads_free(dat_u);
return ret;
}
static u3_noun _siv_de(c3_y* key_y,
c3_w keysize,
u3_noun ads,
u3_atom iv,
u3_atom len,
u3_atom txt)
static u3_noun
_cqea_siv_de(c3_y* key_y,
c3_w key_w,
u3_noun ads,
u3_atom iv,
u3_atom len,
u3_atom txt,
urcrypt_siv low_f)
{
AES_SIV_CTX* ctx = AES_SIV_CTX_new();
if ( 0 == ctx ) {
return u3_none;
c3_w txt_w;
if ( !u3r_word_fit(&txt_w, len) ) {
return u3m_bail(c3__fail);
}
else {
u3_noun ret;
c3_w soc_w;
c3_y *txt_y, *out_y, iv_y[16];
urcrypt_aes_siv_data *dat_u;
if ( 0 == AES_SIV_Init(ctx, key_y, keysize) ) {
AES_SIV_CTX_free(ctx);
return u3_none;
}
u3r_bytes(0, 16, iv_y, iv);
dat_u = _cqea_ads_alloc(ads, &soc_w);
txt_y = u3r_bytes_alloc(0, txt_w, txt);
out_y = u3a_malloc(txt_w);
if ( c3y == u3qa_gth(u3r_met(3, txt), len) ) {
return u3_none;
}
ret = ( 0 != (*low_f)(txt_y, txt_w, dat_u, soc_w, key_y, iv_y, out_y) )
? u3_none
: u3nc(0, u3i_bytes(txt_w, out_y));
while (u3_nul != ads) {
c3_w ad_w = u3r_met(3, u3h(ads));
c3_y* ad_y = u3a_malloc(ad_w);
u3r_bytes_reverse(0, ad_w, ad_y, u3h(ads));
c3_w ret = AES_SIV_AssociateData(ctx, ad_y, ad_w);
u3a_free(ad_y);
if ( 0 == ret ) {
AES_SIV_CTX_free(ctx);
return u3_none;
}
ads = u3t(ads);
}
c3_w txt_w = u3r_word(0, len);
c3_y* txt_y = u3a_malloc(txt_w);
u3r_bytes_reverse(0, txt_w, txt_y, txt);
const c3_w iv_w = 16;
c3_y iv_y[iv_w];
u3r_bytes_reverse(0, 16, iv_y, iv);
c3_y* out_y = u3a_malloc(txt_w);
if ( 0 == AES_SIV_DecryptFinal(ctx, out_y, iv_y, txt_y, txt_w) ) {
u3a_free(out_y);
u3a_free(txt_y);
AES_SIV_CTX_free(ctx);
u3a_free(out_y);
_cqea_ads_free(dat_u);
// Either decryption failed or signature bad or there was a memory
// error. Some of these are deterministic and some are not. return u3_none
// to fallback to the Nock implementation.
return u3_none;
return ret;
}
u3a_free(txt_y);
AES_SIV_CTX_free(ctx);
// Read the first 16 bytes as the "iv"
u3_noun msg = u3i_bytes(txt_w, out_y);
// Reverse byte order for output
u3_noun rev_msg = u3kc_rev(3, txt_w, msg);
u3a_free(out_y);
return u3nc(0, rev_msg);
}
// the siv* hoon doesn't explicitly check keysizes, but all of these functions
// have fixed maximum keysizes, so we will punt if we get a key that is too
// large.
u3_noun
u3qea_siva_en(u3_atom key,
static u3_noun
_cqea_siva_en(u3_atom key,
u3_noun ads,
u3_atom txt)
{
c3_y key_y[32];
if (u3r_met(3, key) > 32) {
if ( u3r_met(3, key) > 32 ) {
return u3_none;
}
u3r_bytes_reverse(0, 32, key_y, key);
return _siv_en(key_y, 32, ads, txt);
else {
c3_y key_y[32];
u3r_bytes(0, 32, key_y, key);
return _cqea_siv_en(key_y, 32, ads, txt, &urcrypt_aes_siva_en);
}
}
u3_noun
@ -185,24 +192,25 @@ u3wea_siva_en(u3_noun cor)
c3n == u3ud(txt) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_siva_en(key, ads, txt);
return u3l_punt("siva-en", _cqea_siva_en(key, ads, txt));
}
}
u3_noun
u3qea_siva_de(u3_atom key,
static u3_noun
_cqea_siva_de(u3_atom key,
u3_noun ads,
u3_atom iv,
u3_atom len,
u3_atom txt)
{
c3_y key_y[32];
if (u3r_met(3, key) > 32) {
if ( u3r_met(3, key) > 32 ) {
return u3_none;
}
u3r_bytes_reverse(0, 32, key_y, key);
return _siv_de(key_y, 32, ads, iv, len, txt);
else {
c3_y key_y[32];
u3r_bytes(0, 32, key_y, key);
return _cqea_siv_de(key_y, 32, ads, iv, len, txt, &urcrypt_aes_siva_de);
}
}
u3_noun
@ -220,25 +228,26 @@ u3wea_siva_de(u3_noun cor)
c3n == u3ud(txt) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_siva_de(key, ads, iv, len, txt);
return u3l_punt("siva-de", _cqea_siva_de(key, ads, iv, len, txt));
}
}
u3_noun
u3qea_sivb_en(u3_atom key,
static u3_noun
_cqea_sivb_en(u3_atom key,
u3_noun ads,
u3_atom txt)
{
c3_y key_y[48];
if (u3r_met(3, key) > 48) {
if ( u3r_met(3, key) > 48 ) {
return u3_none;
}
u3r_bytes_reverse(0, 48, key_y, key);
return _siv_en(key_y, 48, ads, txt);
else {
c3_y key_y[48];
u3r_bytes(0, 48, key_y, key);
return _cqea_siv_en(key_y, 48, ads, txt, &urcrypt_aes_sivb_en);
}
}
u3_noun
u3wea_sivb_en(u3_noun cor)
{
@ -251,24 +260,25 @@ u3wea_sivb_en(u3_noun cor)
c3n == u3ud(txt) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_sivb_en(key, ads, txt);
return u3l_punt("sivb-en", _cqea_sivb_en(key, ads, txt));
}
}
u3_noun
u3qea_sivb_de(u3_atom key,
static u3_noun
_cqea_sivb_de(u3_atom key,
u3_noun ads,
u3_atom iv,
u3_atom len,
u3_atom txt)
{
c3_y key_y[48];
if (u3r_met(3, key) > 48) {
if ( u3r_met(3, key) > 48 ) {
return u3_none;
}
u3r_bytes_reverse(0, 48, key_y, key);
return _siv_de(key_y, 48, ads, iv, len, txt);
else {
c3_y key_y[48];
u3r_bytes(0, 48, key_y, key);
return _cqea_siv_de(key_y, 48, ads, iv, len, txt, &urcrypt_aes_sivb_de);
}
}
u3_noun
@ -286,24 +296,23 @@ u3wea_sivb_de(u3_noun cor)
c3n == u3ud(txt) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_sivb_de(key, ads, iv, len, txt);
return u3l_punt("sivb-de", _cqea_sivb_de(key, ads, iv, len, txt));
}
}
u3_noun
u3qea_sivc_en(u3_atom key,
static u3_noun
_cqea_sivc_en(u3_atom key,
u3_noun ads,
u3_atom txt)
{
c3_y key_y[64];
if (u3r_met(3, key) > 64) {
if ( u3r_met(3, key) > 64 ) {
return u3_none;
}
u3r_bytes_reverse(0, 64, key_y, key);
return _siv_en(key_y, 64, ads, txt);
else {
c3_y key_y[64];
u3r_bytes(0, 64, key_y, key);
return _cqea_siv_en(key_y, 64, ads, txt, &urcrypt_aes_sivc_en);
}
}
u3_noun
@ -318,25 +327,25 @@ u3wea_sivc_en(u3_noun cor)
c3n == u3ud(txt) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_sivc_en(key, ads, txt);
return u3l_punt("sivc-en", _cqea_sivc_en(key, ads, txt));
}
}
u3_noun
u3qea_sivc_de(u3_atom key,
static u3_noun
_cqea_sivc_de(u3_atom key,
u3_noun ads,
u3_atom iv,
u3_atom len,
u3_atom txt)
{
c3_y key_y[64];
if ( u3r_met(3, key) > 64 ) {
return u3_none;
}
u3r_bytes_reverse(0, 64, key_y, key);
return _siv_de(key_y, 64, ads, iv, len, txt);
else {
c3_y key_y[64];
u3r_bytes(0, 64, key_y, key);
return _cqea_siv_de(key_y, 64, ads, iv, len, txt, &urcrypt_aes_sivc_de);
}
}
u3_noun
@ -354,6 +363,6 @@ u3wea_sivc_de(u3_noun cor)
c3n == u3ud(txt) ) {
return u3m_bail(c3__exit);
} else {
return u3qea_sivc_de(key, ads, iv, len, txt);
return u3l_punt("sivc-de", _cqea_sivc_de(key, ads, iv, len, txt));
}
}

View File

@ -1,121 +0,0 @@
/* j/5/aes.c
**
*/
#include "all.h"
#if defined(U3_OS_osx)
#include <CommonCrypto/CommonCryptor.h>
#else
#include <openssl/aes.h>
#endif
/* functions
*/
u3_noun
u3qea_en(u3_atom a,
u3_atom b)
{
c3_y a_y[32];
c3_y b_y[16];
#if defined(U3_OS_osx)
size_t siz_i = 0;
#else
AES_KEY key_u;
#endif
c3_assert(u3r_met(3, a) <= 32);
c3_assert(u3r_met(3, b) <= 16);
u3r_bytes(0, 32, a_y, a);
u3r_bytes(0, 16, b_y, b);
#if defined(U3_OS_osx)
if ( kCCSuccess != CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
kCCOptionECBMode, a_y, kCCKeySizeAES256, 0, b_y,
16, b_y, 16, &siz_i) )
{
return u3m_bail(c3__exit);
}
else c3_assert(16 == siz_i);
#else
if ( 0 != AES_set_encrypt_key(a_y, 256, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_encrypt(b_y, b_y, &key_u);
}
#endif
return u3i_bytes(16, b_y);
}
u3_noun
u3wea_en(u3_noun cor)
{
u3_noun a, b;
if ( c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0) ||
c3n == u3ud(a) ||
c3n == u3ud(b) )
{
return u3m_bail(c3__exit);
}
else {
return u3qea_en(a, b);
}
}
u3_noun
u3qea_de(u3_atom a,
u3_atom b)
{
c3_y a_y[32];
c3_y b_y[16];
#if defined(U3_OS_osx)
size_t siz_i = 0;
#else
AES_KEY key_u;
#endif
c3_assert(u3r_met(3, a) <= 32);
c3_assert(u3r_met(3, b) <= 16);
u3r_bytes(0, 32, a_y, a);
u3r_bytes(0, 16, b_y, b);
#if defined(U3_OS_osx)
if ( kCCSuccess != CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
kCCOptionECBMode, a_y, kCCKeySizeAES256, 0, b_y,
16, b_y, 16, &siz_i) )
{
return u3m_bail(c3__exit);
}
else c3_assert(16 == siz_i);
#else
if ( 0 != AES_set_decrypt_key(a_y, 256, &key_u) ) {
return u3m_bail(c3__exit);
}
else {
AES_decrypt(b_y, b_y, &key_u);
}
#endif
return u3i_bytes(16, b_y);
}
u3_noun
u3wea_de(u3_noun cor)
{
u3_noun a, b;
if ( c3n == u3r_mean(cor, u3x_sam_2, &a, u3x_sam_3, &b, 0) ||
c3n == u3ud(a) ||
c3n == u3ud(b) )
{
return u3m_bail(c3__exit);
}
else {
return u3qea_de(a, b);
}
}

View File

@ -2,104 +2,108 @@
**
*/
#include "all.h"
#include <argon2.h>
#include <urcrypt.h>
/* helpers
*/
int argon2_alloc(uint8_t** output, size_t bytes)
static int
argon2_alloc(uint8_t** output, size_t bytes)
{
*output = u3a_malloc(bytes);
return (NULL != output);
return 1;
}
void argon2_free(uint8_t* memory, size_t bytes)
static void
argon2_free(uint8_t* memory, size_t bytes)
{
u3a_free(memory);
}
static c3_t
_cqear_unpack_type(c3_y* 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;
}
}
/* 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)) );
c3_y typ_u;
c3_w out_w, wik_w, wix_w, wid_w, wis_w, ver_w, ted_w, mem_w, tim_w;
// 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);
// 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);
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", 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 ( !(u3r_word_fit(&out_w, out) &&
u3r_word_fit(&wik_w, wik) &&
u3r_word_fit(&wix_w, wix) &&
u3r_word_fit(&wid_w, wid) &&
u3r_word_fit(&wis_w, wis)) ) {
// too big to allocate
return u3m_bail(c3__fail);
}
if ( ARGON2_OK != argon_res ) {
u3l_log("\nargon2 error: %s", argon2_error_message(argon_res));
u3m_bail(c3__exit);
else if ( !(_cqear_unpack_type(&typ_u, type) &&
u3r_word_fit(&ver_w, version) &&
u3r_word_fit(&ted_w, threads) &&
u3r_word_fit(&mem_w, mem_cost) &&
u3r_word_fit(&tim_w, time_cost)) ) {
return u3_none;
}
else {
u3_atom ret;
c3_y *key_y = u3r_bytes_alloc(0, wik_w, key),
*ex_y = u3r_bytes_alloc(0, wix_w, extra),
*dat_y = u3r_bytes_alloc(0, wid_w, dat),
*sat_y = u3r_bytes_alloc(0, wis_w, sat),
*out_y = u3a_malloc(out_w);
u3z(key); u3z(extra); u3z(dat); u3z(sat);
return u3kc_rev(3, out, u3i_bytes(out, outhash));
const c3_c* err_c = urcrypt_argon2(
typ_u, ver_w, ted_w, mem_w, tim_w,
wik_w, key_y,
wix_w, ex_y,
wid_w, dat_y,
wis_w, sat_y,
out_w, out_y,
&argon2_alloc,
&argon2_free);
u3a_free(key_y);
u3a_free(ex_y);
u3a_free(dat_y);
u3a_free(sat_y);
if ( NULL == err_c ) {
ret = u3i_bytes(out_w, out_y);
}
else {
ret = u3_none;
u3l_log("argon2-error: %s", err_c);
}
u3a_free(out_y);
return ret;
}
}
u3_noun
@ -138,9 +142,10 @@
return u3m_bail(c3__exit);
}
else {
return u3qe_argon2(out, type, version,
threads, mem_cost, time_cost,
wik, key, wix, extra,
wid, dat, wis, sat);
return u3l_punt("argon2",
_cqe_argon2(out, type, version,
threads, mem_cost, time_cost,
wik, key, wix, extra,
wid, dat, wis, sat));
}
}

View File

@ -2,52 +2,41 @@
**
*/
#include "all.h"
#include <argon2.h>
#include <blake2.h>
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qe_blake(u3_atom wid, u3_atom dat,
static u3_atom
_cqe_blake(u3_atom wid, u3_atom dat,
u3_atom wik, u3_atom dak,
u3_atom out)
{
c3_assert(_(u3a_is_cat(wid)) && _(u3a_is_cat(wik)) && _(u3a_is_cat(out)));
// flip endianness for the internal blake2b function
dat = u3qc_rev(3, wid, dat);
dak = u3qc_rev(3, wik, dak);
c3_y* dat_y = (c3_y*)u3a_malloc(wid);
u3r_bytes(0, wid, (void*)dat_y, dat);
c3_y* dak_y = (c3_y*)u3a_malloc(wik);
u3r_bytes(0, wik, (void*)dak_y, dak);
int ret;
c3_y out_y[64];
ret = blake2b(out_y, // OUT: output
out, // IN: max output size
dat_y, // IN: msg body
wid, // IN: msg len
dak_y, // IN: key body
wik); // IN: key len
/* free() BEFORE checking error code;
we don't want to leak memory if we return early
*/
u3a_free(dat_y);
u3a_free(dak_y);
if ( 0 != ret )
{
u3l_log("\rblake jet: cryto lib error");
return u3m_bail(c3__exit);
c3_w wid_w;
if ( !u3r_word_fit(&wid_w, wid) ) {
// impossible to represent an atom this large
return u3m_bail(c3__fail);
}
else {
// the hoon adjusts these widths to its liking
int err;
u3_atom ret;
c3_y out_y[64], dak_y[64];
c3_w wik_w = c3_min(wik, 64),
out_w = c3_max(1, c3_min(out, 64));
c3_y *dat_y = u3r_bytes_alloc(0, wid_w, dat);
return u3kc_rev(3, out, u3i_bytes(out, out_y));
u3r_bytes(0, wik_w, dak_y, dak);
err = urcrypt_blake2(wid_w, dat_y, wik_w, dak_y, out_w, out_y);
u3a_free(dat_y);
if ( 0 == err ) {
return u3i_bytes(out_w, out_y);
}
else {
return u3_none;
}
}
}
u3_noun
@ -64,9 +53,8 @@
u3r_cell(key, &wik, &dak) || u3ud(wik) || u3ud(dak) ||
u3ud(out) )
{
u3l_log("\rblake jet: arguments error");
return u3m_bail(c3__exit);
} else {
return u3qe_blake(wid, dat, wik, dak, out);
return u3l_punt("blake", _cqe_blake(wid, dat, wik, dak, out));
}
}

View File

@ -2,88 +2,28 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <ge.h>
#include "ge-additions.h"
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qc_add_double_scalarmult(u3_atom a,
u3_atom a_point,
static u3_atom
_cqee_add_double_scalarmult(u3_atom a,
u3_atom b,
u3_atom b_point)
u3_atom c,
u3_atom d)
{
c3_y met_w;
c3_y a_y[32], b_y[32], c_y[32], d_y[32], out_y[32];
met_w = u3r_met(3, a);
if (met_w > 32) {
return u3m_bail(c3__fail);
if ( (0 != u3r_bytes_fit(32, a_y, a)) ||
(0 != u3r_bytes_fit(32, b_y, b)) ||
(0 != u3r_bytes_fit(32, c_y, c)) ||
(0 != u3r_bytes_fit(32, d_y, d)) ||
(0 != urcrypt_ed_add_double_scalarmult(a_y, b_y, c_y, d_y, out_y)) ) {
return u3_none;
}
c3_y a_y[32];
memset(a_y, 0, 32);
u3r_bytes(0, met_w, a_y, a);
met_w = u3r_met(3, a_point);
if (met_w > 32) {
return u3m_bail(c3__fail);
else {
return u3i_bytes(32, out_y);
}
c3_y a_point_y[32];
memset(a_point_y, 0, 32);
u3r_bytes(0, met_w, a_point_y, a_point);
met_w = u3r_met(3, b);
if (met_w > 32) {
return u3m_bail(c3__fail);
}
c3_y b_y[32];
memset(b_y, 0, 32);
u3r_bytes(0, met_w, b_y, b);
met_w = u3r_met(3, b_point);
if (met_w > 32) {
return u3m_bail(c3__fail);
}
c3_y b_point_y[32];
memset(b_point_y, 0, 32);
u3r_bytes(0, met_w, b_point_y, b_point);
ge_p3 A;
if (ge_frombytes_negate_vartime(&A, a_point_y) != 0) {
return u3m_bail(c3__exit);
}
ge_p3 B;
if (ge_frombytes_negate_vartime(&B, b_point_y) != 0) {
return u3m_bail(c3__exit);
}
// Undo the negation from above. See add_scalar.c in the ed25519 distro.
fe_neg(A.X, A.X);
fe_neg(A.T, A.T);
fe_neg(B.X, B.X);
fe_neg(B.T, B.T);
// Perform the multiplications of a*A and b*B
ge_p3 a_result, b_result;
ge_scalarmult(&a_result, a_y, &A);
ge_scalarmult(&b_result, b_y, &B);
// Sum those two points
ge_cached b_result_cached;
ge_p3_to_cached(&b_result_cached, &b_result);
ge_p1p1 sum;
ge_add(&sum, &a_result, &b_result_cached);
ge_p3 final_result;
ge_p1p1_to_p3(&final_result, &sum);
c3_y output_y[32];
ge_p3_tobytes(output_y, &final_result);
return u3i_bytes(32, output_y);
}
u3_noun
@ -101,6 +41,7 @@
{
return u3m_bail(c3__exit);
} else {
return u3qc_add_double_scalarmult(a, b, c, d);
return u3l_punt("add-double-scalarmult",
_cqee_add_double_scalarmult(a, b, c, d));
}
}

View File

@ -2,61 +2,26 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <ge.h>
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qc_add_scalarmult_scalarmult_base(u3_atom a,
u3_atom a_point,
u3_atom b)
static u3_atom
_cqee_add_scalarmult_scalarmult_base(u3_atom a,
u3_atom b,
u3_atom c)
{
c3_y met_w;
c3_y a_y[32], b_y[32], c_y[32], out_y[32];
met_w = u3r_met(3, a);
if (met_w > 32) {
return u3m_bail(c3__fail);
if ( (0 != u3r_bytes_fit(32, a_y, a)) ||
(0 != u3r_bytes_fit(32, b_y, b)) ||
(0 != u3r_bytes_fit(32, c_y, c)) ||
(0 != urcrypt_ed_add_scalarmult_scalarmult_base(a_y, b_y, c_y, out_y)) ) {
return u3_none;
}
c3_y a_y[32];
memset(a_y, 0, 32);
u3r_bytes(0, met_w, a_y, a);
met_w = u3r_met(3, a_point);
if (met_w > 32) {
return u3m_bail(c3__fail);
else {
return u3i_bytes(32, out_y);
}
c3_y a_point_y[32];
memset(a_point_y, 0, 32);
u3r_bytes(0, met_w, a_point_y, a_point);
met_w = u3r_met(3, b);
if (met_w > 32) {
return u3m_bail(c3__fail);
}
c3_y b_y[32];
memset(b_y, 0, 32);
u3r_bytes(0, met_w, b_y, b);
ge_p3 A;
if (ge_frombytes_negate_vartime(&A, a_point_y) != 0) {
return u3m_bail(c3__exit);
}
// Undo the negation from above. See add_scalar.c in the ed25519 distro.
fe_neg(A.X, A.X);
fe_neg(A.T, A.T);
ge_p2 r;
ge_double_scalarmult_vartime(&r, a_y, &A, b_y);
c3_y output_y[32];
ge_tobytes(output_y, &r);
return u3i_bytes(32, output_y);
}
u3_noun
@ -73,6 +38,7 @@
{
return u3m_bail(c3__exit);
} else {
return u3qc_add_scalarmult_scalarmult_base(a, b, c);
return u3l_punt("add-scalarmult-scalarmult-base",
_cqee_add_scalarmult_scalarmult_base(a, b, c));
}
}

View File

@ -2,64 +2,25 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <ge.h>
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qc_point_add(u3_atom a,
static u3_atom
_cqee_point_add(u3_atom a,
u3_atom b)
{
c3_y met_w;
c3_y a_y[32], b_y[32], out_y[32];
met_w = u3r_met(3, a);
if (met_w > 32) {
return u3m_bail(c3__fail);
if ( (0 != u3r_bytes_fit(32, a_y, a)) ||
(0 != u3r_bytes_fit(32, b_y, b)) ||
(0 != urcrypt_ed_point_add(a_y, b_y, out_y)) ) {
return u3_none;
}
c3_y a_y[32];
memset(a_y, 0, 32);
u3r_bytes(0, met_w, a_y, a);
met_w = u3r_met(3, b);
if (met_w > 32) {
return u3m_bail(c3__fail);
else {
return u3i_bytes(32, out_y);
}
c3_y b_y[32];
memset(b_y, 0, 32);
u3r_bytes(0, met_w, b_y, b);
ge_p3 A;
if (ge_frombytes_negate_vartime(&A, a_y) != 0) {
return u3m_bail(c3__exit);
}
ge_p3 B;
if (ge_frombytes_negate_vartime(&B, b_y) != 0) {
return u3m_bail(c3__exit);
}
// Undo the negation from above. See add_scalar.c in the ed25519 distro.
fe_neg(A.X, A.X);
fe_neg(A.T, A.T);
fe_neg(B.X, B.X);
fe_neg(B.T, B.T);
ge_cached b_cached;
ge_p3_to_cached(&b_cached, &B);
ge_p1p1 sum;
ge_add(&sum, &A, &b_cached);
ge_p3 result;
ge_p1p1_to_p3(&result, &sum);
c3_y output_y[32];
ge_p3_tobytes(output_y, &result);
return u3i_bytes(32, output_y);
}
u3_noun
@ -74,6 +35,6 @@
{
return u3m_bail(c3__exit);
} else {
return u3qc_point_add(a, b);
return u3l_punt("point-add", _cqee_point_add(a, b));
}
}

View File

@ -2,32 +2,35 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <urcrypt.h>
/* functions
*/
static u3_atom
_cqee_puck(u3_atom sed)
{
c3_y sed_y[32];
if ( 0 != u3r_bytes_fit(32, sed_y, sed) ) {
// hoon explicitly crashes on mis-size
return u3m_bail(c3__exit);
}
else {
c3_y pub_y[32];
urcrypt_ed_puck(sed_y, pub_y);
return u3i_bytes(32, pub_y);
}
}
u3_noun
u3wee_puck(u3_noun cor)
{
c3_y pub_y[32];
c3_y sec_y[64];
c3_y sed_y[32];
c3_w met_w;
u3_noun a = u3r_at(u3x_sam, cor);
if ( (u3_none == a) || (c3n == u3ud(a)) ) {
return u3m_bail(c3__exit);
}
met_w = u3r_met(3, a);
if ( met_w > 32 ) {
return u3m_bail(c3__exit);
else {
return _cqee_puck(a);
}
memset(sed_y, 0, 32);
u3r_bytes(0, met_w, sed_y, a);
ed25519_create_keypair(pub_y, sec_y, sed_y);
return u3i_bytes(32, pub_y);
}

View File

@ -2,51 +2,25 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include "ge-additions.h"
#include "urcrypt.h"
/* functions
*/
u3_noun
u3qc_scalarmult(u3_atom a,
static u3_atom
_cqee_scalarmult(u3_atom a,
u3_atom b)
{
c3_y met_w;
c3_y a_y[32], b_y[32], out_y[32];
met_w = u3r_met(3, a);
if (met_w > 32) {
return u3m_bail(c3__exit);
if ( (0 != u3r_bytes_fit(32, a_y, a)) ||
(0 != u3r_bytes_fit(32, b_y, b)) ||
(0 != urcrypt_ed_scalarmult(a_y, b_y, out_y)) ) {
// hoon does not check size of inputs
return u3_none;
}
c3_y a_y[32];
memset(a_y, 0, 32);
u3r_bytes(0, met_w, a_y, a);
met_w = u3r_met(3, b);
if (met_w > 32) {
return u3m_bail(c3__exit);
else {
return u3i_bytes(32, out_y);
}
c3_y b_y[32];
memset(b_y, 0, 32);
u3r_bytes(0, met_w, b_y, b);
ge_p3 B;
if (ge_frombytes_negate_vartime(&B, b_y) != 0) {
return u3m_bail(c3__exit);
}
// Undo the negation from above. See add_scalar.c in the ed25519 distro.
fe_neg(B.X, B.X);
fe_neg(B.T, B.T);
ge_p3 result;
ge_scalarmult(&result, a_y, &B);
c3_y output_y[32];
ge_p3_tobytes(output_y, &result);
return u3i_bytes(32, output_y);
}
u3_noun
@ -61,6 +35,6 @@
{
return u3m_bail(c3__exit);
} else {
return u3qc_scalarmult(a, b);
return u3l_punt("scalarmult", _cqee_scalarmult(a, b));
}
}

View File

@ -2,35 +2,34 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <ge.h>
#include <urcrypt.h>
/* functions
*/
static u3_atom
_cqee_scalarmult_base(u3_atom a)
{
c3_y a_y[32];
if ( 0 != u3r_bytes_fit(32, a_y, a) ) {
return u3_none;
}
else {
c3_y out_y[32];
urcrypt_ed_scalarmult_base(a_y, out_y);
return u3i_bytes(32, out_y);
}
}
u3_noun
u3wee_scalarmult_base(u3_noun cor)
{
u3_noun scalar = u3r_at(u3x_sam, cor);
u3_noun a = u3r_at(u3x_sam, cor);
if ( (u3_none == scalar) || (c3n == u3ud(scalar)) ) {
if ( (u3_none == a) || (c3n == u3ud(a)) ) {
return u3m_bail(c3__exit);
}
c3_w met_w = u3r_met(3, scalar);
if ( met_w > 32 ) {
return u3m_bail(c3__fail);
else {
return u3l_punt("scalarmult-base", _cqee_scalarmult_base(a));
}
c3_y scalar_y[32];
memset(scalar_y, 0, 32);
u3r_bytes(0, met_w, scalar_y, scalar);
ge_p3 R;
ge_scalarmult_base(&R, scalar_y);
c3_y output_y[32];
ge_p3_tobytes(output_y, &R);
return u3i_bytes(32, output_y);
}

View File

@ -2,33 +2,26 @@
**
*/
#include "all.h"
#include <urcrypt.h>
#include <ed25519.h>
u3_noun
u3qee_shar(u3_atom pub, u3_atom sek)
static u3_atom
_cqee_shar(u3_atom pub, u3_atom sek)
{
c3_y pub_y[32], sek_y[32], self_y[32], exp_y[64], shr_y[32];
c3_w met_pub_w, met_sek_w;
c3_y pub_y[32], sek_y[32];
met_pub_w = u3r_met(3, pub);
met_sek_w = u3r_met(3, sek);
if ( (met_pub_w > 32) || (met_sek_w > 32) ) {
if ( 0 != u3r_bytes_fit(32, pub_y, pub) ) {
// pub is not size checked in the hoon
return u3_none;
}
else if ( 0 != u3r_bytes_fit(32, sek_y, sek) ) {
// sek explicitly bails through suck
return u3m_bail(c3__exit);
}
u3r_bytes(0, 32, pub_y, pub);
u3r_bytes(0, 32, sek_y, sek);
memset(self_y, 0, 32);
memset(exp_y, 0, 64);
memset(shr_y, 0, 32);
ed25519_create_keypair(self_y, exp_y, sek_y);
ed25519_key_exchange(shr_y, pub_y, exp_y);
return u3i_bytes(32, shr_y);
else {
c3_y shr_y[32];
urcrypt_ed_shar(pub_y, sek_y, shr_y);
return u3i_bytes(32, shr_y);
}
}
u3_noun
@ -42,6 +35,6 @@
{
return u3m_bail(c3__exit);
} else {
return u3qee_shar(pub, sek);
return u3l_punt("shar", _cqee_shar(pub, sek));
}
}

View File

@ -2,40 +2,30 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <urcrypt.h>
/* functions
*/
static u3_noun
static u3_atom
_cqee_sign(u3_noun a,
u3_noun b)
{
c3_y sig_y[64];
c3_y sed_y[32];
c3_y pub_y[64];
c3_y sec_y[64];
c3_w mesm_w = u3r_met(3, a);
c3_w mess_w = u3r_met(3, b);
if ( 0 != u3r_bytes_fit(32, sed_y, b) ) {
// hoon calls suck, which calls puck, which crashes
return u3m_bail(c3__exit);
}
else {
c3_y sig_y[64];
c3_w met_w;
c3_y* mes_y = u3r_bytes_all(&met_w, a);
c3_y* mes_y = 0;
urcrypt_ed_sign(mes_y, met_w, sed_y, sig_y);
u3a_free(mes_y);
memset(sig_y, 0, 64);
memset(sed_y, 0, 32);
memset(pub_y, 0, 64);
memset(sec_y, 0, 64);
mes_y = u3a_malloc(mesm_w);
u3r_bytes(0, mesm_w, mes_y, a);
u3r_bytes(0, mess_w, sed_y, b);
ed25519_create_keypair(pub_y, sec_y, sed_y);
ed25519_sign(sig_y, mes_y, mesm_w, pub_y, sec_y);
u3a_free(mes_y);
return u3i_bytes(64, sig_y);
return u3i_bytes(64, sig_y);
}
}
u3_noun

View File

@ -2,36 +2,30 @@
**
*/
#include "all.h"
#include <ed25519.h>
#include <urcrypt.h>
/* functions
*/
static u3_noun
static u3_atom
_cqee_veri(u3_noun s,
u3_noun m,
u3_noun pk)
{
c3_y sig_y[64];
c3_y pub_y[32];
c3_w ret;
c3_y* mes_y;
c3_y sig_y[64], pub_y[32];
c3_w mesm_w = u3r_met(3, m);
if ( (0 != u3r_bytes_fit(64, sig_y, s)) ||
(0 != u3r_bytes_fit(32, pub_y, pk)) ) {
// hoon checks sizes, but weirdly and without crashes
return u3_none;
}
else {
c3_w met_w;
c3_y* mes_y = u3r_bytes_all(&met_w, m);
c3_t val_t = urcrypt_ed_veri(mes_y, met_w, pub_y, sig_y);
u3a_free(mes_y);
memset(sig_y, 0, 64);
memset(pub_y, 0, 32);
mes_y = u3a_malloc(mesm_w);
u3r_bytes(0, 64, sig_y, s);
u3r_bytes(0, 32, pub_y, pk);
u3r_bytes(0, mesm_w, mes_y, m);
ret = ed25519_verify(sig_y, mes_y, mesm_w, pub_y) == 1 ? c3y : c3n;
u3a_free(mes_y);
return ret;
return val_t ? c3y : c3n;
}
}
u3_noun
@ -43,6 +37,6 @@
u3x_sam_7, &c, 0) ) {
return u3m_bail(c3__fail);
} else {
return _cqee_veri(a, b, c);
return u3l_punt("veri", _cqee_veri(a, b, c));
}
}

View File

@ -2,62 +2,31 @@
**
*/
#include "all.h"
#include <openssl/evp.h>
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qe_ripe(u3_atom wid, u3_atom dat)
static u3_atom
_cqe_ripe(u3_atom wid, u3_atom dat)
{
c3_assert(_(u3a_is_cat(wid)));
dat = u3qc_rev(3, wid, dat);
c3_w len_w;
if ( !u3r_word_fit(&len_w, wid) ) {
return u3m_bail(c3__fail);
}
else {
u3_atom ret;
c3_y out_y[20];
c3_y *dat_y = u3r_bytes_alloc(0, len_w, dat);
c3_y* dat_y = (c3_y*)u3a_malloc(wid); // msg body
u3r_bytes(0, wid, (void*)dat_y, dat);
ret = ( 0 == urcrypt_ripemd160(dat_y, len_w, out_y) )
? u3i_bytes(20, out_y)
: u3_none;
const EVP_MD* rip_u = EVP_ripemd160(); // ripem algorithm
EVP_MD_CTX* con_u = EVP_MD_CTX_create();
/* perform signature
*/
c3_y sib_y[20]; // signature body
c3_w sil_w; // signature length
c3_w ret_w; // return code
ret_w = EVP_DigestInit_ex(con_u, rip_u, NULL);
if ( 1 != ret_w ) {
u3a_free(dat_y);
EVP_MD_CTX_destroy(con_u);
u3l_log("\rripe jet: crypto library fail 1");
return u3m_bail(c3__fail);
return ret;
}
ret_w = EVP_DigestUpdate(con_u, (void*)dat_y, wid);
u3a_free(dat_y);
if (1 != ret_w) {
EVP_MD_CTX_destroy(con_u);
u3l_log("\rripe jet: crypto library fail 2");
return u3m_bail(c3__fail);
}
ret_w = EVP_DigestFinal_ex(con_u, sib_y, &sil_w);
if ( 1 != ret_w ) {
EVP_MD_CTX_destroy(con_u);
u3l_log("\rripe jet: crypto library fail 3");
return u3m_bail(c3__fail);
}
EVP_MD_CTX_destroy(con_u);
/* endian conversion;
turn into noun for return
*/
return u3kc_rev(3, sil_w, u3i_bytes(sil_w, sib_y));
}
u3_noun
u3we_ripe(u3_noun cor)
{
@ -68,10 +37,9 @@
u3ud(wid) || u3ud(dat))
)
{
u3l_log("\rripe jet: argument error");
return u3m_bail(c3__exit);
}
else {
return u3qe_ripe(wid, dat);
return u3l_punt("ripe", _cqe_ripe(wid, dat));
}
}

View File

@ -2,48 +2,88 @@
**
*/
#include "all.h"
#include <stdint.h>
#include <errno.h>
#include <libscrypt.h>
#include <sha256.h>
static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t,
uint64_t, uint32_t, uint32_t, uint8_t *, size_t);
#include <urcrypt.h>
/* functions
*/
static u3_weak
_cqes_hs(u3_atom p, c3_w pwd_w,
u3_atom s, c3_w sal_w,
u3_atom n,
u3_atom r,
u3_atom z,
u3_atom d)
{
u3_noun chk;
c3_w out_w;
u3_noun
u3qes_hsl(u3_atom p, u3_atom pl,
if ( !u3r_word_fit(&out_w, d) ) {
return u3m_bail(c3__fail);
}
if ( 0 == r || 0 == z ) {
return u3m_bail(c3__exit);
}
chk = u3qc_bex(31);
if ( (c3n == u3qa_lth(pwd_w, chk)) ||
(c3n == u3qa_lth(sal_w, chk)) ) {
return u3m_bail(c3__exit);
}
u3z(chk);
chk = u3kc_bex(u3ka_dec(u3qc_xeb(n)));
if ( c3n == u3r_sing(n, chk) ) {
return u3m_bail(c3__exit);
}
u3z(chk);
if ( c3n == u3ka_lte(
u3ka_mul(u3qa_mul(128, r), u3ka_dec(u3qa_add(n, z))),
u3qc_bex(30)) ) {
return u3m_bail(c3__exit);
}
if ( (u3r_met(6, n) > 1) ||
(u3r_met(5, r) > 1) ||
(u3r_met(5, z) > 1) ) {
return u3_none;
}
else {
u3_noun pro;
c3_d n_d = u3r_chub(0, n);
c3_w r_w = u3r_word(0, r),
z_w = u3r_word(0, z);
c3_y *pwd_y = u3a_malloc(pwd_w),
*sal_y = u3a_malloc(sal_w),
*out_y = u3a_malloc(d);
u3r_bytes(0, pwd_w, pwd_y, p);
u3r_bytes(0, sal_w, sal_y, s);
pro = ( 0 == urcrypt_scrypt(pwd_y, pwd_w,
sal_y, sal_w,
n_d, r_w, z_w,
out_w, out_y) )
? u3i_bytes(out_w, out_y)
: u3_none;
u3a_free(pwd_y);
u3a_free(sal_y);
u3a_free(out_y);
return pro;
}
}
static u3_weak
_cqes_hsl(u3_atom p, u3_atom pl,
u3_atom s, u3_atom sl,
u3_atom n,
u3_atom r,
u3_atom z,
u3_atom d)
{
// asserting that n is power of 2 in _crypto_scrypt
if (!(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_cat(pl)) && _(u3a_is_cat(sl)) &&
_(u3a_is_cat(n)) && _(u3a_is_cat(r)) &&
_(u3a_is_cat(z)) && _(u3a_is_cat(d)) &&
(r != 0) && (z != 0) &&
(((c3_d)r * 128 * ((c3_d)n + z - 1)) <= (1 << 30))))
return u3m_bail(c3__exit);
c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(sl + 1);
u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s);
b_p[pl] = 0; b_s[sl]=0;
c3_y* buf = u3a_malloc(d);
if (_crypto_scrypt(b_p, pl, b_s, sl, n, r, z, buf, d) != 0)
return u3m_bail(c3__exit);
u3_noun res = u3i_bytes(d, buf);
u3a_free(b_p); u3a_free(b_s); u3a_free(buf);
return res;
c3_w pwd_w, sal_w;
if ( !(u3r_word_fit(&pwd_w, pl) &&
u3r_word_fit(&sal_w, sl)) ) {
return u3m_bail(c3__fail);
}
else {
return _cqes_hs(p, pwd_w, s, sal_w, n, r, z, d);
}
}
u3_noun
@ -52,41 +92,31 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t,
u3_noun p, pl, s, sl, n, r, z, d;
u3_noun q;
u3x_quil(u3r_at(u3x_sam, cor), &p, &pl, &s, &sl, &q);
u3x_quil(u3x_at(u3x_sam, cor), &p, &pl, &s, &sl, &q);
u3x_qual(q, &n, &r, &z, &d);
return u3qes_hsl(p, pl, s, sl, n, r, z, d);
if ( !(_(u3a_is_atom(p)) && _(u3a_is_atom(pl)) &&
_(u3a_is_atom(s)) && _(u3a_is_atom(sl)) &&
_(u3a_is_atom(n)) && _(u3a_is_atom(r)) &&
_(u3a_is_atom(z)) && _(u3a_is_atom(d))) ) {
return u3m_bail(c3__exit);
}
else {
return u3l_punt("scr-hsl", _cqes_hsl(p, pl, s, sl, n, r, z, d));
}
}
u3_noun
u3qes_hsh(u3_atom p,
static u3_weak
_cqes_hsh(u3_atom p,
u3_atom s,
u3_atom n,
u3_atom r,
u3_atom z,
u3_atom d)
{
// asserting that n is power of 2 in _crypto_scrypt
if (!(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_cat(n)) && _(u3a_is_cat(r)) &&
_(u3a_is_cat(z)) && _(u3a_is_cat(d)) &&
(r != 0) && (z != 0) &&
(((c3_d)r * 128 * ((c3_d)n + z - 1)) <= (1 << 30))))
return u3m_bail(c3__exit);
c3_w pl = u3r_met(3, p); c3_w sl = u3r_met(3, s);
c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(sl + 1);
u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s);
b_p[pl] = 0; b_s[sl]=0;
c3_y* buf = u3a_malloc(d);
if (_crypto_scrypt(b_p, pl, b_s, sl, n, r, z, buf, d) != 0)
return u3m_bail(c3__exit);
u3_noun res = u3i_bytes(d, buf);
u3a_free(b_p); u3a_free(b_s); u3a_free(buf);
return res;
return _cqes_hs(p, u3r_met(3, p),
s, u3r_met(3, s),
n, r, z, d);
}
u3_noun
@ -95,36 +125,62 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t,
u3_noun p, s, n, r, z, d;
u3_noun q;
u3x_quil(u3r_at(u3x_sam, cor), &p, &s, &n, &r, &q);
u3x_quil(u3x_at(u3x_sam, cor), &p, &s, &n, &r, &q);
u3x_cell(q, &z, &d);
return u3qes_hsh(p, s, n, r, z, d);
if ( !(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_atom(n)) && _(u3a_is_atom(r)) &&
_(u3a_is_atom(z)) && _(u3a_is_atom(d))) ) {
return u3m_bail(c3__exit);
}
else {
return u3l_punt("scr-hsh", _cqes_hsh(p, s, n, r, z, d));
}
}
u3_noun
u3qes_pbl(u3_atom p, u3_atom pl,
static u3_atom
_cqes_pb(u3_atom p, c3_w pwd_w,
u3_atom s, c3_w sal_w,
u3_atom c,
u3_atom d)
{
if ( (c > (1 << 28)) ||
(d > (1 << 30)) ) {
// max key length 1gb
// max iterations 2^28
return u3m_bail(c3__exit);
}
else {
u3_noun pro;
c3_w out_w;
c3_y *pwd_y = u3a_malloc(pwd_w),
*sal_y = u3a_malloc(sal_w),
*out_y = u3a_malloc(d);
u3r_bytes(0, pwd_w, pwd_y, p);
u3r_bytes(0, sal_w, sal_y, s);
urcrypt_scrypt_pbkdf_sha256(pwd_y, pwd_w, sal_y, sal_w, c, d, out_y);
pro = u3i_bytes(d, out_y);
u3a_free(pwd_y);
u3a_free(sal_y);
u3a_free(out_y);
return pro;
}
}
static u3_noun
_cqes_pbl(u3_atom p, u3_atom pl,
u3_atom s, u3_atom sl,
u3_atom c,
u3_atom d)
{
if (!(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_cat(pl)) && _(u3a_is_cat(sl)) &&
_(u3a_is_cat(c)) && _(u3a_is_cat(d)) &&
(d <= (1 << 30)) && (c <= (1 << 28)) &&
(c != 0)))
return u3m_bail(c3__exit);
c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(pl + 1);
u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s);
b_p[pl] = 0; b_s[sl]=0;
c3_y* buf = u3a_malloc(d);
libscrypt_PBKDF2_SHA256(b_p, pl, b_s, sl, c, buf, d);
u3_noun res = u3i_bytes(d, buf);
u3a_free(b_p); u3a_free(b_s); u3a_free(buf);
return res;
c3_w pwd_w, sal_w;
if ( !(u3r_word_fit(&pwd_w, pl) &&
u3r_word_fit(&sal_w, sl)) ) {
return u3m_bail(c3__fail);
}
else {
return _cqes_pb(p, pwd_w, s, sal_w, c, d);
}
}
u3_noun
@ -133,33 +189,25 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t,
u3_noun p, pl, s, sl, c, d;
u3_noun q;
u3x_quil(u3r_at(u3x_sam, cor), &p, &pl, &s, &sl, &q);
u3x_quil(u3x_at(u3x_sam, cor), &p, &pl, &s, &sl, &q);
u3x_cell(q, &c, &d);
return u3qes_pbl(p, pl, s, sl, c, d);
if ( !(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_atom(pl)) && _(u3a_is_atom(sl)) &&
_(u3a_is_atom(c)) && _(u3a_is_atom(d))) ) {
return u3m_bail(c3__exit);
}
else {
return _cqes_pbl(p, pl, s, sl, c, d);
}
}
u3_noun
u3qes_pbk(u3_atom p, u3_atom s, u3_atom c, u3_atom d)
static u3_atom
_cqes_pbk(u3_atom p, u3_atom s, u3_atom c, u3_atom d)
{
if (!(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_cat(c)) && _(u3a_is_cat(d)) &&
(d <= (1 << 30)) && (c <= (1 << 28)) &&
(c != 0)))
return u3m_bail(c3__exit);
c3_w pl = u3r_met(3, p); c3_w sl = u3r_met(3, s);
c3_y* b_p = u3a_malloc(pl + 1); c3_y* b_s= u3a_malloc(pl + 1);
u3r_bytes(0, pl, b_p, p); u3r_bytes(0, sl, b_s, s);
b_p[pl] = 0; b_s[sl]=0;
c3_y* buf = u3a_malloc(d);
libscrypt_PBKDF2_SHA256(b_p, pl, b_s, sl, c, buf, d);
u3_noun res = u3i_bytes(d, buf);
u3a_free(b_p); u3a_free(b_s); u3a_free(buf);
return res;
return _cqes_pb(p, u3r_met(3, p),
s, u3r_met(3, s),
c, d);
}
u3_noun
@ -167,24 +215,13 @@ static int _crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t,
{
u3_noun p, s, c, d;
u3x_qual(u3r_at(u3x_sam, cor), &p, &s, &c, &d);
u3x_qual(u3x_at(u3x_sam, cor), &p, &s, &c, &d);
return u3qes_pbk(p, s, c, d);
if ( !(_(u3a_is_atom(p)) && _(u3a_is_atom(s)) &&
_(u3a_is_atom(c)) && _(u3a_is_atom(d))) ) {
return u3m_bail(c3__exit);
}
else {
return _cqes_pbk(p, s, c, d);
}
}
/**
* crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):
* Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,
* p, buflen) and write the result into buf. The parameters r, p, and buflen
* must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N
* must be a power of 2 greater than 1.
*
* Return 0 on success; or -1 on error.
*/
static int
_crypto_scrypt(const uint8_t * passwd, size_t passwdlen,
const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p,
uint8_t * buf, size_t buflen)
{
return libscrypt_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen);
}

View File

@ -2,55 +2,111 @@
**
*/
#include "all.h"
#include "../include/secp256k1.h"
#include "../include/secp256k1_recovery.h"
#include "urcrypt.h"
#include <ent.h>
static urcrypt_secp_context* sec_u;
/* call at process start */
void
u3je_secp_init()
{
c3_y ent_y[32];
ent_getentropy(ent_y, 32);
sec_u = malloc(urcrypt_secp_prealloc_size());
if ( 0 != urcrypt_secp_init(sec_u, ent_y) ) {
u3l_log("u3e_secp_init failed");
abort();
}
}
/* call at process end */
void
u3je_secp_stop()
{
urcrypt_secp_destroy(sec_u);
free(sec_u);
sec_u = NULL;
}
/* util funcs
*/
/* no guarantees if 'in' and 'out' overlap / are the same */
static void byte_reverse(c3_y *i_y, /* in */
c3_y *o_y, /* out */
c3_w n_w) /* size */
static c3_t
_cqes_in_order(u3_atom a)
{
c3_w j_w;
for (j_w = 0; j_w < n_w; j_w++){
o_y[n_w - 1 - j_w] = i_y[j_w];
}
// this is the "n" parameter of the secp256k1 curve
static const c3_w now_w[8] = {
0xd0364141, 0xbfd25e8c, 0xaf48a03b, 0xbaaedce6,
0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff
};
return;
if ( 0 == a ) {
return 0;
}
else if ( c3y == u3a_is_cat(a) ) {
return 1;
}
else {
u3a_atom* a_u = u3a_to_ptr(a);
c3_w len_w = a_u->len_w;
if ( len_w < 8 ) {
return 1;
}
else if ( len_w > 8 ) {
return 0;
}
else {
c3_y i_y;
c3_w *buf_w = a_u->buf_w;
// loop from most to least significant words
for ( i_y = 8; i_y > 0; ) {
c3_w b_w = buf_w[i_y],
o_w = now_w[--i_y];
if ( b_w < o_w ) {
return 1;
}
else if ( b_w > o_w ) {
return 0;
}
}
return 1;
}
}
}
/* Identical to u3r_bytes, but reverses bytes in place.
could be cleaner if we modified u3r_bytes(), but not gonna do that.
This func exists bc Urbit code base is explicitly little-endian,
and secp256k1 library is explicitly big-endian.
Several times below we do the pattern of (1) invoke u3r_bytes, (2) invert. Do it in a func.
*/
static void u3r_bytes_reverse(c3_w a_w,
c3_w b_w,
c3_y* c_y, /* out */
u3_atom d) /* in */
static void
_cqes_unpack_fe(u3_atom k, c3_y out_y[32])
{
u3r_bytes(a_w, b_w, c_y, d);
c3_w i_w;
for (i_w = 0; i_w < ((b_w - a_w) / 2) ; i_w++) {
c3_y lo = c_y[i_w];
c3_y hi = c_y[b_w - i_w - 1];
c_y[i_w] = hi;
c_y[b_w - i_w - 1] = lo;
if ( _cqes_in_order(k) ) {
u3r_bytes(0, 32, out_y, k);
}
else {
u3m_bail(c3__exit);
}
return;
}
/* sign hash with priv key
*/
static u3_noun
_cqes_sign(u3_atom has,
u3_atom prv)
{
c3_y has_y[32];
if ( 0 != u3r_bytes_fit(32, has_y, has) ) {
return u3m_bail(c3__exit);
}
else {
c3_y prv_y[32], v_y, r_y[32], s_y[32];
_cqes_unpack_fe(prv, prv_y);
return( 0 == urcrypt_secp_sign(sec_u, has_y, prv_y, &v_y, r_y, s_y) )
? u3nt(v_y, u3i_bytes(32, r_y), u3i_bytes(32, s_y))
: u3_none;
}
}
u3_noun
u3we_sign(u3_noun cor)
@ -64,73 +120,36 @@ u3we_sign(u3_noun cor)
0)) ||
(c3n == u3ud(has)) ||
(c3n == u3ud(prv))) {
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
} else {
return (u3qe_sign(has, prv));
}
else {
return u3l_punt("secp-sign", _cqes_sign(has, prv));
}
}
u3_noun
u3qe_sign(u3_atom has,
u3_atom prv)
{
/* build library context object once (and only once) */
static secp256k1_context * ctx_u = NULL;
if (NULL == ctx_u) {
ctx_u = secp256k1_context_create(SECP256K1_CONTEXT_SIGN);
}
/* parse arguments, convert endianness */
c3_y has_y[32]; /* hash */
c3_y prv_y[32]; /* private key */
u3r_bytes_reverse(0, 32, has_y, has);
u3r_bytes_reverse(0, 32, prv_y, prv);
/* sign
N.B. if we want the 'v' field we can't use default secp256k1_ecdsa_sign(),
but must use secp256k1_ecdsa_sign_recoverable() */
c3_ws ret;
secp256k1_ecdsa_recoverable_signature sig_u;
ret = secp256k1_ecdsa_sign_recoverable(ctx_u, /* IN: context object */
& sig_u, /* OUT: signature */
(const c3_y *) has_y, /* IN: 32 byte hash to be signed */
(const c3_y *) prv_y, /* IN: 32 byte secret key */
(secp256k1_nonce_function) NULL, /* IN: nonce-function ptr ; NULL = default */
(const void *) NULL); /* IN: data for nonce function; not used */
if (1 != ret) {
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
}
/* convert opaque 65 byte signature into v + [r + s]
convert endianness while we're at it */
c3_y rec_y[64];
c3_ws v = 0;
ret = secp256k1_ecdsa_recoverable_signature_serialize_compact(ctx_u,
rec_y, /* OUT: 64 byte sig (r,s) */
& v, /* OUT: v */
& sig_u); /* IN: 65 byte sig */
if (1 != ret) {
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
}
c3_y s_y[32];
c3_y r_y[32];
byte_reverse(rec_y, r_y, 32);
byte_reverse(rec_y + 32, s_y, 32);
/* package s,r,v signature for return */
u3_noun s = u3i_words(8, (const c3_w*) s_y);
u3_noun r = u3i_words(8, (const c3_w*) r_y);
return (u3nt(v, r, s));
}
/* recover pubkey from signature (which is how we verify signatures)
*/
static u3_noun
_cqes_reco(u3_atom has,
u3_atom siv, /* signature: v */
u3_atom sir, /* signature: r */
u3_atom sis) /* signature: s */
{
c3_y has_y[32];
if ( !((siv < 4) && (0 == u3r_bytes_fit(32, has_y, has)) ) ) {
return u3m_bail(c3__exit);
}
else {
c3_y sir_y[32], sis_y[32], x_y[32], y_y[32];
c3_y siv_y = (c3_y) siv;
_cqes_unpack_fe(sir, sir_y);
_cqes_unpack_fe(sis, sis_y);
return
( 0 == urcrypt_secp_reco(sec_u, has_y, siv, sir_y, sis_y, x_y, y_y) )
? u3nc(u3i_bytes(32, x_y), u3i_bytes(32, y_y))
: u3_none;
}
}
u3_noun
u3we_reco(u3_noun cor)
@ -147,117 +166,32 @@ u3we_reco(u3_noun cor)
(c3n == u3ud(has)) ||
(c3n == u3ud(siv)) ||
(c3n == u3ud(sir)) ||
(c3n == u3ud(sis)) )
{
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
} else {
return u3qe_reco(has, siv, sir, sis);
(c3n == u3ud(sis)) ) {
return u3m_bail(c3__exit);
}
else {
return u3l_punt("secp-reco", _cqes_reco(has, siv, sir, sis));
}
}
u3_noun
u3qe_reco(u3_atom has,
u3_atom siv, /* signature: v */
u3_atom sir, /* signature: r */
u3_atom sis) /* signature: s */
static u3_atom
_cqes_make(u3_atom has,
u3_atom prv)
{
/* build library context object once (and only once) */
static secp256k1_context * ctx_u = NULL;
if (NULL == ctx_u) {
ctx_u = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY);
}
/* parse arguments, convert endianness */
c3_y has_y[32];
c3_y sir_y[32];
c3_y sis_y[32];
c3_y siv_y[1];
u3r_bytes_reverse(0, 32, has_y, has);
u3r_bytes_reverse(0, 32, sir_y, sir);
u3r_bytes_reverse(0, 32, sis_y, sis);
u3r_bytes_reverse(0, 1, siv_y, siv);
/* build the signature object */
c3_y ras_y[64]; /* priv key: r and s components */
c3_ws i_ws;
for (i_ws = 0; i_ws < 32; i_ws++) {
ras_y[i_ws] = sir_y[i_ws] ;
}
for (i_ws = 0; i_ws < 32; i_ws++) {
ras_y[i_ws + 32] = sis_y[i_ws] ;
}
c3_ws siv_ws = siv_y[0];
secp256k1_ecdsa_recoverable_signature sig_u;
memset( (void *) & sig_u, 0, sizeof(secp256k1_ecdsa_recoverable_signature) );
c3_ws ret = secp256k1_ecdsa_recoverable_signature_parse_compact(ctx_u, /* IN: context */
& sig_u, /* OUT: sig */
ras_y, /* IN: r/s */
siv_ws); /* IN: v */
if (1 != ret) {
u3l_log("\rsecp jet: crypto package error");
if ( 0 != u3r_bytes_fit(32, has_y, has) ) {
return u3m_bail(c3__exit);
}
/* turn sign into puk_u */
secp256k1_pubkey puk_u;
memset((void *) & puk_u, 0, sizeof(secp256k1_pubkey) );
ret = secp256k1_ecdsa_recover(ctx_u, /* IN: context */
& puk_u, /* OUT: pub key */
& sig_u, /* IN: signature */
has_y); /* IN: message has */
if (1 != ret) {
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
else {
c3_y prv_y[32], out_y[32];
_cqes_unpack_fe(prv, prv_y);
return ( 0 == urcrypt_secp_make(has_y, prv_y, out_y) )
? u3i_bytes(32, out_y)
: u3_none;
}
/* convert puk_u into serialized form that we can get x,y out of */
c3_y puk_y[65];
size_t outputlen = 65;
memset((void *) puk_y, 0, 65);
ret = secp256k1_ec_pubkey_serialize( ctx_u, /* IN: */
puk_y, /* OUT: */
& outputlen, /* OUT: */
& puk_u, /* IN: */
SECP256K1_EC_UNCOMPRESSED); /* IN: flags */
if (1 != ret) {
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
}
/* in file
subprojects/secp256k1/src/eckey_impl.h
func
secp256k1_eckey_puk_u_parse()
we can see
byte 0: signal bits (???)
bytes 1-32: x
bytes 33-64: y
convert endianness while we're at it */
c3_y x_y[32];
for (i_ws = 0; i_ws < 32; i_ws++) {
x_y[i_ws] = puk_y[32 - i_ws];
}
u3_noun x = u3i_bytes(32, x_y);
c3_y y_y[32];
for (i_ws = 0; i_ws < 32; i_ws++) {
y_y[i_ws] = puk_y[64 - i_ws];
}
u3_noun y = u3i_bytes(32, y_y);
/* returns x,y */
return(u3nc(x, y));
}
u3_noun
u3we_make(u3_noun cor)
{
@ -267,49 +201,10 @@ u3we_make(u3_noun cor)
u3x_sam_3, &prv,
0)) ||
(c3n == u3ud(has)) ||
(c3n == u3ud(prv)) )
{
u3l_log("\rsecp jet: crypto package error");
return u3m_bail(c3__exit);
} else {
return u3qe_make(has, prv);
}
}
u3_noun
u3qe_make(u3_atom has,
u3_atom prv)
{
c3_y hel_y[32]; /* hash, little endian */
c3_y heb_y[32]; /* hash, big endian */
u3r_bytes(0, 32, hel_y, has);
byte_reverse(hel_y, heb_y, 32);
c3_y pel_y[32]; /* priv key, little endian */
c3_y peb_y[32]; /* priv key, big endian */
u3r_bytes(0, 32, pel_y, prv);
byte_reverse(pel_y, peb_y, 32);
c3_ws ret_ws;
c3_y neb_y[32]; /* nonce */
ret_ws = secp256k1_nonce_function_rfc6979(neb_y, /* OUT: return arg for nonce */
(const c3_y *) heb_y, /* IN: message / hash */
(const c3_y *) peb_y, /* IN: key32 */
NULL, /* IN: algorithm (NULL == ECDSA) */
(void *) NULL, /* IN: arbitrary data pointer (unused) */
0); /* IN: attempt number (0 == normal) */
if (1 != ret_ws) {
u3l_log("\rsecp jet: crypto package error");
(c3n == u3ud(prv)) ) {
return u3m_bail(c3__exit);
}
c3_y nel_y[32];
byte_reverse(neb_y, nel_y, 32);
u3_noun non = u3i_words(8, (const c3_w*) nel_y);
return(non);
else {
return u3l_punt("secp-make", _cqes_make(has, prv));
}
}

View File

@ -2,42 +2,24 @@
**
*/
#include "all.h"
#if defined(U3_OS_osx)
#include <CommonCrypto/CommonDigest.h>
#else
#include <openssl/sha.h>
#endif
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qe_sha1(u3_atom wid, u3_atom dat)
static u3_noun
_cqe_sha1(u3_atom wid, u3_atom dat)
{
c3_assert(_(u3a_is_cat(wid)));
dat = u3qc_rev(3, wid, dat);
c3_w len_w;
if ( !u3r_word_fit(&len_w, wid) ) {
return u3m_bail(c3__fail);
}
else {
c3_y out_y[20];
c3_y *dat_y = u3r_bytes_alloc(0, len_w, dat);
c3_y* fat_y = u3a_malloc(wid + 1);
u3r_bytes(0, wid, fat_y, dat);
{
c3_y dig_y[32];
#if defined(U3_OS_osx)
CC_SHA1_CTX ctx_h;
CC_SHA1_Init(&ctx_h);
CC_SHA1_Update(&ctx_h, fat_y, wid);
CC_SHA1_Final(dig_y, &ctx_h);
#else
SHA_CTX ctx_h;
SHA1_Init(&ctx_h);
SHA1_Update(&ctx_h, fat_y, wid);
SHA1_Final(dig_y, &ctx_h);
#endif
u3a_free(fat_y);
u3z(dat);
return u3kc_rev(3, 20, u3i_bytes(20, dig_y));
urcrypt_sha1(dat_y, len_w, out_y);
u3a_free(dat_y);
return u3i_bytes(20, out_y);
}
}
@ -48,12 +30,11 @@
if ( (c3n == u3r_mean(cor, u3x_sam_2, &wid, u3x_sam_3, &dat, 0)) ||
(c3n == u3ud(wid)) ||
(c3n == u3a_is_cat(wid)) ||
(c3n == u3ud(dat)) )
{
return u3m_bail(c3__exit);
}
else {
return u3qe_sha1(wid, dat);
return _cqe_sha1(wid, dat);
}
}

View File

@ -2,119 +2,69 @@
**
*/
#include "all.h"
#if defined(U3_OS_osx)
#include <CommonCrypto/CommonDigest.h>
#else
#include <openssl/sha.h>
#endif
#include <urcrypt.h>
/* functions
*/
u3_noun
u3qe_shay(u3_atom a,
u3_atom b)
static u3_atom
_cqe_shay(u3_atom wid,
u3_atom dat)
{
c3_assert(_(u3a_is_cat(a)));
c3_y* fat_y = u3a_malloc(a + 1);
u3r_bytes(0, a, fat_y, b);
{
c3_y dig_y[32];
#if defined(U3_OS_osx)
CC_SHA256_CTX ctx_h;
CC_SHA256_Init(&ctx_h);
CC_SHA256_Update(&ctx_h, fat_y, a);
CC_SHA256_Final(dig_y, &ctx_h);
#else
SHA256_CTX ctx_h;
SHA256_Init(&ctx_h);
SHA256_Update(&ctx_h, fat_y, a);
SHA256_Final(dig_y, &ctx_h);
#endif
u3a_free(fat_y);
return u3i_bytes(32, dig_y);
c3_w len_w;
if ( !u3r_word_fit(&len_w, wid) ) {
return u3m_bail(c3__fail);
}
else {
c3_y out_y[32];
c3_y* dat_y = u3r_bytes_alloc(0, len_w, dat);
urcrypt_shay(dat_y, len_w, out_y);
u3a_free(dat_y);
return u3i_bytes(32, out_y);
}
}
// u3_noun
// u3qe_shax(
// u3_atom a)
// {
// c3_w met_w = u3r_met(3, a);
// return u3qe_shay(met_w, a);
// }
// XX preformance
u3_noun
u3qe_shax(u3_atom a)
static u3_atom
_cqe_shax(u3_atom a)
{
c3_w met_w = u3r_met(3, a);
c3_y* fat_y = u3a_malloc(met_w + 1);
c3_w len_w;
c3_y out_y[32];
c3_y* dat_y = u3r_bytes_all(&len_w, a);
urcrypt_shay(dat_y, len_w, out_y);
u3a_free(dat_y);
return u3i_bytes(32, out_y);
}
u3r_bytes(0, met_w, fat_y, a);
{
c3_y dig_y[32];
#if defined(U3_OS_osx)
CC_SHA256_CTX ctx_h;
CC_SHA256_Init(&ctx_h);
CC_SHA256_Update(&ctx_h, fat_y, met_w);
CC_SHA256_Final(dig_y, &ctx_h);
#else
SHA256_CTX ctx_h;
SHA256_Init(&ctx_h);
SHA256_Update(&ctx_h, fat_y, met_w);
SHA256_Final(dig_y, &ctx_h);
#endif
u3a_free(fat_y);
return u3i_bytes(32, dig_y);
static u3_atom
_cqe_shal(u3_atom wid,
u3_atom dat)
{
c3_w len_w;
if ( !u3r_word_fit(&len_w, wid) ) {
return u3m_bail(c3__fail);
}
else {
c3_y out_y[64];
c3_y* dat_y = u3r_bytes_alloc(0, len_w, dat);
urcrypt_shal(dat_y, len_w, out_y);
u3a_free(dat_y);
return u3i_bytes(64, out_y);
}
}
// XX end preformance
u3_noun
u3qe_shal(u3_atom a,
u3_atom b)
{
c3_assert(_(u3a_is_cat(a)));
c3_y* fat_y = u3a_malloc(a + 1);
u3r_bytes(0, a, fat_y, b);
{
c3_y dig_y[64];
#if defined(U3_OS_osx)
CC_SHA512_CTX ctx_h;
CC_SHA512_Init(&ctx_h);
CC_SHA512_Update(&ctx_h, fat_y, a);
CC_SHA512_Final(dig_y, &ctx_h);
#else
SHA512_CTX ctx_h;
SHA512_Init(&ctx_h);
SHA512_Update(&ctx_h, fat_y, a);
SHA512_Final(dig_y, &ctx_h);
#endif
u3a_free(fat_y);
return u3i_bytes(64, dig_y);
}
}
u3_noun
u3qe_shas(u3_atom sal,
static u3_atom
_cqe_shas(u3_atom sal,
u3_atom ruz)
{
u3_noun one = u3qe_shax(ruz);
u3_noun two = u3qc_mix(sal, one);
u3_noun tri = u3qe_shax(two);
c3_w sal_w, ruz_w;
c3_y *sal_y, *ruz_y, out_y[32];
u3z(one); u3z(two); return tri;
sal_y = u3r_bytes_all(&sal_w, sal);
ruz_y = u3r_bytes_all(&ruz_w, ruz);
urcrypt_shas(sal_y, sal_w, ruz_y, ruz_w, out_y);
u3a_free(sal_y);
u3a_free(ruz_y);
return u3i_bytes(32, out_y);
}
u3_noun
@ -127,7 +77,7 @@ u3_noun
{
return u3m_bail(c3__exit);
} else {
return u3qe_shax(a);
return _cqe_shax(a);
}
}
@ -136,20 +86,14 @@ u3_noun
{
u3_noun a, b;
// static int few = 0;
// if(few == 0) printf("foo\r\n");
// few++; few %= 1000;
if ( (u3_none == (a = u3r_at(u3x_sam_2, cor))) ||
(u3_none == (b = u3r_at(u3x_sam_3, cor))) ||
(c3n == u3ud(a)) ||
(c3n == u3a_is_cat(a)) ||
(c3n == u3ud(b)) )
{
return u3m_bail(c3__exit);
} else {
return u3qe_shay(a, b);
return _cqe_shay(a, b);
}
}
@ -161,12 +105,11 @@ u3_noun
if ( (u3_none == (a = u3r_at(u3x_sam_2, cor))) ||
(u3_none == (b = u3r_at(u3x_sam_3, cor))) ||
(c3n == u3ud(a)) ||
(c3n == u3a_is_cat(a)) ||
(c3n == u3ud(b)) )
{
return u3m_bail(c3__exit);
} else {
return u3qe_shal(a, b);
return _cqe_shal(a, b);
}
}
@ -182,7 +125,7 @@ u3_noun
{
return u3m_bail(c3__exit);
} else {
return u3qe_shas(sal, ruz);
return _cqe_shas(sal, ruz);
}
}
@ -199,7 +142,7 @@ u3_noun
while ( 0 != b ) {
u3_noun x = u3qc_mix(a, c);
u3_noun y = u3qc_mix(b, x);
u3_noun d = u3qe_shas(c3_s4('o','g','-','b'), y);
u3_noun d = _cqe_shas(c3_s4('o','g','-','b'), y);
u3_noun m;
u3z(x); u3z(y);
@ -226,7 +169,7 @@ u3_noun
u3_atom b)
{
u3_noun x = u3qc_mix(b, a);
u3_noun c = u3qe_shas(c3_s4('o','g','-','a'), x);
u3_noun c = _cqe_shas(c3_s4('o','g','-','a'), x);
u3_noun l = _og_list(a, b, c);
u3_noun r = u3qc_can(0, l);

View File

@ -376,17 +376,29 @@ static c3_c* _140_hex_argon_ha[] = {
0
};
static c3_c* _140_hex_scr_pbk_ha[] = { 0 };
static u3j_harm _140_hex_scr_pbk_a[] = {{".2", u3wes_pbk, c3y}, {}};
static c3_c* _140_hex_scr_pbl_ha[] = { 0 };
static u3j_harm _140_hex_scr_pbl_a[] = {{".2", u3wes_pbl, c3y}, {}};
static c3_c* _140_hex_scr_hsh_ha[] = { 0 };
static u3j_harm _140_hex_scr_hsh_a[] = {{".2", u3wes_hsh, c3y}, {}};
static c3_c* _140_hex_scr_hsl_ha[] = { 0 };
static u3j_harm _140_hex_scr_hsl_a[] = {{".2", u3wes_hsl, c3y}, {}};
static c3_c* _140_hex_scr_ha[] = { 0 };
static u3j_core _140_hex_scr_d[] =
{ { "pbk", 7, _140_hex_scr_pbk_a, 0, _140_hex_scr_pbk_ha },
{ "pbl", 7, _140_hex_scr_pbl_a, 0, _140_hex_scr_pbl_ha },
{ "hsh", 7, _140_hex_scr_hsh_a, 0, _140_hex_scr_hsh_ha },
{ "hsl", 7, _140_hex_scr_hsl_a, 0, _140_hex_scr_hsl_ha },
{}
};
static c3_c* _140_hex_secp_secp256k1_make_ha[] = { 0 };
static u3j_harm _140_hex_secp_secp256k1_make_a[] = {{".2", u3we_make, c3y}, {}};
static c3_c* _140_hex_secp_secp256k1_sign_ha[] = {
"3e75b3452b74776488d5eec75a91211700d9f360a4e06dd779600d5128d9c600",
0
};
static c3_c* _140_hex_secp_secp256k1_sign_ha[] = { 0 };
static u3j_harm _140_hex_secp_secp256k1_sign_a[] = {{".2", u3we_sign, c3y}, {}};
static c3_c* _140_hex_secp_secp256k1_reco_ha[] = {
"449f3aa878b61962c3048e167c23ba54a0736d3aa1ab7762bd54016fbba136ee",
0
};
static c3_c* _140_hex_secp_secp256k1_reco_ha[] = { 0 };
static u3j_harm _140_hex_secp_secp256k1_reco_a[] = {{".2", u3we_reco, c3y}, {}};
static c3_c* _140_hex_secp_secp256k1_ha[] = {
@ -451,7 +463,8 @@ static u3j_core _140_hex_d[] =
{ "argon", 31, 0, _140_hex_argon_d, _140_hex_argon_ha },
{ "blake", 31, 0, _140_hex_blake_d, _140_hex_blake_ha },
{ "ripemd", 31, 0, _140_hex_ripe_d, _140_hex_ripe_ha },
{ "secp", 6, 0, _140_hex_secp_d, _140_hex_secp_ha },
{ "scr", 31, 0, _140_hex_scr_d, _140_hex_scr_ha },
{ "secp", 6, 0, _140_hex_secp_d, _140_hex_secp_ha },
{ "mimes", 31, 0, _140_hex_mimes_d, _140_hex_mimes_ha },
{}
};

View File

@ -1,12 +1,11 @@
/* g/e.c
**
*/
#include "all.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "all.h"
#ifdef U3_SNAPSHOT_VALIDATION
/* Image check.
*/
@ -815,8 +814,8 @@ u3e_save(void)
_ce_image_sync(&u3P.nor_u);
_ce_image_sync(&u3P.sou_u);
_ce_patch_delete();
_ce_patch_free(pat_u);
_ce_patch_delete();
}
/* u3e_live(): start the checkpointing system.
@ -853,8 +852,8 @@ u3e_live(c3_o nuu_o, c3_c* dir_c)
_ce_patch_apply(pat_u);
_ce_image_sync(&u3P.nor_u);
_ce_image_sync(&u3P.sou_u);
_ce_patch_delete();
_ce_patch_free(pat_u);
_ce_patch_delete();
}
/* Write image files to memory; reinstate protection.

View File

@ -2,12 +2,7 @@
**
*/
#include "all.h"
#if defined(U3_OS_osx)
#include <CommonCrypto/CommonDigest.h>
#else
#include <openssl/sha.h>
#endif
#include <urcrypt.h>
/** Data structures.
**/
@ -128,20 +123,7 @@ _cj_bash(u3_noun bat)
//
c3_y* fat_y = sab_u.buf_y;
c3_y dig_y[32];
#if defined(U3_OS_osx)
CC_SHA256_CTX ctx_h;
CC_SHA256_Init(&ctx_h);
CC_SHA256_Update(&ctx_h, fat_y, met_w);
CC_SHA256_Final(dig_y, &ctx_h);
#else
SHA256_CTX ctx_h;
SHA256_Init(&ctx_h);
SHA256_Update(&ctx_h, fat_y, met_w);
SHA256_Final(dig_y, &ctx_h);
#endif
urcrypt_shay(fat_y, met_w, dig_y);
pro = u3i_bytes(32, dig_y);
u3h_put(u3R->jed.bas_p, bat, u3k(pro));

View File

@ -28,3 +28,12 @@ u3l_log(const char* format, ...)
va_end(myargs);
}
u3_weak
u3l_punt(const char* name, u3_weak pro)
{
if ( u3_none == pro ) {
u3l_log("%s-punt\r\n", name);
}
return pro;
}

View File

@ -1,16 +1,15 @@
/* n/m.c
**
*/
#include "all.h"
#include "rsignal.h"
#include "vere/vere.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <ctype.h>
#include <sigsegv.h>
#include <curl/curl.h>
#include <openssl/crypto.h>
#include "all.h"
#include "vere/vere.h"
#include <urcrypt.h>
// XX stack-overflow recovery should be gated by -a
//
@ -75,7 +74,17 @@
u3_noun arg);
static sigjmp_buf u3_Signal;
// u3m_signal uses restricted functionality signals for compatibility reasons:
// some platforms may not provide true POSIX asynchronous signals and their
// compat layer will then implement this restricted functionality subset.
// u3m_signal never needs to interrupt I/O operations, its signal handlers
// do not manipulate signals, do not modify shared state, and always either
// return or longjmp.
//
static rsignal_jmpbuf u3_Signal;
#if !defined(U3_OS_mingw)
#include <sigsegv.h>
#ifndef SIGSTKSZ
# define SIGSTKSZ 16384
@ -83,6 +92,7 @@ static sigjmp_buf u3_Signal;
#ifndef NO_OVERFLOW
static uint8_t Sigstk[SIGSTKSZ];
#endif
#endif
#if 0
/* _cm_punt(): crudely print trace.
@ -129,17 +139,25 @@ static void _cm_overflow(void *arg1, void *arg2, void *arg3)
static void
_cm_signal_handle(c3_l sig_l)
{
#ifndef U3_OS_mingw
if ( c3__over == sig_l ) {
#ifndef NO_OVERFLOW
sigsegv_leave_handler(_cm_overflow, NULL, NULL, NULL);
}
else {
#endif
} else
#endif
{
u3m_signal(sig_l);
}
}
#ifndef NO_OVERFLOW
static void
#ifndef U3_OS_mingw
_cm_signal_handle_over(int emergency, stackoverflow_context_t scp)
#else
_cm_signal_handle_over(int x)
#endif
{
_cm_signal_handle(c3__over);
}
@ -330,10 +348,14 @@ _cm_signal_deep(c3_w mil_w)
}
#ifndef NO_OVERFLOW
#ifndef U3_OS_mingw
stackoverflow_install_handler(_cm_signal_handle_over, Sigstk, SIGSTKSZ);
#else
rsignal_install_handler(SIGSTK, _cm_signal_handle_over);
#endif
signal(SIGINT, _cm_signal_handle_intr);
signal(SIGTERM, _cm_signal_handle_term);
#endif
rsignal_install_handler(SIGINT, _cm_signal_handle_intr);
rsignal_install_handler(SIGTERM, _cm_signal_handle_term);
// Provide a little emergency memory, for use in case things
// go utterly haywire.
@ -349,11 +371,11 @@ _cm_signal_deep(c3_w mil_w)
itm_u.it_value.tv_sec = (mil_w / 1000);
itm_u.it_value.tv_usec = 1000 * (mil_w % 1000);
if ( setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) {
if ( rsignal_setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) {
u3l_log("loom: set timer failed %s", strerror(errno));
}
else {
signal(SIGVTALRM, _cm_signal_handle_alrm);
rsignal_install_handler(SIGVTALRM, _cm_signal_handle_alrm);
}
}
@ -365,12 +387,16 @@ _cm_signal_deep(c3_w mil_w)
static void
_cm_signal_done()
{
signal(SIGINT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
signal(SIGVTALRM, SIG_IGN);
rsignal_deinstall_handler(SIGINT);
rsignal_deinstall_handler(SIGTERM);
rsignal_deinstall_handler(SIGVTALRM);
#ifndef NO_OVERFLOW
#ifndef U3_OS_mingw
stackoverflow_deinstall_handler();
#else
rsignal_deinstall_handler(SIGSTK);
#endif
#endif
{
struct itimerval itm_u;
@ -378,7 +404,7 @@ _cm_signal_done()
timerclear(&itm_u.it_interval);
timerclear(&itm_u.it_value);
if ( setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) {
if ( rsignal_setitimer(ITIMER_VIRTUAL, &itm_u, 0) ) {
u3l_log("loom: clear timer failed %s", strerror(errno));
}
}
@ -397,7 +423,7 @@ _cm_signal_done()
void
u3m_signal(u3_noun sig_l)
{
siglongjmp(u3_Signal, sig_l);
rsignal_longjmp(u3_Signal, sig_l);
}
/* u3m_file(): load file, as atom, or bail.
@ -959,7 +985,7 @@ u3m_soft_top(c3_w mil_w, // timer ms
*/
_cm_signal_deep(mil_w);
if ( 0 != (sig_l = sigsetjmp(u3_Signal, 1)) ) {
if ( 0 != (sig_l = rsignal_setjmp(u3_Signal)) ) {
// reinitialize trace state
//
u3t_init();
@ -1559,6 +1585,10 @@ u3m_wall(u3_noun wol)
static void
_cm_limits(void)
{
# ifdef U3_OS_mingw
// Windows doesn't have rlimits. Default maximum thread
// stack size is set in the executable file header.
# else
struct rlimit rlm;
// Moar stack.
@ -1606,6 +1636,7 @@ _cm_limits(void)
}
}
# endif
# endif
}
/* _cm_signals(): set up interrupts, etc.
@ -1613,13 +1644,23 @@ _cm_limits(void)
static void
_cm_signals(void)
{
# if defined(U3_OS_mingw)
// vere using libsigsegv on MingW is very slow, because libsigsegv
// works by installing a top-level SEH unhandled exception filter.
// The top-level filter runs only after Windows walks the whole stack,
// looking up registered exception filters for every stack frame, and
// finds no filter to handle the exception.
// Instead of libsigsegv, all vere functions register a SEH exception
// filter (see compat/mingw/seh_handler.c) that handles both memory
// access and stack overflow exceptions. It calls u3e_fault directly.
# else
if ( 0 != sigsegv_install_handler(u3e_fault) ) {
u3l_log("boot: sigsegv install failed");
exit(1);
}
// signal(SIGINT, _loom_stop);
# endif
# if defined(U3_OS_PROF)
// Block SIGPROF, so that if/when we reactivate it on the
// main thread for profiling, we won't get hits in parallel
// on other threads.
@ -1634,6 +1675,24 @@ _cm_signals(void)
exit(1);
}
}
# endif
}
extern void u3je_secp_init(void);
extern void u3je_secp_stop(void);
static void
_cm_crypto()
{
/* Initialize OpenSSL with loom allocation functions. */
if ( 0 == CRYPTO_set_mem_functions(&u3a_malloc_ssl,
&u3a_realloc_ssl,
&u3a_free_ssl) ) {
u3l_log("%s\r\n", "openssl initialization failed");
abort();
}
u3je_secp_init();
}
/* u3m_init(): start the environment.
@ -1643,6 +1702,7 @@ u3m_init(void)
{
_cm_limits();
_cm_signals();
_cm_crypto();
/* Make sure GMP uses our malloc.
*/
@ -1681,6 +1741,13 @@ u3m_init(void)
}
}
/* u3m_stop(): graceful shutdown cleanup. */
void
u3m_stop()
{
u3je_secp_stop();
}
/* u3m_boot(): start the u3 system. return next event, starting from 1.
*/
c3_d
@ -1692,11 +1759,6 @@ u3m_boot(c3_c* dir_c)
*/
u3m_init();
/* In the worker, set the openssl memory allocation functions to always
** work on the loom.
*/
CRYPTO_set_mem_functions(u3a_malloc_ssl, u3a_realloc_ssl, u3a_free_ssl);
/* Activate the storage system.
*/
nuu_o = u3e_live(c3n, dir_c);

View File

@ -1188,6 +1188,49 @@ u3r_bytes(c3_w a_w,
}
}
/* u3r_bytes_fit():
**
** Copy (len_w) bytes of (a) into (buf_y) if it fits, returning overage
*/
c3_w
u3r_bytes_fit(c3_w len_w, c3_y *buf_y, u3_atom a)
{
c3_w met_w = u3r_met(3, a);
if ( met_w <= len_w ) {
u3r_bytes(0, len_w, buf_y, a);
return 0;
}
else {
return len_w - met_w;
}
}
/* u3r_bytes_alloc():
**
** Copy (len_w) bytes starting at (a_w) from (b) into a fresh allocation.
*/
c3_y*
u3r_bytes_alloc(c3_w a_w,
c3_w len_w,
u3_atom b)
{
c3_y* b_y = u3a_malloc(len_w);
u3r_bytes(a_w, a_w + len_w, b_y, b);
return b_y;
}
/* u3r_bytes_all():
**
** Allocate and return a new byte array with all the bytes of (a),
** storing the length in (len_w).
*/
c3_y*
u3r_bytes_all(c3_w* len_w, u3_atom a)
{
c3_w met_w = *len_w = u3r_met(3, a);
return u3r_bytes_alloc(0, met_w, a);
}
/* u3r_mp():
**
** Copy (b) into (a_mp).
@ -1274,6 +1317,22 @@ u3r_word(c3_w a_w,
}
}
/* u3r_word_fit():
**
** Fill (out_w) with (a) if it fits, returning success.
*/
c3_t
u3r_word_fit(c3_w *out_w, u3_atom a)
{
if ( u3r_met(5, a) > 1 ) {
return 0;
}
else {
*out_w = u3r_word(0, a);
return 1;
}
}
/* u3r_chub():
**
** Return double-word (a_w) of (b).

View File

@ -2,11 +2,10 @@
**
*/
#include <errno.h>
#include <fcntl.h>
#include "all.h"
#include "ur/ur.h"
#include <errno.h>
#include <fcntl.h>
/* _cs_jam_buf: struct for tracking the fibonacci-allocated jam of a noun
*/

Some files were not shown because too many files have changed in this diff Show More