Merge 1e70a1be2a into release/next-userspace

This commit is contained in:
janeway-bot 2021-10-06 00:47:10 +04:00 committed by GitHub
commit ccc8f3b3d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
308 changed files with 107111 additions and 4173 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
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

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0af91e5c51359719aaa943f37a1e953989c786412616b18fbaa0addb2cf0740
size 10272514
oid sha256:9a56f675d2a6c5dafa92a9e2d55040d994f3d3d27a1ed827bd87d1158b1e69d0
size 3749183

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:23d8235b19a3404e0bfbed54aa56a018255beb1f33457e37f521bc0763b4d0eb
size 6245506
oid sha256:f50aee74e4f3dd6685d36520bbc924ab94d3d47a7bc86e649882e58ab069e7dd
size 991930

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5159d6516c0b3d12b3c7f39f434ab769e99392dc94aa43add32bb2a91455c73a
size 6121099
oid sha256:8229a2dc1908d4bb322a3300e68f79e79e3352507b8ef68d40e802bcbdb19550
size 5437325

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4427b6e4a925502fe2e63087e190dfe0c77f75644dfe31a306de64d269b128f2
size 14661883
oid sha256:618a74c199baa6d52ae9eea8c40f4f5b15e95b441e743d0f989275321e5b0703
size 7299622

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8baf284490d8c7cfbad2481f1ef0d17a6bb05200bc179b78c1a8718461756a06
size 12941119
oid sha256:d8d387759fe4830fcc09a1fc7b80d52e61327d518f7eb0713697aec1819eacf7
size 5608210

View File

@ -86,19 +86,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 { };
@ -118,6 +110,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

@ -1587,14 +1587,15 @@
:::: ++keccak:crypto :: (2b7) keccak family
:: ::::
++ keccak
~% %kecc ..part ~
|%
::
:: keccak
::
++ keccak-224 |=(a=octs (keccak 1.152 448 224 a))
++ keccak-256 |=(a=octs (keccak 1.088 512 256 a))
++ keccak-384 |=(a=octs (keccak 832 768 384 a))
++ keccak-512 |=(a=octs (keccak 576 1.024 512 a))
++ keccak-224 ~/ %k224 |=(a=octs (keccak 1.152 448 224 a))
++ keccak-256 ~/ %k256 |=(a=octs (keccak 1.088 512 256 a))
++ keccak-384 ~/ %k384 |=(a=octs (keccak 832 768 384 a))
++ keccak-512 ~/ %k512 |=(a=octs (keccak 576 1.024 512 a))
::
++ keccak (cury (cury hash keccak-f) padding-keccak)
::

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

@ -85,7 +85,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{..} =
@ -117,6 +117,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 }
@ -145,6 +175,7 @@ data Dawn = MkDawn
deriveNoun ''Dnses
deriveNoun ''EthPoint
deriveNoun ''Seed
deriveNoun ''Germ
deriveNoun ''Dawn
@ -239,6 +270,16 @@ data BoatEv
deriveNoun ''BoatEv
-- Jael Events -----------------------------------------------------------------
data JaelEv
= JaelEvRekey () (Life, Ring)
| JaelEvCrud Path Noun
deriving (Eq, Show)
deriveNoun ''JaelEv
-- Timer Events ----------------------------------------------------------------
data BehnEv
@ -313,6 +354,7 @@ data BlipEv
| BlipEvBoat BoatEv
| BlipEvHttpClient HttpClientEv
| BlipEvHttpServer HttpServerEv
| BlipEvJael JaelEv
| BlipEvNewt NewtEv
| BlipEvSync SyncEv
| BlipEvTerm TermEv
@ -335,6 +377,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)
@ -362,6 +405,7 @@ getSpinnerNameForEvent = \case
BlipEvBoat _ -> Just "boat"
BlipEvHttpClient _ -> Just "iris"
BlipEvHttpServer _ -> Just "eyre"
BlipEvJael _ -> Just "jael"
BlipEvNewt _ -> Just "newt"
BlipEvSync _ -> Just "clay"
BlipEvTerm t | isRet t -> 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
bootFromFeed 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
bootFromFeed 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
bootFromFeed :: Pill -> Feed -> RIO HostEnv ()
bootFromFeed 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) = do
case clanFromShip ship of
Ob.Comet -> pure validateComet
Ob.Moon -> pure validateMoon
_ -> validateRest
where
cometFromPass = cometFingerprint $ ringToPass ring
validateComet
-- A comet address is the fingerprint of the keypair
| (ship /= cometFromPass) =
Left ("comet name doesn't match fingerprint " <>
show ship <> " vs " <>
show cometFromPass)
| (life /= 1) =
Left "comet can never be re-keyed"
| otherwise =
Right (shipSein ship)
validateRest = do
putStrLn ("boot: retrieving " <> renderShip ship <> "'s public keys")
validateMoon =
-- 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.
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,5 +1,5 @@
name: urbit-king
version: 1.5
version: 1.6
license: MIT
license-file: LICENSE
data-files:

