From 1a302f605f6bd2e44798ebbce05d19f2f47b6b96 Mon Sep 17 00:00:00 2001 From: bit4bit Date: Sat, 4 Dec 2021 15:44:45 +0000 Subject: [PATCH] se adiciona experimental/facho-wasm para crear wasm de firmado para facturacion electronica FossilOrigin-Name: f5823c4b16ec6f81eaf92676dfe4a2bee3edc150ce3485ffcd8732c2c4284e5b --- experimental/facho-wasm/xmlsec-wasm/build.sh | 7 + .../facho-wasm/xmlsec-wasm/build_libxml2.sh | 19 ++ .../facho-wasm/xmlsec-wasm/build_openssl.sh | 41 ++++ .../facho-wasm/xmlsec-wasm/build_xmlsec.sh | 14 ++ .../facho-wasm/xmlsec-wasm/examples/README.md | 6 + .../facho-wasm/xmlsec-wasm/examples/build.sh | 12 + .../facho-wasm/xmlsec-wasm/examples/sign.c | 216 ++++++++++++++++++ .../xmlsec-wasm/examples/sign1-tmpl.xml | 27 +++ .../xmlsec-wasm/openssl-1.1.1l.patch | 199 ++++++++++++++++ 9 files changed, 541 insertions(+) create mode 100644 experimental/facho-wasm/xmlsec-wasm/build.sh create mode 100644 experimental/facho-wasm/xmlsec-wasm/build_libxml2.sh create mode 100644 experimental/facho-wasm/xmlsec-wasm/build_openssl.sh create mode 100644 experimental/facho-wasm/xmlsec-wasm/build_xmlsec.sh create mode 100644 experimental/facho-wasm/xmlsec-wasm/examples/README.md create mode 100644 experimental/facho-wasm/xmlsec-wasm/examples/build.sh create mode 100644 experimental/facho-wasm/xmlsec-wasm/examples/sign.c create mode 100644 experimental/facho-wasm/xmlsec-wasm/examples/sign1-tmpl.xml create mode 100644 experimental/facho-wasm/xmlsec-wasm/openssl-1.1.1l.patch diff --git a/experimental/facho-wasm/xmlsec-wasm/build.sh b/experimental/facho-wasm/xmlsec-wasm/build.sh new file mode 100644 index 0000000..bcb6b0b --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/build.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -ex + +sh build_openssl.sh +sh build_libxml2.sh +sh build_xmlsec.sh diff --git a/experimental/facho-wasm/xmlsec-wasm/build_libxml2.sh b/experimental/facho-wasm/xmlsec-wasm/build_libxml2.sh new file mode 100644 index 0000000..d5743b7 --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/build_libxml2.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +LIBXML2_VERSION=2.9.12 + +tar xf libxml2-${LIBXML2_VERSION}.tar.gz + +mv libxml2-${LIBXML2_VERSION} libxml2 + +cd libxml2 + +wasiconfigure ./configure --enable-static --without-http --without-ftp --without-modules --without-python --without-zlib --without-lzma --without-threads --host=x86_64 + +wasimake make clean +wasimake make -j4 + +mkdir -p ../vendor/libxml2/lib +mkdir -p ../vendor/libxml2/include +cp -r include/libxml2 ../vendor/libxml2/include +cp -r .libs/libxml2.a ../vendor/libxml2/lib diff --git a/experimental/facho-wasm/xmlsec-wasm/build_openssl.sh b/experimental/facho-wasm/xmlsec-wasm/build_openssl.sh new file mode 100644 index 0000000..e78fe34 --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/build_openssl.sh @@ -0,0 +1,41 @@ +#!/bin/sh +# TOMADO DE: https://github.com/voltbuilder/openssl-wasm + +OPENSSL_VERSION=1.1.1l + +# get the source +tar xf openssl-${OPENSSL_VERSION}.tar.gz + +patch -p0 < openssl-${OPENSSL_VERSION}.patch + +cd openssl-${OPENSSL_VERSION} +make clean + +set -e + +# why ./Configure instead of ./config? We want to force using the generic gcc profile which is more conservative than linux-x32 +# -no-sock - we don't have sockets in WASI +# new -no-ui-console - sdk 12 has no termios??? +# check in 12 -DHAVE_FORK=0 - no fork() in WASI +# new -D_WASI_EMULATED_MMAN - works with the library below to enable WASI mman emulation +# new -D_WASI_EMULATED_SIGNAL - with sdk 12 +# new -DOPENSSL_NO_SECURE_MEMORY - wasi doesn't have secure mem (madvise, mlock, etc...) +# new -DNO_SYSLOG - get rid of need for patch above +# --with-rand-seed=getrandom (needed to force using getentropy because WASI has no /dev/random or getrandom) +wasiconfigure ./Configure gcc -no-sock -no-ui-console -DHAVE_FORK=0 -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_SIGNAL -DOPENSSL_NO_SECURE_MEMORY -DNO_SYSLOG --with-rand-seed=getrandom + +# enables stuff from mman.h (see define above) also add -lwasi-emulated-signal +#sed -i -e "s/CNF_EX_LIBS=/CNF_EX_LIBS=-lwasi-emulated-mman -lwasi-emulated-signal /g" Makefile + +# build! +wasimake make -j4 build_generated libssl.a libcrypto.a + +rm -rf ../vendor/openssl/include +mkdir -p ../vendor/openssl/include +cp -R include/openssl ../vendor/openssl/include + +mkdir -p ../vendor/openssl/lib/ +cp libssl.a ../vendor/openssl/lib/ +cp libcrypto.a ../vendor/openssl/lib/ + +exit 0 diff --git a/experimental/facho-wasm/xmlsec-wasm/build_xmlsec.sh b/experimental/facho-wasm/xmlsec-wasm/build_xmlsec.sh new file mode 100644 index 0000000..4f38e2f --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/build_xmlsec.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +XMLSEC1_VERSION=1.2.33 + +tar xf xmlsec1-${XMLSEC1_VERSION}.tar.gz + +cd xmlsec1-${XMLSEC1_VERSION} + +cp -r ../libxml2 . +cp -r ../vendor . + +wasiconfigure ./configure --with-libxml-src=`pwd`/libxml2 --with-openssl=`pwd`/vendor/openssl --enable-static-linking --disable-folders-search --disable-apps --disable-apps-crypto-dl --disable-crypto-dl + +wasimake make -j4 diff --git a/experimental/facho-wasm/xmlsec-wasm/examples/README.md b/experimental/facho-wasm/xmlsec-wasm/examples/README.md new file mode 100644 index 0000000..67dbc48 --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/examples/README.md @@ -0,0 +1,6 @@ +# ejemplo + +~~~ +$ bash build.sh +$ wasirun ./a.out sign1-tmpl.xml example.key +~~~ diff --git a/experimental/facho-wasm/xmlsec-wasm/examples/build.sh b/experimental/facho-wasm/xmlsec-wasm/examples/build.sh new file mode 100644 index 0000000..20ad4f6 --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/examples/build.sh @@ -0,0 +1,12 @@ +cp ../vendor/openssl/lib/*.a . +cp ../xmlsec1-1.2.33/src/.libs/*.a . +cp ../xmlsec1-1.2.33/src/openssl/.libs/*.a . +cp ../libxml2/.libs/libxml2.a . + +mkdir -p include + +cp -r ../libxml2/include/libxml include/ +cp -r ../xmlsec1-1.2.33/include/xmlsec include/ +cp -r ../vendor/openssl/include/* include/ + +wasicc -Iinclude libxml2.a libcrypto.a libssl.a libxmlsec1.a libxmlsec1-openssl.a sign.c diff --git a/experimental/facho-wasm/xmlsec-wasm/examples/sign.c b/experimental/facho-wasm/xmlsec-wasm/examples/sign.c new file mode 100644 index 0000000..4dde92c --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/examples/sign.c @@ -0,0 +1,216 @@ +/** + * XML Security Library example: Signing a template file. + * + * Signs a template file using a key from PEM file + * + * Usage: + * ./sign1 + * + * Example: + * ./sign1 sign1-tmpl.xml rsakey.pem > sign1-res.xml + * + * The result signature could be validated using verify1 example: + * ./verify1 sign1-res.xml rsapub.pem + * + * This is free software; see Copyright file in the source + * distribution for preciese wording. + * + * Copyright (C) 2002-2016 Aleksey Sanin . All Rights Reserved. + */ +#include +#include +#include + +#include +#include +#include + +#define XMLSEC_NO_XSLT +#define XMLSEC_CRYPTO_OPENSSL + +#ifndef XMLSEC_NO_XSLT +#include +#include +#endif /* XMLSEC_NO_XSLT */ + +#include +#include +#include +#include + +int sign_file(const char* tmpl_file, const char* key_file); + +int +main(int argc, char **argv) { +#ifndef XMLSEC_NO_XSLT + xsltSecurityPrefsPtr xsltSecPrefs = NULL; +#endif /* XMLSEC_NO_XSLT */ + setenv("RANDFILE", "/dev/random", 1); + assert(argv); + + if(argc != 3) { + fprintf(stderr, "Error: wrong number of arguments.\n"); + fprintf(stderr, "Usage: %s \n", argv[0]); + return(1); + } + + printf("template %s key %s\n", argv[1], argv[2]); + /* Init libxml and libxslt libraries */ + xmlInitParser(); + LIBXML_TEST_VERSION + xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; + xmlSubstituteEntitiesDefault(1); +#ifndef XMLSEC_NO_XSLT + xmlIndentTreeOutput = 1; +#endif /* XMLSEC_NO_XSLT */ + + /* Init libxslt */ +#ifndef XMLSEC_NO_XSLT + /* disable everything */ + xsltSecPrefs = xsltNewSecurityPrefs(); + xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_FILE, xsltSecurityForbid); + xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_FILE, xsltSecurityForbid); + xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_CREATE_DIRECTORY, xsltSecurityForbid); + xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_READ_NETWORK, xsltSecurityForbid); + xsltSetSecurityPrefs(xsltSecPrefs, XSLT_SECPREF_WRITE_NETWORK, xsltSecurityForbid); + xsltSetDefaultSecurityPrefs(xsltSecPrefs); +#endif /* XMLSEC_NO_XSLT */ + + /* Init xmlsec library */ + if(xmlSecInit() < 0) { + fprintf(stderr, "Error: xmlsec initialization failed.\n"); + return(-1); + } + puts("done xmlSecInit"); + + /* Check loaded library version */ + if(xmlSecCheckVersion() != 1) { + fprintf(stderr, "Error: loaded xmlsec library version is not compatible.\n"); + return(-1); + } + puts("done xmlSecCheckVersion"); + /* Load default crypto engine if we are supporting dynamic + * loading for xmlsec-crypto libraries. Use the crypto library + * name ("openssl", "nss", etc.) to load corresponding + * xmlsec-crypto library. + */ +#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING + if(xmlSecCryptoDLLoadLibrary(NULL) < 0) { + fprintf(stderr, "Error: unable to load default xmlsec-crypto library. Make sure\n" + "that you have it installed and check shared libraries path\n" + "(LD_LIBRARY_PATH and/or LTDL_LIBRARY_PATH) environment variables.\n"); + return(-1); + } +#endif /* XMLSEC_CRYPTO_DYNAMIC_LOADING */ + + /* Init crypto library */ + if(xmlSecCryptoAppInit(NULL) < 0) { + fprintf(stderr, "Error: crypto initialization failed.\n"); + return(-1); + } +puts("done xmlSecCryptoAppInit"); + /* Init xmlsec-crypto library */ + if(xmlSecCryptoInit() < 0) { + fprintf(stderr, "Error: xmlsec-crypto initialization failed.\n"); + return(-1); + } +puts("done xmlSecCryptoInit"); + if(sign_file(argv[1], argv[2]) < 0) { + return(-1); + } + + /* Shutdown xmlsec-crypto library */ + xmlSecCryptoShutdown(); + + /* Shutdown crypto library */ + xmlSecCryptoAppShutdown(); + + /* Shutdown xmlsec library */ + xmlSecShutdown(); + + /* Shutdown libxslt/libxml */ +#ifndef XMLSEC_NO_XSLT + xsltFreeSecurityPrefs(xsltSecPrefs); + xsltCleanupGlobals(); +#endif /* XMLSEC_NO_XSLT */ + xmlCleanupParser(); + + return(0); +} + +/** + * sign_file: + * @tmpl_file: the signature template file name. + * @key_file: the PEM private key file name. + * + * Signs the #tmpl_file using private key from #key_file. + * + * Returns 0 on success or a negative value if an error occurs. + */ +int +sign_file(const char* tmpl_file, const char* key_file) { + xmlDocPtr doc = NULL; + xmlNodePtr node = NULL; + xmlSecDSigCtxPtr dsigCtx = NULL; + int res = -1; + + assert(tmpl_file); + assert(key_file); + + /* load template */ + doc = xmlParseFile(tmpl_file); + if ((doc == NULL) || (xmlDocGetRootElement(doc) == NULL)){ + fprintf(stderr, "Error: unable to parse file \"%s\"\n", tmpl_file); + goto done; + } + + /* find start node */ + node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, xmlSecDSigNs); + if(node == NULL) { + fprintf(stderr, "Error: start node not found in \"%s\"\n", tmpl_file); + goto done; + } + + /* create signature context, we don't need keys manager in this example */ + dsigCtx = xmlSecDSigCtxCreate(NULL); + if(dsigCtx == NULL) { + fprintf(stderr,"Error: failed to create signature context\n"); + goto done; + } + + /* load private key, assuming that there is not password */ + dsigCtx->signKey = xmlSecCryptoAppKeyLoad(key_file, xmlSecKeyDataFormatPem, NULL, NULL, NULL); + if(dsigCtx->signKey == NULL) { + fprintf(stderr,"Error: failed to load private pem key from \"%s\"\n", key_file); + goto done; + } + + /* set key name to the file name, this is just an example! */ + if(xmlSecKeySetName(dsigCtx->signKey, key_file) < 0) { + fprintf(stderr,"Error: failed to set key name for key from \"%s\"\n", key_file); + goto done; + } + + /* sign the template */ + if(xmlSecDSigCtxSign(dsigCtx, node) < 0) { + fprintf(stderr,"Error: signature failed\n"); + goto done; + } + + /* print signed document to stdout */ + xmlDocDump(stdout, doc); + + /* success */ + res = 0; + +done: + /* cleanup */ + if(dsigCtx != NULL) { + xmlSecDSigCtxDestroy(dsigCtx); + } + + if(doc != NULL) { + xmlFreeDoc(doc); + } + return(res); +} diff --git a/experimental/facho-wasm/xmlsec-wasm/examples/sign1-tmpl.xml b/experimental/facho-wasm/xmlsec-wasm/examples/sign1-tmpl.xml new file mode 100644 index 0000000..ac71a94 --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/examples/sign1-tmpl.xml @@ -0,0 +1,27 @@ + + + + + Hello, World! + + + + + + + + + + + + + + + + + + + + diff --git a/experimental/facho-wasm/xmlsec-wasm/openssl-1.1.1l.patch b/experimental/facho-wasm/xmlsec-wasm/openssl-1.1.1l.patch new file mode 100644 index 0000000..a87c5d9 --- /dev/null +++ b/experimental/facho-wasm/xmlsec-wasm/openssl-1.1.1l.patch @@ -0,0 +1,199 @@ +diff '--color=auto' -ruN openssl-1.1.1l/crypto/rand/rand_unix.c patch-1.1.1l/crypto/rand/rand_unix.c +--- openssl-1.1.1l/crypto/rand/rand_unix.c 2021-08-24 09:38:47.000000000 -0400 ++++ patch-1.1.1l/crypto/rand/rand_unix.c 2021-09-12 02:26:35.765347423 -0400 +@@ -372,36 +372,36 @@ + * Note: Sometimes getentropy() can be provided but not implemented + * internally. So we need to check errno for ENOSYS + */ +-# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) +- extern int getentropy(void *buffer, size_t length) __attribute__((weak)); ++/* # if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux) */ ++/* extern int getentropy(void *buffer, size_t length) __attribute__((weak)); */ + +- if (getentropy != NULL) { ++/* if (getentropy != NULL) { */ + if (getentropy(buf, buflen) == 0) + return (ssize_t)buflen; + if (errno != ENOSYS) + return -1; +- } +-# elif defined(__APPLE__) +- if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) +- return (ssize_t)buflen; +- +- return -1; +-# else +- union { +- void *p; +- int (*f)(void *buffer, size_t length); +- } p_getentropy; +- +- /* +- * We could cache the result of the lookup, but we normally don't +- * call this function often. +- */ +- ERR_set_mark(); +- p_getentropy.p = DSO_global_lookup("getentropy"); +- ERR_pop_to_mark(); +- if (p_getentropy.p != NULL) +- return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; +-# endif ++/* } */ ++/* # elif defined(__APPLE__) */ ++/* if (CCRandomGenerateBytes(buf, buflen) == kCCSuccess) */ ++/* return (ssize_t)buflen; */ ++ ++/* return -1; */ ++/* # else */ ++/* union { */ ++/* void *p; */ ++/* int (*f)(void *buffer, size_t length); */ ++/* } p_getentropy; */ ++ ++/* /\* */ ++/* * We could cache the result of the lookup, but we normally don't */ ++/* * call this function often. */ ++/* *\/ */ ++/* ERR_set_mark(); */ ++/* p_getentropy.p = DSO_global_lookup("getentropy"); */ ++/* ERR_pop_to_mark(); */ ++/* if (p_getentropy.p != NULL) */ ++/* return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1; */ ++/* # endif */ + + /* Linux supports this since version 3.17 */ + # if defined(__linux) && defined(__NR_getrandom) +@@ -635,12 +635,12 @@ + */ + size_t rand_pool_acquire_entropy(RAND_POOL *pool) + { +-# if defined(OPENSSL_RAND_SEED_NONE) +- return rand_pool_entropy_available(pool); +-# else ++/* # if defined(OPENSSL_RAND_SEED_NONE) */ ++/* return rand_pool_entropy_available(pool); */ ++/* # else */ + size_t entropy_available; + +-# if defined(OPENSSL_RAND_SEED_GETRANDOM) ++/* # if defined(OPENSSL_RAND_SEED_GETRANDOM) */ + { + size_t bytes_needed; + unsigned char *buffer; +@@ -664,7 +664,7 @@ + entropy_available = rand_pool_entropy_available(pool); + if (entropy_available > 0) + return entropy_available; +-# endif ++/* # endif */ + + # if defined(OPENSSL_RAND_SEED_LIBRANDOM) + { +@@ -752,7 +752,7 @@ + # endif + + return rand_pool_entropy_available(pool); +-# endif ++/* # endif */ + } + # endif + #endif +diff '--color=auto' -ruN openssl-1.1.1l/test/drbgtest.c patch-1.1.1l/test/drbgtest.c +--- openssl-1.1.1l/test/drbgtest.c 2021-08-24 09:38:47.000000000 -0400 ++++ patch-1.1.1l/test/drbgtest.c 2021-09-12 02:07:38.062332301 -0400 +@@ -22,8 +22,21 @@ + # include + #endif + ++#ifndef HAVE_FORK ++# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS) ++# define HAVE_FORK 0 ++# else ++# define HAVE_FORK 1 ++# endif ++#endif ++ ++#if HAVE_FORK ++# undef NO_FORK ++#else ++# define NO_FORK ++#endif + +-#if defined(OPENSSL_SYS_UNIX) ++#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK) + # include + # include + # include +@@ -676,7 +689,7 @@ + } + + +-#if defined(OPENSSL_SYS_UNIX) ++#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK) + /* + * Test whether master, public and private DRBG are reseeded after + * forking the process. +@@ -795,7 +808,7 @@ + goto error; + reset_drbg_hook_ctx(); + +-#if defined(OPENSSL_SYS_UNIX) ++#if defined(OPENSSL_SYS_UNIX) && !defined(NO_FORK) + if (!TEST_true(test_drbg_reseed_after_fork(master, public, private))) + goto error; + #endif +diff '--color=auto' -ruN openssl-1.1.1l/test/run_tests.pl patch-1.1.1l/test/run_tests.pl +--- openssl-1.1.1l/test/run_tests.pl 2021-08-24 09:38:47.000000000 -0400 ++++ patch-1.1.1l/test/run_tests.pl 2021-09-12 02:03:57.603451471 -0400 +@@ -28,7 +28,7 @@ + my $recipesdir = catdir($srctop, "test", "recipes"); + my $libdir = rel2abs(catdir($srctop, "util", "perl")); + +-$ENV{OPENSSL_CONF} = catdir($srctop, "apps", "openssl.cnf"); ++$ENV{OPENSSL_CONF} = rel2abs(catdir($srctop, "apps", "openssl.cnf")); + + my %tapargs = + ( verbosity => $ENV{VERBOSE} || $ENV{V} || $ENV{HARNESS_VERBOSE} ? 1 : 0, +diff '--color=auto' -ruN openssl-1.1.1l/util/perl/OpenSSL/Test.pm patch-1.1.1l/util/perl/OpenSSL/Test.pm +--- openssl-1.1.1l/util/perl/OpenSSL/Test.pm 2021-08-24 09:38:47.000000000 -0400 ++++ patch-1.1.1l/util/perl/OpenSSL/Test.pm 2021-09-12 02:01:14.155136681 -0400 +@@ -65,7 +65,7 @@ + rel2abs/; + use File::Path 2.00 qw/rmtree mkpath/; + use File::Basename; +-use Cwd qw/getcwd abs_path/; ++use Cwd qw/abs_path/; + + my $level = 0; + +@@ -904,26 +904,26 @@ + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $f = pop; +- return abs2rel(catfile($directories{SRCTOP},@_,$f),getcwd); ++ return catfile($directories{SRCTOP},@_,$f); + } + + sub __srctop_dir { + BAIL_OUT("Must run setup() first") if (! $test_name); + +- return abs2rel(catdir($directories{SRCTOP},@_), getcwd); ++ return catdir($directories{SRCTOP},@_); + } + + sub __bldtop_file { + BAIL_OUT("Must run setup() first") if (! $test_name); + + my $f = pop; +- return abs2rel(catfile($directories{BLDTOP},@_,$f), getcwd); ++ return catfile($directories{BLDTOP},@_,$f); + } + + sub __bldtop_dir { + BAIL_OUT("Must run setup() first") if (! $test_name); + +- return abs2rel(catdir($directories{BLDTOP},@_), getcwd); ++ return catdir($directories{BLDTOP},@_); + } + + # __exeext is a function that returns the platform dependent file extension