View File

@ -1,7 +1,7 @@
{-|
Template Haskell Code to Generate FromNoun and ToNoun Instances
-}
module Urbit.Noun.TH (deriveNoun, deriveToNoun, deriveFromNoun) where
module Urbit.Noun.TH (deriveNoun, deriveToNoun, deriveFromNoun, deriveToNounFunc, deriveFromNounFunc) where
import ClassyPrelude hiding (fromList)
import Control.Monad.Fail (fail)
@ -83,13 +83,9 @@ deriveNoun n = (<>) <$> deriveToNoun n <*> deriveFromNoun n
deriveToNoun :: Name -> Q [Dec]
deriveToNoun tyName = do
(params, shape) <- typeShape tyName
let exp = case shape of Vod -> vodToNoun
Tup con -> tupToNoun con
-- Enu cons -> enumToAtom cons
Sum atoms cells -> sumToNoun atoms cells
(params, _) <- typeShape tyName
exp <- deriveToNounFunc tyName
params <- pure $ zip ['a' ..] params <&> \(n,_) -> mkName (singleton n)
let ty = foldl' (\acc v -> AppT acc (VarT v)) (ConT tyName) params
@ -101,6 +97,15 @@ deriveToNoun tyName = do
pure [InstanceD overlap ctx inst [ValD (VarP 'toNoun) body []]]
deriveToNounFunc :: Name -> Q Exp
deriveToNounFunc tyName = do
(_, shape) <- typeShape tyName
pure case shape of
Vod -> vodToNoun
Tup con -> tupToNoun con
-- Enu cons -> enumToAtom cons
Sum atoms cells -> sumToNoun atoms cells
--------------------------------------------------------------------------------
addErrTag :: String -> Exp -> Exp
@ -111,13 +116,9 @@ addErrTag tag exp =
deriveFromNoun :: Name -> Q [Dec]
deriveFromNoun tyName = do
(params, shape) <- typeShape tyName
let exp = case shape of Vod -> vodFromNoun
Tup con -> tupFromNoun con
-- Enu cons -> enumFromAtom cons
Sum atoms cells -> sumFromNoun atoms cells
(params, _) <- typeShape tyName
exp <- deriveFromNounFunc tyName
params <- pure $ zip ['a' ..] params <&> \(n,_) -> mkName (singleton n)
let ty = foldl' (\acc v -> AppT acc (VarT v)) (ConT tyName) params
@ -129,6 +130,15 @@ deriveFromNoun tyName = do
pure [InstanceD overlap ctx inst [ValD (VarP 'parseNoun) body []]]
deriveFromNounFunc :: Name -> Q Exp
deriveFromNounFunc tyName = do
(_, shape) <- typeShape tyName
pure case shape of
Vod -> vodFromNoun
Tup con -> tupFromNoun con
-- Enu cons -> enumFromAtom cons
Sum atoms cells -> sumFromNoun atoms cells
sumFromNoun :: [(String, Name)] -> [(String, ConInfo)] -> Exp
sumFromNoun [] cl = taggedFromNoun cl
sumFromNoun at [] = enumFromAtom at

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) -static -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.pip_u, 0)) &&
0 == (e = uv_pipe_init(lup_u, &uty_u->pop_u.pip_u, 0)) &&
0 == (e = uv_pipe_open(&uty_u->pin_u.pip_u, 0)) &&
0 == (e = uv_pipe_open(&uty_u->pop_u.pip_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,38 @@
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
@@ -1054,7 +1054,6 @@ static DWORD WINAPI uv_pipe_writefile_thread_proc(void* parameter) {
assert(req != NULL);
assert(req->type == UV_WRITE);
assert(handle->type == UV_NAMED_PIPE);
- assert(req->write_buffer.base);
result = WriteFile(handle->handle,
req->write_buffer.base,
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 "$narinfo"|while IFS=: read k v; do if [ "$k" == "URL" ]; then echo $v; fi; done)"
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="$(IFS=:;echo "${pdirs[*]}"):${PKG_CONFIG_PATH-}"

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,189 @@
/* 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.pip_u, 0);
uv_pipe_init(lup_u, &uty_u->pop_u.pip_u, 0);
uv_pipe_open(&uty_u->pin_u.pip_u, 0);
uv_pipe_open(&uty_u->pop_u.pip_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.
//
{
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

141
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,41 @@ 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
[ -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 +105,58 @@ esac
# TODO Determine if the target cpu is little or big endian.
case $(tr A-Z a-z <<< $os) in
*mingw*)
# mingw builds are static-only
#
opt_static=1
# 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 +167,39 @@ 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
CFLAGS="${CFLAGS-} -static"
# XX can't set -static here due libuv's -ldl on MacOS
#
# LDFLAGS="${LDFLAGS-} -static"
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
CFLAGS := $CFLAGS -funsigned-char -ffast-math -fcommon -std=gnu99
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

Binary file not shown.

View File

@ -32,7 +32,7 @@
if (!(x)) { \
fflush(stderr); \
fprintf(stderr, "\rAssertion '%s' " \
"failed in %s:%d\n", \
"failed in %s:%d\r\n", \
#x, __FILE__, __LINE__); \
c3_cooked(); \
assert(x); \

View File

@ -1237,6 +1237,7 @@
# define c3__werp c3_s4('w','e','r','p')
# define c3__west c3_s4('w','e','s','t')
# define c3__what c3_s4('w','h','a','t')
# define c3__whey c3_s4('w','h','e','y')
# define c3__whom c3_s4('w','h','o','m')
# define c3__wing c3_s4('w','i','n','g')
# define c3__wild c3_s4('w','i','l','d')

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
@ -85,6 +104,8 @@
# endif
/** Address space layout.
***
*** NB: 2^29 words == 2GB
**/
# if defined(U3_OS_linux)
# ifdef __LP64__
@ -96,21 +117,24 @@
# else
# define U3_OS_LoomBase 0x36000000
# endif
# define U3_OS_LoomBits 29 // ie, 2^29 words == 2GB
# define U3_OS_LoomBits 29
# elif defined(U3_OS_mingw)
# define U3_OS_LoomBase 0x28000000000
# define U3_OS_LoomBits 29
# elif defined(U3_OS_osx)
# ifdef __LP64__
# define U3_OS_LoomBase 0x200000000
# define U3_OS_LoomBase 0x28000000000
# else
# define U3_OS_LoomBase 0x4000000
# endif
# define U3_OS_LoomBits 29 // ie, 2^29 words == 2GB
# define U3_OS_LoomBits 29
# elif defined(U3_OS_bsd)
# ifdef __LP64__
# define U3_OS_LoomBase 0x200000000
# else
# define U3_OS_LoomBase 0x4000000
# endif
# define U3_OS_LoomBits 29 // ie, 2^29 words == 2GB
# define U3_OS_LoomBits 29
# else
# error "port: LoomBase"
# endif
@ -153,7 +177,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 +191,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 +206,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 +214,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 +224,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

@ -192,6 +192,10 @@
u3_noun u3we_hmac(u3_noun);
u3_noun u3we_kecc224(u3_noun);
u3_noun u3we_kecc256(u3_noun);
u3_noun u3we_kecc384(u3_noun);
u3_noun u3we_kecc512(u3_noun);
u3_noun u3we_argon2(u3_noun);

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

@ -45,8 +45,8 @@
c3_w use_w; // number of lines currently filled
struct {
c3_w mug_w; // current hash
c3_w inx_w; // index into current hash bucket iff buc_o
c3_o buc_o; // yes if in middle of hash bucket
c3_w inx_w; // index into current hash bucket
c3_o buc_o; // XX remove
} arm_u; // clock arm
u3h_slot sot_w[64]; // slots
} u3h_root;

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

@ -40,7 +40,6 @@ typedef uint32_t ur_mug;
#define ur_pail_max 10
typedef struct ur_pail32_s {
uint8_t fill;
ur_nref refs[ur_pail_max];
uint32_t vals[ur_pail_max];
} ur_pail32_t;
@ -48,11 +47,11 @@ typedef struct ur_pail32_s {
typedef struct ur_dict32_s {
uint64_t prev;
uint64_t size;
uint8_t *fills;
ur_pail32_t *buckets;
} ur_dict32_t;
typedef struct ur_pail64_s {
uint8_t fill;
ur_nref refs[ur_pail_max];
uint64_t vals[ur_pail_max];
} ur_pail64_t;
@ -60,17 +59,18 @@ typedef struct ur_pail64_s {
typedef struct ur_dict64_s {
uint64_t prev;
uint64_t size;
uint8_t *fills;
ur_pail64_t *buckets;
} ur_dict64_t;
typedef struct ur_pail_s {
uint8_t fill;
ur_nref refs[ur_pail_max];
} ur_pail_t;
typedef struct ur_dict_s {
uint64_t prev;
uint64_t size;
uint8_t *fills;
ur_pail_t *buckets;
} ur_dict_t;

View File

@ -222,22 +222,39 @@
};
#endif
/* u3_utty: unix tty.
*/
struct _u3_utty;
/* u3_ustm: uv stream.
*/
typedef union _u3_ustm {
uv_pipe_t pip_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; // terminfo strings
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;
@ -301,6 +318,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
@ -469,6 +489,7 @@
time_t wen_t; // process creation time
u3_mojo inn_u; // client's stdin
u3_moat out_u; // client's stdout
uv_pipe_t err_u; // client's stderr
c3_w wag_w; // config flags
c3_c* bin_c; // binary path
c3_c* pax_c; // directory
@ -641,7 +662,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;
@ -716,7 +738,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
@ -1103,6 +1125,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.
**/
@ -1289,7 +1316,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.
*/
@ -1334,7 +1362,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
*/
@ -1371,6 +1399,15 @@
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
u3_write_fd(c3_i fid_i, const void* buf_v, size_t len_i);
c3_w
u3_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);

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

@ -11,7 +11,7 @@
u3_noun b)
{
if ( !_(u3a_is_cat(a)) || (a >= 32) ) {
return u3m_bail(c3__exit);
return u3m_bail(c3__fail);
}
else {
c3_g a_g = a;

View File

@ -98,7 +98,7 @@ _block_rep(u3_atom a,
u3_noun b)
{
if ( !_(u3a_is_cat(a)) || (a >= 32) ) {
return u3m_bail(c3__exit);
return u3m_bail(c3__fail);
}
else {
c3_g a_g = a;
@ -170,7 +170,7 @@ u3qc_rep(u3_atom a,
}
u3l_log("rep: stub\r\n");
return u3m_bail(c3__fail);
return u3_none;
}
u3_noun

View File

@ -160,7 +160,7 @@ u3qc_rip(u3_atom a,
}
u3l_log("rip: stub\r\n");
return u3m_bail(c3__fail);
return u3_none;
}
u3_noun

View File

@ -5,6 +5,9 @@
/* internal functions
*/
/* RETAIN
*/
static u3_noun
_b_dif_join(u3_noun d,
u3_noun e)
@ -27,14 +30,14 @@ _b_dif_join(u3_noun d,
return u3nt(u3k(n_d),
u3k(l_d),
_b_dif_join(u3k(r_d), u3k(e)));
_b_dif_join(r_d, e));
}
else {
u3_noun l_e, r_e;
u3x_cell(lr_e, &l_e, &r_e);
return u3nt(u3k(n_e),
_b_dif_join(u3k(d), u3k(l_e)),
_b_dif_join(d, l_e),
u3k(r_e));
}
}
@ -69,6 +72,11 @@ u3qdb_dif(u3_noun a,
u3_noun e = u3qdb_dif(r_c, r_b);
u3z(c);
return _b_dif_join(d, e);
u3_noun pro = _b_dif_join(d, e);
u3z(d);
u3z(e);
return pro;
}
}

View File

@ -5,6 +5,9 @@
/* internal functions
*/
/* RETAIN
*/
static u3_noun
_i_dif_join(u3_noun d,
u3_noun e)
@ -27,14 +30,14 @@ _i_dif_join(u3_noun d,
return u3nt(u3k(n_d),
u3k(l_d),
_i_dif_join(u3k(r_d), u3k(e)));
_i_dif_join(r_d, e));
}
else {
u3_noun l_e, r_e;
u3x_cell(lr_e, &l_e, &r_e);
return u3nt(u3k(n_e),
_i_dif_join(u3k(d), u3k(l_e)),
_i_dif_join(d, l_e),
u3k(r_e));
}
}
@ -70,6 +73,10 @@ u3qdi_dif(u3_noun a,
e = u3qdi_dif(r_c, r_b);
u3z(c);
return _i_dif_join(d, e);
u3_noun pro = _i_dif_join(d, e);
u3z(d);
u3z(e);
return pro;
}
}

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\n", 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\n", 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\r\n", 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\n");
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\n");
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));
}
}

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