diff --git a/.gitignore b/.gitignore
index e0281ae9..526277f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -134,6 +134,7 @@ test/default/secretbox7
test/default/secretbox8
test/default/secretbox_easy
test/default/secretbox_easy2
+test/default/secretstream
test/default/shorthash
test/default/sign
test/default/siphashx24
diff --git a/ChangeLog b/ChangeLog
index ce502497..b3e331d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,8 @@ store keys to.
- SSE2 implementations of `crypto_verify_*()` have been added.
- Passwords can be hashed using a specific algorithm with the new
`crypto_pwhash_str_alg()` function.
+ - Due to popular demand, base64 encoding (`sodium_bin2base64()`) and
+decoding (`sodium_base642bin()`) have been implemented.
* Version 1.0.13
- Javascript: the sumo builds now include all symbols. They were
diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj b/builds/msvc/vs2010/libsodium/libsodium.vcxproj
index 122b5330..e2a50bbe 100644
--- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj
@@ -181,6 +181,7 @@
+
diff --git a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters
index 67cdb12b..366153e8 100644
--- a/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2010/libsodium/libsodium.vcxproj.filters
@@ -336,6 +336,9 @@
randombytes\sysrandom
+
+ sodium
+
sodium
diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj b/builds/msvc/vs2012/libsodium/libsodium.vcxproj
index 2430855f..d278f407 100644
--- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj
@@ -181,6 +181,7 @@
+
diff --git a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters
index 67cdb12b..366153e8 100644
--- a/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2012/libsodium/libsodium.vcxproj.filters
@@ -336,6 +336,9 @@
randombytes\sysrandom
+
+ sodium
+
sodium
diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj b/builds/msvc/vs2013/libsodium/libsodium.vcxproj
index d4fa9fb2..5c4ba37d 100644
--- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj
@@ -181,6 +181,7 @@
+
diff --git a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters
index 67cdb12b..366153e8 100644
--- a/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2013/libsodium/libsodium.vcxproj.filters
@@ -336,6 +336,9 @@
randombytes\sysrandom
+
+ sodium
+
sodium
diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj b/builds/msvc/vs2015/libsodium/libsodium.vcxproj
index 87379646..bb5a01f6 100644
--- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj
@@ -181,6 +181,7 @@
+
diff --git a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters
index 67cdb12b..366153e8 100644
--- a/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2015/libsodium/libsodium.vcxproj.filters
@@ -336,6 +336,9 @@
randombytes\sysrandom
+
+ sodium
+
sodium
diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj b/builds/msvc/vs2017/libsodium/libsodium.vcxproj
index 8b59d53e..ff99c6fc 100644
--- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj
+++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj
@@ -181,6 +181,7 @@
+
diff --git a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters
index 67cdb12b..366153e8 100644
--- a/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters
+++ b/builds/msvc/vs2017/libsodium/libsodium.vcxproj.filters
@@ -336,6 +336,9 @@
randombytes\sysrandom
+
+ sodium
+
sodium
diff --git a/configure.ac b/configure.ac
index da6a261c..98df317b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -280,16 +280,17 @@ AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wformat=2], [CWFLAGS="$CWFLAGS -Wformat=2"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wmissing-declarations], [CWFLAGS="$CWFLAGS -Wmissing-declarations"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wmissing-prototypes], [CWFLAGS="$CWFLAGS -Wmissing-prototypes"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wnested-externs], [CWFLAGS="$CWFLAGS -Wnested-externs"])
+AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wno-type-limits], [CWFLAGS="$CWFLAGS -Wno-type-limits"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wno-unknown-pragmas], [CWFLAGS="$CWFLAGS -Wno-unknown-pragmas"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wnormalized=id], [CWFLAGS="$CWFLAGS -Wnormalized=id"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wnull-dereference], [CWFLAGS="$CWFLAGS -Wnull-dereference"])
+AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wold-style-declaration], [CWFLAGS="$CWFLAGS -Wold-style-declaration"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wpointer-arith], [CWFLAGS="$CWFLAGS -Wpointer-arith"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wredundant-decls], [CWFLAGS="$CWFLAGS -Wredundant-decls"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wshorten-64-to-32], [CWFLAGS="$CWFLAGS -Wshorten-64-to-32"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wstrict-prototypes], [CWFLAGS="$CWFLAGS -Wstrict-prototypes"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wswitch-enum], [CWFLAGS="$CWFLAGS -Wswitch-enum"])
AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wvariable-decl], [CWFLAGS="$CWFLAGS -Wvariable-decl"])
-AX_CHECK_COMPILE_FLAG([$CWFLAGS -Wno-type-limits], [CWFLAGS="$CWFLAGS -Wno-type-limits"])
AX_CHECK_LINK_FLAG([-Wl,-z,relro], [LDFLAGS="$LDFLAGS -Wl,-z,relro"])
AX_CHECK_LINK_FLAG([-Wl,-z,now], [LDFLAGS="$LDFLAGS -Wl,-z,now"])
diff --git a/libsodium.vcxproj b/libsodium.vcxproj
index cd0b7299..05448ee8 100644
--- a/libsodium.vcxproj
+++ b/libsodium.vcxproj
@@ -419,6 +419,7 @@
+
diff --git a/libsodium.vcxproj.filters b/libsodium.vcxproj.filters
index b0536551..c0bb58d8 100644
--- a/libsodium.vcxproj.filters
+++ b/libsodium.vcxproj.filters
@@ -327,6 +327,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/packaging/dotnet-core/desktop.targets b/packaging/dotnet-core/desktop.targets
deleted file mode 100644
index b117c478..00000000
--- a/packaging/dotnet-core/desktop.targets
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
- x86\libsodium.dll
- PreserveNewest
- PreserveNewest
- false
-
-
- x64\libsodium.dll
- PreserveNewest
- PreserveNewest
- false
-
-
-
\ No newline at end of file
diff --git a/packaging/dotnet-core/libsodium.props b/packaging/dotnet-core/libsodium.props
index 1986e39b..96f62f70 100644
--- a/packaging/dotnet-core/libsodium.props
+++ b/packaging/dotnet-core/libsodium.props
@@ -2,7 +2,7 @@
- netstandard1.1;net46
+ netstandard1.1
true
true
false
@@ -27,7 +27,6 @@
-
diff --git a/packaging/dotnet-core/prepare.py b/packaging/dotnet-core/prepare.py
index 44d2d8e4..610e4ebd 100755
--- a/packaging/dotnet-core/prepare.py
+++ b/packaging/dotnet-core/prepare.py
@@ -8,8 +8,8 @@ WINDOWS = [
# --------------------- ----------------- #
# Runtime ID Platform #
# --------------------- ----------------- #
- ( 'win7-x64', 'x64' ),
- ( 'win7-x86', 'Win32' ),
+ ( 'win-x64', 'x64' ),
+ ( 'win-x86', 'Win32' ),
# --------------------- ----------------- #
]
@@ -17,9 +17,7 @@ MACOS = [
# --------------------- ----------------- #
# Runtime ID Codename #
# --------------------- ----------------- #
- ( 'osx.10.10-x64', 'yosemite' ),
- ( 'osx.10.11-x64', 'el_capitan' ),
- ( 'osx.10.12-x64', 'sierra' ),
+ ( 'osx-x64', 'sierra' ),
# --------------------- ----------------- #
]
@@ -27,22 +25,13 @@ LINUX = [
# --------------------- ----------------- #
# Runtime ID Docker Image #
# --------------------- ----------------- #
- ( 'centos.7-x64', 'centos:7.1.1503' ),
- ( 'debian.8-x64', 'debian:8.2' ),
- ( 'fedora.24-x64', 'fedora:24' ),
- ( 'fedora.25-x64', 'fedora:25' ),
- ( 'fedora.26-x64', 'fedora:26' ),
- ( 'opensuse.42.1-x64', 'opensuse:42.1' ),
- ( 'ubuntu.14.04-x64', 'ubuntu:trusty' ),
- ( 'ubuntu.16.04-x64', 'ubuntu:xenial' ),
- ( 'ubuntu.16.10-x64', 'ubuntu:yakkety' ),
+ ( 'linux-x64', 'debian:stretch' ),
# --------------------- ----------------- #
]
EXTRAS = [ 'LICENSE', 'AUTHORS', 'ChangeLog' ]
PROPSFILE = 'libsodium.props'
-DESKTOPTARGETSFILE = 'desktop.targets'
MAKEFILE = 'Makefile'
BUILDDIR = 'build'
CACHEDIR = 'cache'
@@ -64,7 +53,6 @@ class Version:
self.projfile = os.path.join(self.builddir, '{0}.{1}.pkgproj'.format(PACKAGE, package_version))
self.propsfile = os.path.join(self.builddir, '{0}.props'.format(PACKAGE))
self.pkgfile = os.path.join(BUILDDIR, '{0}.{1}.nupkg'.format(PACKAGE, package_version))
- self.desktoptargetsfile = os.path.join(self.builddir, 'build', 'net46', '{0}.targets'.format(PACKAGE))
class WindowsItem:
@@ -212,11 +200,6 @@ def main(args):
for item in items:
item.make(f)
- f.write('\n')
- f.write('{0}: {1}\n'.format(version.desktoptargetsfile, DESKTOPTARGETSFILE))
- f.write('\t@mkdir -p $(dir $@)\n')
- f.write('\tcp -f $< $@\n')
-
f.write('\n')
f.write('{0}: {1}\n'.format(version.propsfile, PROPSFILE))
f.write('\t@mkdir -p $(dir $@)\n')
@@ -237,7 +220,6 @@ def main(args):
f.write('{0}:'.format(version.pkgfile))
f.write(' \\\n\t\t{0}'.format(version.projfile))
f.write(' \\\n\t\t{0}'.format(version.propsfile))
- f.write(' \\\n\t\t{0}'.format(version.desktoptargetsfile))
for item in items:
f.write(' \\\n\t\t{0}'.format(item.packfile))
f.write('\n')
@@ -246,14 +228,14 @@ def main(args):
'-v $(abspath recipes):/io/recipes ' +
'-v $(abspath $(dir $<)):/io/input ' +
'-v $(abspath $(dir $@)):/io/output ' +
- '{0} sh -x -e /io/recipes/{1} {2}\n'.format('microsoft/dotnet:1.1-sdk', 'pack', os.path.relpath(version.projfile, version.builddir)))
+ '{0} sh -x -e /io/recipes/{1} {2}\n'.format('microsoft/dotnet:2.0-sdk', 'pack', os.path.relpath(version.projfile, version.builddir)))
f.write('\n')
f.write('test: {0}\n'.format(version.pkgfile))
f.write('\t{0} run --rm '.format(DOCKER) +
'-v $(abspath recipes):/io/recipes ' +
'-v $(abspath $(dir $<)):/io/packages ' +
- '{0} sh -x -e /io/recipes/{1} "{2}"\n'.format('microsoft/dotnet:1.1-sdk', 'test', version.package_version))
+ '{0} sh -x -e /io/recipes/{1} "{2}"\n'.format('microsoft/dotnet:2.0-sdk', 'test', version.package_version))
print('prepared', MAKEFILE, 'to make', version.pkgfile, 'for libsodium', version.libsodium_version)
return 0
diff --git a/packaging/dotnet-core/recipes/linux-x64 b/packaging/dotnet-core/recipes/linux-x64
new file mode 100644
index 00000000..e22c9efc
--- /dev/null
+++ b/packaging/dotnet-core/recipes/linux-x64
@@ -0,0 +1,4 @@
+apt-get update
+apt-get install -y --no-install-recommends build-essential
+
+. $(dirname $0)/build
diff --git a/src/libsodium/Makefile.am b/src/libsodium/Makefile.am
index cf0cffb3..8186b806 100644
--- a/src/libsodium/Makefile.am
+++ b/src/libsodium/Makefile.am
@@ -62,6 +62,7 @@ libsodium_la_SOURCES = \
crypto_secretbox/crypto_secretbox.c \
crypto_secretbox/crypto_secretbox_easy.c \
crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c \
+ crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c \
crypto_shorthash/crypto_shorthash.c \
crypto_shorthash/siphash24/shorthash_siphash24.c \
crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c \
@@ -87,6 +88,7 @@ libsodium_la_SOURCES = \
include/sodium/private/mutex.h \
include/sodium/private/sse2_64_32.h \
randombytes/randombytes.c \
+ sodium/codecs.c \
sodium/core.c \
sodium/runtime.c \
sodium/utils.c \
diff --git a/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c b/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
index 51667d02..b5993367 100644
--- a/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
+++ b/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
@@ -1920,11 +1920,11 @@ ge_mul_l(ge_p3 *r, const ge_p3 *A)
static const signed char aslide[253] = {
13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
};
- ge_cached Ai[8];
- ge_p1p1 t;
- ge_p3 u;
- ge_p3 A2;
- int i;
+ ge_cached Ai[8];
+ ge_p1p1 t;
+ ge_p3 u;
+ ge_p3 A2;
+ int i;
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
diff --git a/src/libsodium/crypto_pwhash/argon2/argon2-encoding.c b/src/libsodium/crypto_pwhash/argon2/argon2-encoding.c
index 5224cb61..a08acdda 100644
--- a/src/libsodium/crypto_pwhash/argon2/argon2-encoding.c
+++ b/src/libsodium/crypto_pwhash/argon2/argon2-encoding.c
@@ -1,5 +1,6 @@
#include "argon2-encoding.h"
#include "argon2-core.h"
+#include "utils.h"
#include
#include
#include
@@ -9,19 +10,6 @@
* Example code for a decoder and encoder of "hash strings", with Argon2
* parameters.
*
- * This code comprises three sections:
- *
- * -- The first section contains generic Base64 encoding and decoding
- * functions. It is conceptually applicable to any hash function
- * implementation that uses Base64 to encode and decode parameters,
- * salts and outputs. It could be made into a library, provided that
- * the relevant functions are made public (non-static) and be given
- * reasonable names to avoid collisions with other functions.
- *
- * -- The second section is specific to Argon2. It encodes and decodes
- * the parameters, salts and outputs. It does not compute the hash
- * itself.
- *
* The code was originally written by Thomas Pornin ,
* to whom comments and remarks may be sent. It is released under what
* should amount to Public Domain or its closest equivalent; the
@@ -39,156 +27,6 @@
*/
/* ==================================================================== */
-/*
- * Common code; could be shared between different hash functions.
- *
- * Note: the Base64 functions below assume that uppercase letters (resp.
- * lowercase letters) have consecutive numerical codes, that fit on 8
- * bits. All modern systems use ASCII-compatible charsets, where these
- * properties are true. If you are stuck with a dinosaur of a system
- * that still defaults to EBCDIC then you already have much bigger
- * interoperability issues to deal with.
- */
-
-/*
- * Some macros for constant-time comparisons. These work over values in
- * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
- */
-#define EQ(x, y) \
- ((((0U - ((unsigned) (x) ^ (unsigned) (y))) >> 8) & 0xFF) ^ 0xFF)
-#define GT(x, y) ((((unsigned) (y) - (unsigned) (x)) >> 8) & 0xFF)
-#define GE(x, y) (GT(y, x) ^ 0xFF)
-#define LT(x, y) GT(y, x)
-#define LE(x, y) GE(y, x)
-
-/*
- * Convert value x (0..63) to corresponding Base64 character.
- */
-static int
-b64_byte_to_char(unsigned x)
-{
- return (LT(x, 26) & (x + 'A')) |
- (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
- (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
- (EQ(x, 63) & '/');
-}
-
-/*
- * Convert character c to the corresponding 6-bit value. If character c
- * is not a Base64 character, then 0xFF (255) is returned.
- */
-static unsigned
-b64_char_to_byte(int c)
-{
- unsigned x;
-
- x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
- (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
- (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
- (EQ(c, '/') & 63);
- return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
-}
-
-/*
- * Convert some bytes to Base64. 'dst_len' is the length (in characters)
- * of the output buffer 'dst'; if that buffer is not large enough to
- * receive the result (including the terminating 0), then (size_t)-1
- * is returned. Otherwise, the zero-terminated Base64 string is written
- * in the buffer, and the output length (counted WITHOUT the terminating
- * zero) is returned.
- */
-static size_t
-to_base64(char *dst, size_t dst_len, const void *src, size_t src_len)
-{
- size_t olen;
- const unsigned char *buf;
- unsigned acc, acc_len;
-
- olen = (src_len / 3) << 2;
- switch (src_len % 3) {
- case 2:
- olen++;
- /* fall through */
- case 1:
- olen += 2;
- break;
- }
- if (dst_len <= olen) {
- return (size_t) -1;
- }
- acc = 0;
- acc_len = 0;
- buf = (const unsigned char *) src;
- while (src_len-- > 0) {
- acc = (acc << 8) + (*buf++);
- acc_len += 8;
- while (acc_len >= 6) {
- acc_len -= 6;
- *dst++ = (char) b64_byte_to_char((acc >> acc_len) & 0x3F);
- }
- }
- if (acc_len > 0) {
- *dst++ = (char) b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
- }
- *dst++ = 0;
- return olen;
-}
-
-/*
- * Decode Base64 chars into bytes. The '*dst_len' value must initially
- * contain the length of the output buffer '*dst'; when the decoding
- * ends, the actual number of decoded bytes is written back in
- * '*dst_len'.
- *
- * Decoding stops when a non-Base64 character is encountered, or when
- * the output buffer capacity is exceeded. If an error occurred (output
- * buffer is too small, invalid last characters leading to unprocessed
- * buffered bits), then NULL is returned; otherwise, the returned value
- * points to the first non-Base64 character in the source stream, which
- * may be the terminating zero.
- */
-static const char *
-from_base64(void *dst, size_t *dst_len, const char *src)
-{
- size_t len;
- unsigned char *buf;
- unsigned acc, acc_len;
-
- buf = (unsigned char *) dst;
- len = 0;
- acc = 0;
- acc_len = 0;
- for (;;) {
- unsigned d;
-
- d = b64_char_to_byte(*src);
- if (d == 0xFF) {
- break;
- }
- src++;
- acc = (acc << 6) + d;
- acc_len += 6;
- if (acc_len >= 8) {
- acc_len -= 8;
- if ((len++) >= *dst_len) {
- return NULL;
- }
- *buf++ = (acc >> acc_len) & 0xFF;
- }
- }
-
- /*
- * If the input length is equal to 1 modulo 4 (which is
- * invalid), then there will remain 6 unprocessed bits;
- * otherwise, only 0, 2 or 4 bits are buffered. The buffered
- * bits must also all be zero.
- */
- if (acc_len > 4 || (acc & ((1U << acc_len) - 1)) != 0) {
- return NULL;
- }
- *dst_len = len;
- return src;
-}
/*
* Decode decimal integer from 'str'; the value is written in '*v'.
@@ -300,14 +138,18 @@ decode_string(argon2_context *ctx, const char *str, argon2_type type)
} while ((void)0, 0)
/* Decoding base64 into a binary buffer */
-#define BIN(buf, max_len, len) \
- do { \
- size_t bin_len = (max_len); \
- str = from_base64(buf, &bin_len, str); \
- if (str == NULL || bin_len > UINT32_MAX) { \
- return ARGON2_DECODING_FAIL; \
- } \
- (len) = (uint32_t) bin_len; \
+#define BIN(buf, max_len, len) \
+ do { \
+ size_t bin_len = (max_len); \
+ const char *str_end; \
+ if (sodium_base642bin((buf), (max_len), str, strlen(str), NULL, \
+ &bin_len, &str_end, \
+ sodium_base64_VARIANT_ORIGINAL_NO_PADDING) != 0 || \
+ bin_len > UINT32_MAX) { \
+ return ARGON2_DECODING_FAIL; \
+ } \
+ (len) = (uint32_t) bin_len; \
+ str = str_end; \
} while ((void) 0, 0)
size_t maxsaltlen = ctx->saltlen;
@@ -416,14 +258,16 @@ encode_string(char *dst, size_t dst_len, argon2_context *ctx, argon2_type type)
SS(tmp); \
} while ((void) 0, 0)
-#define SB(buf, len) \
- do { \
- size_t sb_len = to_base64(dst, dst_len, buf, len); \
- if (sb_len == (size_t) -1) { \
- return ARGON2_ENCODING_FAIL; \
- } \
- dst += sb_len; \
- dst_len -= sb_len; \
+#define SB(buf, len) \
+ do { \
+ size_t sb_len; \
+ if (sodium_bin2base64(dst, dst_len, (buf), (len), \
+ sodium_base64_VARIANT_ORIGINAL_NO_PADDING) == NULL) { \
+ return ARGON2_ENCODING_FAIL; \
+ } \
+ sb_len = strlen(dst); \
+ dst += sb_len; \
+ dst_len -= sb_len; \
} while ((void) 0, 0)
int validation_result;
diff --git a/src/libsodium/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c b/src/libsodium/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c
new file mode 100644
index 00000000..b2ed5141
--- /dev/null
+++ b/src/libsodium/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c
@@ -0,0 +1,237 @@
+
+#include
+#include
+#include
+#include
+
+#include "core.h"
+#include "crypto_aead_chacha20poly1305.h"
+#include "crypto_aead_xchacha20poly1305.h"
+#include "crypto_core_hchacha20.h"
+#include "crypto_onetimeauth_poly1305.h"
+#include "crypto_secretstream_xchacha20poly1305.h"
+#include "randombytes.h"
+#include "utils.h"
+
+#include "private/common.h"
+
+#define crypto_secretstream_xchacha20poly1305_COUNTERBYTES 4U
+#define crypto_secretstream_xchacha20poly1305_INONCEBYTES 8U
+
+static const unsigned char _pad0[16] = { 0 };
+
+void
+crypto_secretstream_xchacha20poly1305_keygen
+ (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
+{
+ randombytes_buf(k, crypto_secretstream_xchacha20poly1305_KEYBYTES);
+}
+
+int
+crypto_secretstream_xchacha20poly1305_init_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char out[crypto_secretstream_xchacha20poly1305_INITBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
+{
+ COMPILER_ASSERT(crypto_secretstream_xchacha20poly1305_INITBYTES ==
+ crypto_core_hchacha20_INPUTBYTES + crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+
+ randombytes_buf(out, crypto_secretstream_xchacha20poly1305_INITBYTES);
+ crypto_core_hchacha20(state->k, out, k, NULL);
+ memcpy(state->nonce, out + crypto_core_hchacha20_INPUTBYTES,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ memset(state->nonce + crypto_secretstream_xchacha20poly1305_INONCEBYTES, 0,
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ memset(state->_pad, 0, sizeof state->_pad);
+
+ return 0;
+}
+
+int
+crypto_secretstream_xchacha20poly1305_init_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ const unsigned char in[crypto_secretstream_xchacha20poly1305_INITBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES])
+{
+ crypto_core_hchacha20(state->k, in, k, NULL);
+ memcpy(state->nonce, in + crypto_core_hchacha20_INPUTBYTES,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ memset(state->nonce + crypto_secretstream_xchacha20poly1305_INONCEBYTES, 0,
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ memset(state->_pad, 0, sizeof state->_pad);
+
+ return 0;
+}
+
+void
+crypto_secretstream_xchacha20poly1305_rekey
+ (crypto_secretstream_xchacha20poly1305_state *state)
+{
+ unsigned char new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES];
+
+ crypto_stream_chacha20_ietf(new_key_and_inonce, sizeof new_key_and_inonce,
+ state->nonce, state->k);
+ memcpy(state->k, new_key_and_inonce, sizeof state->k);
+ memcpy(state->nonce, new_key_and_inonce + sizeof state->k,
+ crypto_secretstream_xchacha20poly1305_INONCEBYTES);
+ memset(state->nonce + crypto_secretstream_xchacha20poly1305_INONCEBYTES, 0,
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+}
+
+int
+crypto_secretstream_xchacha20poly1305_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *out, unsigned long long *outlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen, unsigned char tag)
+{
+ crypto_onetimeauth_poly1305_state poly1305_state;
+ unsigned char block[64U];
+ unsigned char slen[8U];
+ unsigned char *c;
+ unsigned char *mac;
+ unsigned int i;
+
+ if (outlen_p != NULL) {
+ *outlen_p = 0U;
+ }
+ if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX) {
+ sodium_misuse();
+ }
+ crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
+ crypto_onetimeauth_poly1305_init(&poly1305_state, block);
+ sodium_memzero(block, sizeof block);
+
+ crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
+ (0x10 - adlen) & 0xf);
+ memset(block, 0, sizeof block);
+ block[0] = tag;
+
+ crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
+ state->nonce, 1U, state->k);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
+ out[0] = block[0];
+
+ c = out + (sizeof tag);
+ crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce, 2U, state->k);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
+ crypto_onetimeauth_poly1305_update
+ (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
+
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+ STORE64_LE(slen, (sizeof block) + mlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+
+ mac = c + mlen;
+ crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
+ sodium_memzero(&poly1305_state, sizeof poly1305_state);
+
+ for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
+ state->nonce[i] ^= mac[i];
+ }
+ sodium_increment(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
+ sodium_is_zero(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
+ crypto_secretstream_xchacha20poly1305_rekey(state);
+ }
+ if (outlen_p != NULL) {
+ *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES + mlen;
+ }
+ return 0;
+}
+
+int
+crypto_secretstream_xchacha20poly1305_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
+ const unsigned char *in, unsigned long long inlen,
+ const unsigned char *ad, unsigned long long adlen)
+{
+ crypto_onetimeauth_poly1305_state poly1305_state;
+ unsigned char block[64U];
+ unsigned char slen[8U];
+ unsigned char mac[crypto_onetimeauth_poly1305_BYTES];
+ const unsigned char *c;
+ const unsigned char *stored_mac;
+ unsigned long long mlen;
+ unsigned int i;
+ unsigned char tag;
+
+ if (mlen_p != NULL) {
+ *mlen_p = 0U;
+ }
+ if (tag_p != NULL) {
+ *tag_p = 0xff;
+ }
+ if (inlen < crypto_secretstream_xchacha20poly1305_ABYTES) {
+ return -1;
+ }
+ mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
+ if (mlen > crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX) {
+ sodium_misuse();
+ }
+ crypto_stream_chacha20_ietf(block, sizeof block, state->nonce, state->k);
+ crypto_onetimeauth_poly1305_init(&poly1305_state, block);
+ sodium_memzero(block, sizeof block);
+
+ crypto_onetimeauth_poly1305_update(&poly1305_state, ad, adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
+ (0x10 - adlen) & 0xf);
+
+ memset(block, 0, sizeof block);
+ block[0] = in[0];
+ crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
+ state->nonce, 1U, state->k);
+ tag = block[0];
+ block[0] = in[0];
+ crypto_onetimeauth_poly1305_update(&poly1305_state, block, sizeof block);
+
+ c = in + (sizeof tag);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
+ crypto_onetimeauth_poly1305_update
+ (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) & 0xf);
+
+ STORE64_LE(slen, (uint64_t) adlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+ STORE64_LE(slen, (sizeof block) + mlen);
+ crypto_onetimeauth_poly1305_update(&poly1305_state, slen, sizeof slen);
+
+ crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
+ sodium_memzero(&poly1305_state, sizeof poly1305_state);
+
+ stored_mac = c + mlen;
+ if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
+ sodium_memzero(mac, sizeof mac);
+ return -1;
+ }
+
+ crypto_stream_chacha20_ietf_xor_ic(m, c, mlen, state->nonce, 2U, state->k);
+ for (i = 0U; i < crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
+ state->nonce[i] ^= mac[i];
+ }
+ sodium_increment(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
+ if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
+ sodium_is_zero(&state->nonce[crypto_secretstream_xchacha20poly1305_INONCEBYTES],
+ crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
+ crypto_secretstream_xchacha20poly1305_rekey(state);
+ }
+ if (mlen_p != NULL) {
+ *mlen_p = mlen;
+ }
+ if (tag_p != NULL) {
+ *tag_p = tag;
+ }
+ return 0;
+}
+
+size_t
+crypto_secretstream_xchacha20poly1305_statebytes(void)
+{
+ return sizeof(crypto_secretstream_xchacha20poly1305_state);
+}
diff --git a/src/libsodium/include/Makefile.am b/src/libsodium/include/Makefile.am
index a63d127a..06f3f4a4 100644
--- a/src/libsodium/include/Makefile.am
+++ b/src/libsodium/include/Makefile.am
@@ -36,6 +36,7 @@ SODIUM_EXPORT = \
sodium/crypto_secretbox.h \
sodium/crypto_secretbox_xchacha20poly1305.h \
sodium/crypto_secretbox_xsalsa20poly1305.h \
+ sodium/crypto_secretstream_xchacha20poly1305.h \
sodium/crypto_shorthash.h \
sodium/crypto_shorthash_siphash24.h \
sodium/crypto_sign.h \
diff --git a/src/libsodium/include/sodium.h b/src/libsodium/include/sodium.h
index 1f79e87b..8c3e8bc7 100644
--- a/src/libsodium/include/sodium.h
+++ b/src/libsodium/include/sodium.h
@@ -35,6 +35,7 @@
#include "sodium/crypto_scalarmult_curve25519.h"
#include "sodium/crypto_secretbox.h"
#include "sodium/crypto_secretbox_xsalsa20poly1305.h"
+#include "sodium/crypto_secretstream_xchacha20poly1305.h"
#include "sodium/crypto_shorthash.h"
#include "sodium/crypto_shorthash_siphash24.h"
#include "sodium/crypto_sign.h"
diff --git a/src/libsodium/include/sodium/crypto_pwhash.h b/src/libsodium/include/sodium/crypto_pwhash.h
index da5f5461..d0b8bba7 100644
--- a/src/libsodium/include/sodium/crypto_pwhash.h
+++ b/src/libsodium/include/sodium/crypto_pwhash.h
@@ -94,6 +94,10 @@ size_t crypto_pwhash_opslimit_sensitive(void);
SODIUM_EXPORT
size_t crypto_pwhash_memlimit_sensitive(void);
+/*
+ * With this function, do not forget to store all parameters, including the
+ * algorithm identifier in order to produce deterministic output.
+ */
SODIUM_EXPORT
int crypto_pwhash(unsigned char * const out, unsigned long long outlen,
const char * const passwd, unsigned long long passwdlen,
@@ -101,6 +105,11 @@ int crypto_pwhash(unsigned char * const out, unsigned long long outlen,
unsigned long long opslimit, size_t memlimit, int alg)
__attribute__ ((warn_unused_result));
+/*
+ * The output string already includes all the required parameters, including
+ * the algorithm identifier. The string is all that has to be stored in
+ * order to verify a password.
+ */
SODIUM_EXPORT
int crypto_pwhash_str(char out[crypto_pwhash_STRBYTES],
const char * const passwd, unsigned long long passwdlen,
diff --git a/src/libsodium/include/sodium/crypto_secretstream_xchacha20poly1305.h b/src/libsodium/include/sodium/crypto_secretstream_xchacha20poly1305.h
new file mode 100644
index 00000000..9b782d3c
--- /dev/null
+++ b/src/libsodium/include/sodium/crypto_secretstream_xchacha20poly1305.h
@@ -0,0 +1,84 @@
+#ifndef crypto_secretstream_xchacha20poly1305_H
+#define crypto_secretstream_xchacha20poly1305_H
+
+#include
+
+#include "crypto_aead_xchacha20poly1305.h"
+#include "crypto_stream_chacha20.h"
+#include "export.h"
+
+#ifdef __cplusplus
+# ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wlong-long"
+# endif
+extern "C" {
+#endif
+
+#define crypto_secretstream_xchacha20poly1305_ABYTES \
+ (1U + crypto_aead_xchacha20poly1305_ietf_ABYTES)
+
+#define crypto_secretstream_xchacha20poly1305_INITBYTES \
+ crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
+
+#define crypto_secretstream_xchacha20poly1305_KEYBYTES \
+ crypto_aead_xchacha20poly1305_ietf_KEYBYTES
+
+#define crypto_secretstream_xchacha20poly1305_MESSAGESBYTES_MAX \
+ ((1ULL << 32) - 2ULL * 64ULL)
+
+#define crypto_secretstream_xchacha20poly1305_TAG_MESSAGE 0x00
+#define crypto_secretstream_xchacha20poly1305_TAG_PUSH 0x01
+#define crypto_secretstream_xchacha20poly1305_TAG_REKEY 0x02
+
+#define crypto_secretstream_xchacha20poly1305_TAG_FINAL \
+ (crypto_secretstream_xchacha20poly1305_TAG_PUSH | \
+ crypto_secretstream_xchacha20poly1305_TAG_REKEY)
+
+typedef struct crypto_secretstream_xchacha20poly1305_state {
+ unsigned char k[crypto_stream_chacha20_ietf_KEYBYTES];
+ unsigned char nonce[crypto_stream_chacha20_ietf_NONCEBYTES];
+ unsigned char _pad[8];
+} crypto_secretstream_xchacha20poly1305_state;
+
+SODIUM_EXPORT
+size_t crypto_secretstream_xchacha20poly1305_statebytes(void);
+
+SODIUM_EXPORT
+void crypto_secretstream_xchacha20poly1305_keygen
+ (unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_init_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char out[crypto_secretstream_xchacha20poly1305_INITBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_init_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ const unsigned char in[crypto_secretstream_xchacha20poly1305_INITBYTES],
+ const unsigned char k[crypto_secretstream_xchacha20poly1305_KEYBYTES]);
+
+SODIUM_EXPORT
+void crypto_secretstream_xchacha20poly1305_rekey
+ (crypto_secretstream_xchacha20poly1305_state *state);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_push
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *out, unsigned long long *outlen_p,
+ const unsigned char *m, unsigned long long mlen,
+ const unsigned char *ad, unsigned long long adlen, unsigned char tag);
+
+SODIUM_EXPORT
+int crypto_secretstream_xchacha20poly1305_pull
+ (crypto_secretstream_xchacha20poly1305_state *state,
+ unsigned char *m, unsigned long long *mlen_p, unsigned char *tag_p,
+ const unsigned char *in, unsigned long long inlen,
+ const unsigned char *ad, unsigned long long adlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/libsodium/include/sodium/utils.h b/src/libsodium/include/sodium/utils.h
index 0a7aadb4..ab00b0b1 100644
--- a/src/libsodium/include/sodium/utils.h
+++ b/src/libsodium/include/sodium/utils.h
@@ -61,6 +61,22 @@ int sodium_hex2bin(unsigned char * const bin, const size_t bin_maxlen,
const char * const ignore, size_t * const bin_len,
const char ** const hex_end);
+#define sodium_base64_VARIANT_ORIGINAL 1
+#define sodium_base64_VARIANT_ORIGINAL_NO_PADDING 3
+#define sodium_base64_VARIANT_URLSAFE 5
+#define sodium_base64_VARIANT_URLSAFE_NO_PADDING 7
+
+SODIUM_EXPORT
+char *sodium_bin2base64(char * const b64, const size_t b64_maxlen,
+ const unsigned char * const bin, const size_t bin_len,
+ const int variant);
+
+SODIUM_EXPORT
+int sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const b64, const size_t b64_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const b64_end, const int variant);
+
SODIUM_EXPORT
int sodium_mlock(void * const addr, const size_t len);
diff --git a/src/libsodium/sodium/codecs.c b/src/libsodium/sodium/codecs.c
new file mode 100644
index 00000000..7e203a5c
--- /dev/null
+++ b/src/libsodium/sodium/codecs.c
@@ -0,0 +1,315 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "core.h"
+#include "utils.h"
+
+/* Derived from original code by CodesInChaos */
+char *
+sodium_bin2hex(char *const hex, const size_t hex_maxlen,
+ const unsigned char *const bin, const size_t bin_len)
+{
+ size_t i = (size_t) 0U;
+ unsigned int x;
+ int b;
+ int c;
+
+ if (bin_len >= SIZE_MAX / 2 || hex_maxlen <= bin_len * 2U) {
+ sodium_misuse(); /* LCOV_EXCL_LINE */
+ }
+ while (i < bin_len) {
+ c = bin[i] & 0xf;
+ b = bin[i] >> 4;
+ x = (unsigned char) (87U + c + (((c - 10U) >> 8) & ~38U)) << 8 |
+ (unsigned char) (87U + b + (((b - 10U) >> 8) & ~38U));
+ hex[i * 2U] = (char) x;
+ x >>= 8;
+ hex[i * 2U + 1U] = (char) x;
+ i++;
+ }
+ hex[i * 2U] = 0U;
+
+ return hex;
+}
+
+int
+sodium_hex2bin(unsigned char *const bin, const size_t bin_maxlen,
+ const char *const hex, const size_t hex_len,
+ const char *const ignore, size_t *const bin_len,
+ const char **const hex_end)
+{
+ size_t bin_pos = (size_t) 0U;
+ size_t hex_pos = (size_t) 0U;
+ int ret = 0;
+ unsigned char c;
+ unsigned char c_acc = 0U;
+ unsigned char c_alpha0, c_alpha;
+ unsigned char c_num0, c_num;
+ unsigned char c_val;
+ unsigned char state = 0U;
+
+ while (hex_pos < hex_len) {
+ c = (unsigned char) hex[hex_pos];
+ c_num = c ^ 48U;
+ c_num0 = (c_num - 10U) >> 8;
+ c_alpha = (c & ~32U) - 55U;
+ c_alpha0 = ((c_alpha - 10U) ^ (c_alpha - 16U)) >> 8;
+ if ((c_num0 | c_alpha0) == 0U) {
+ if (ignore != NULL && state == 0U && strchr(ignore, c) != NULL) {
+ hex_pos++;
+ continue;
+ }
+ break;
+ }
+ c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
+ if (bin_pos >= bin_maxlen) {
+ ret = -1;
+ errno = ERANGE;
+ break;
+ }
+ if (state == 0U) {
+ c_acc = c_val * 16U;
+ } else {
+ bin[bin_pos++] = c_acc | c_val;
+ }
+ state = ~state;
+ hex_pos++;
+ }
+ if (state != 0U) {
+ hex_pos--;
+ }
+ if (hex_end != NULL) {
+ *hex_end = &hex[hex_pos];
+ }
+ if (ret != 0) {
+ bin_pos = (size_t) 0U;
+ }
+ if (bin_len != NULL) {
+ *bin_len = bin_pos;
+ }
+ return ret;
+}
+
+/*
+ * Some macros for constant-time comparisons. These work over values in
+ * the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
+ *
+ * Original code by Thomas Pornin.
+ */
+#define EQ(x, y) \
+ ((((0U - ((unsigned int) (x) ^ (unsigned int) (y))) >> 8) & 0xFF) ^ 0xFF)
+#define GT(x, y) ((((unsigned int) (y) - (unsigned int) (x)) >> 8) & 0xFF)
+#define GE(x, y) (GT(y, x) ^ 0xFF)
+#define LT(x, y) GT(y, x)
+#define LE(x, y) GE(y, x)
+
+static int
+b64_byte_to_char(unsigned int x)
+{
+ return (LT(x, 26) & (x + 'A')) |
+ (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
+ (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
+ (EQ(x, 63) & '/');
+}
+
+static unsigned int
+b64_char_to_byte(int c)
+{
+ const unsigned int x =
+ (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
+ (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
+ (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
+ (EQ(c, '/') & 63);
+
+ return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
+}
+
+static int
+b64_byte_to_urlsafe_char(unsigned int x)
+{
+ return (LT(x, 26) & (x + 'A')) |
+ (GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
+ (GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '-') |
+ (EQ(x, 63) & '_');
+}
+
+static unsigned int
+b64_urlsafe_char_to_byte(int c)
+{
+ const unsigned x =
+ (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
+ (GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
+ (GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '-') & 62) |
+ (EQ(c, '_') & 63);
+
+ return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
+}
+
+
+#define VARIANT_NO_PADDING_MASK 0x2U
+#define VARIANT_URLSAFE_MASK 0x4U
+
+char *
+sodium_bin2base64(char * const b64, const size_t b64_maxlen,
+ const unsigned char * const bin, const size_t bin_len,
+ const int variant)
+{
+ size_t acc_len = (size_t) 0;
+ size_t b64_len;
+ size_t b64_pos = (size_t) 0;
+ size_t bin_pos = (size_t) 0;
+ size_t nibbles;
+ size_t remainder;
+ unsigned int acc = 0U;
+
+ if ((((unsigned int) variant) & ~ 0x6U) != 0x1U) {
+ sodium_misuse();
+ }
+ nibbles = bin_len / 3;
+ remainder = bin_len - 3 * nibbles;
+ b64_len = nibbles * 4;
+ if (remainder != 0) {
+ if ((((unsigned int) variant) & VARIANT_NO_PADDING_MASK) == 0U) {
+ b64_len += 4;
+ } else {
+ b64_len += 2;
+ if (remainder == 2) {
+ b64_len++;
+ }
+ }
+ }
+ if (b64_maxlen <= b64_len) {
+ sodium_misuse();
+ }
+ if ((((unsigned int) variant) & VARIANT_URLSAFE_MASK) != 0U) {
+ while (bin_pos < bin_len) {
+ acc = (acc << 8) + bin[bin_pos++];
+ acc_len += 8;
+ while (acc_len >= 6) {
+ acc_len -= 6;
+ b64[b64_pos++] = (char) b64_byte_to_urlsafe_char((acc >> acc_len) & 0x3F);
+ }
+ }
+ if (acc_len > 0) {
+ b64[b64_pos++] = (char) b64_byte_to_urlsafe_char((acc << (6 - acc_len)) & 0x3F);
+ }
+ } else {
+ while (bin_pos < bin_len) {
+ acc = (acc << 8) + bin[bin_pos++];
+ acc_len += 8;
+ while (acc_len >= 6) {
+ acc_len -= 6;
+ b64[b64_pos++] = (char) b64_byte_to_char((acc >> acc_len) & 0x3F);
+ }
+ }
+ if (acc_len > 0) {
+ b64[b64_pos++] = (char) b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
+ }
+ }
+ assert(b64_pos <= b64_len);
+ while (b64_pos < b64_len) {
+ b64[b64_pos++] = '=';
+ }
+ b64[b64_pos++] = 0;
+
+ return b64;
+}
+
+static int
+_sodium_base642bin_skip_padding(const char * const b64, const size_t b64_len,
+ size_t * const b64_pos_p,
+ const char * const ignore, size_t padding_len)
+{
+ int c;
+
+ while (padding_len > 0) {
+ if (*b64_pos_p >= b64_len) {
+ errno = ERANGE;
+ return -1;
+ }
+ c = b64[*b64_pos_p];
+ if (c == '=') {
+ padding_len--;
+ } else if (ignore == NULL || strchr(ignore, c) == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+ (*b64_pos_p)++;
+ }
+ return 0;
+}
+
+int
+sodium_base642bin(unsigned char * const bin, const size_t bin_maxlen,
+ const char * const b64, const size_t b64_len,
+ const char * const ignore, size_t * const bin_len,
+ const char ** const b64_end, const int variant)
+{
+ size_t acc_len = (size_t) 0;
+ size_t b64_pos = (size_t) 0;
+ size_t bin_pos = (size_t) 0;
+ int is_urlsafe;
+ int ret = 0;
+ unsigned int acc = 0U;
+ unsigned int d;
+ char c;
+
+ if ((((unsigned int) variant) & ~ 0x6U) != 0x1U) {
+ sodium_misuse();
+ }
+ is_urlsafe = ((unsigned int) variant) & VARIANT_URLSAFE_MASK;
+ while (b64_pos < b64_len) {
+ c = b64[b64_pos];
+ if (is_urlsafe) {
+ d = b64_urlsafe_char_to_byte(c);
+ } else {
+ d = b64_char_to_byte(c);
+ }
+ if (d == 0xFF) {
+ if (ignore != NULL && strchr(ignore, c) != NULL) {
+ if (b64_pos >= b64_len) {
+ errno = ERANGE;
+ ret = -1;
+ break;
+ }
+ b64_pos++;
+ continue;
+ }
+ break;
+ }
+ acc = (acc << 6) + d;
+ acc_len += 6;
+ if (acc_len >= 8) {
+ acc_len -= 8;
+ if (bin_pos >= bin_maxlen) {
+ errno = ERANGE;
+ ret = -1;
+ break;
+ }
+ bin[bin_pos++] = (acc >> acc_len) & 0xFF;
+ }
+ b64_pos++;
+ }
+ if (acc_len > 4U || (acc & ((1U << acc_len) - 1U)) != 0U) {
+ ret = -1;
+ } else if (ret == 0 &&
+ (((unsigned int) variant) & VARIANT_NO_PADDING_MASK) == 0U) {
+ ret = _sodium_base642bin_skip_padding(b64, b64_len, &b64_pos, ignore,
+ acc_len / 2);
+ }
+ if (ret != 0) {
+ bin_pos = (size_t) 0U;
+ }
+ if (bin_len != NULL) {
+ *bin_len = bin_pos;
+ }
+ if (b64_end != NULL) {
+ *b64_end = &b64[b64_pos];
+ }
+ return ret;
+}
diff --git a/src/libsodium/sodium/utils.c b/src/libsodium/sodium/utils.c
index bff6e359..e430cbb9 100644
--- a/src/libsodium/sodium/utils.c
+++ b/src/libsodium/sodium/utils.c
@@ -287,89 +287,6 @@ sodium_add(unsigned char *a, const unsigned char *b, const size_t len)
}
}
-/* Derived from original code by CodesInChaos */
-char *
-sodium_bin2hex(char *const hex, const size_t hex_maxlen,
- const unsigned char *const bin, const size_t bin_len)
-{
- size_t i = (size_t) 0U;
- unsigned int x;
- int b;
- int c;
-
- if (bin_len >= SIZE_MAX / 2 || hex_maxlen <= bin_len * 2U) {
- sodium_misuse(); /* LCOV_EXCL_LINE */
- }
- while (i < bin_len) {
- c = bin[i] & 0xf;
- b = bin[i] >> 4;
- x = (unsigned char) (87U + c + (((c - 10U) >> 8) & ~38U)) << 8 |
- (unsigned char) (87U + b + (((b - 10U) >> 8) & ~38U));
- hex[i * 2U] = (char) x;
- x >>= 8;
- hex[i * 2U + 1U] = (char) x;
- i++;
- }
- hex[i * 2U] = 0U;
-
- return hex;
-}
-
-int
-sodium_hex2bin(unsigned char *const bin, const size_t bin_maxlen,
- const char *const hex, const size_t hex_len,
- const char *const ignore, size_t *const bin_len,
- const char **const hex_end)
-{
- size_t bin_pos = (size_t) 0U;
- size_t hex_pos = (size_t) 0U;
- int ret = 0;
- unsigned char c;
- unsigned char c_acc = 0U;
- unsigned char c_alpha0, c_alpha;
- unsigned char c_num0, c_num;
- unsigned char c_val;
- unsigned char state = 0U;
-
- while (hex_pos < hex_len) {
- c = (unsigned char) hex[hex_pos];
- c_num = c ^ 48U;
- c_num0 = (c_num - 10U) >> 8;
- c_alpha = (c & ~32U) - 55U;
- c_alpha0 = ((c_alpha - 10U) ^ (c_alpha - 16U)) >> 8;
- if ((c_num0 | c_alpha0) == 0U) {
- if (ignore != NULL && state == 0U && strchr(ignore, c) != NULL) {
- hex_pos++;
- continue;
- }
- break;
- }
- c_val = (c_num0 & c_num) | (c_alpha0 & c_alpha);
- if (bin_pos >= bin_maxlen) {
- ret = -1;
- errno = ERANGE;
- break;
- }
- if (state == 0U) {
- c_acc = c_val * 16U;
- } else {
- bin[bin_pos++] = c_acc | c_val;
- }
- state = ~state;
- hex_pos++;
- }
- if (state != 0U) {
- hex_pos--;
- }
- if (hex_end != NULL) {
- *hex_end = &hex[hex_pos];
- }
- if (bin_len != NULL) {
- *bin_len = bin_pos;
- }
- return ret;
-}
-
int
_sodium_alloc_init(void)
{
diff --git a/test/default/Makefile.am b/test/default/Makefile.am
index 2cda92e4..4e1d79d3 100644
--- a/test/default/Makefile.am
+++ b/test/default/Makefile.am
@@ -57,6 +57,7 @@ EXTRA_DIST = \
secretbox8.exp \
secretbox_easy.exp \
secretbox_easy2.exp \
+ secretstream.exp \
shorthash.exp \
sign.exp \
siphashx24.exp \
@@ -127,6 +128,7 @@ DISTCLEANFILES = \
secretbox8.res \
secretbox_easy.res \
secretbox_easy2.res \
+ secretstream.res \
shorthash.res \
sign.res \
siphashx24.res \
@@ -198,6 +200,7 @@ CLEANFILES = \
secretbox8.final \
secretbox_easy.final \
secretbox_easy2.final \
+ secretstream.final \
shorthash.final \
sign.final \
siphashx24.final \
@@ -264,6 +267,7 @@ CLEANFILES = \
secretbox8.nexe \
secretbox_easy.nexe \
secretbox_easy2.nexe \
+ secretstream.nexe \
shorthash.nexe \
sign.nexe \
siphashx24.nexe \
@@ -340,6 +344,7 @@ TESTS_TARGETS = \
secretbox8 \
secretbox_easy \
secretbox_easy2 \
+ secretstream \
shorthash \
sign \
sodium_core \
@@ -525,6 +530,9 @@ secretbox_easy_LDADD = $(TESTS_LDADD)
secretbox_easy2_SOURCE = cmptest.h secretbox_easy2.c
secretbox_easy2_LDADD = $(TESTS_LDADD)
+secretstream_SOURCE = cmptest.h secretstream.c
+secretstream_LDADD = $(TESTS_LDADD)
+
shorthash_SOURCE = cmptest.h shorthash.c
shorthash_LDADD = $(TESTS_LDADD)
diff --git a/test/default/secretstream.c b/test/default/secretstream.c
new file mode 100644
index 00000000..bd080667
--- /dev/null
+++ b/test/default/secretstream.c
@@ -0,0 +1,181 @@
+
+#define TEST_NAME "secretstream"
+#include "cmptest.h"
+
+int
+main(void)
+{
+ crypto_secretstream_xchacha20poly1305_state *state;
+ unsigned char *header;
+ unsigned char *k;
+ unsigned char *c1, *c2, *c3;
+ unsigned char *m1, *m2, *m3;
+ unsigned char *m1_, *m2_, *m3_;
+ size_t m1_len, m2_len, m3_len;
+ int ret;
+ unsigned char tag;
+
+ state = (crypto_secretstream_xchacha20poly1305_state *)
+ sodium_malloc(crypto_secretstream_xchacha20poly1305_statebytes());
+ header = (unsigned char *)
+ sodium_malloc(crypto_secretstream_xchacha20poly1305_INITBYTES);
+
+ m1_len = randombytes_uniform(1000);
+ m2_len = randombytes_uniform(1000);
+ m3_len = randombytes_uniform(1000);
+
+ c1 = (unsigned char *)
+ sodium_malloc(m1_len + crypto_secretstream_xchacha20poly1305_ABYTES);
+ c2 = (unsigned char *)
+ sodium_malloc(m2_len + crypto_secretstream_xchacha20poly1305_ABYTES);
+ c3 = (unsigned char *)
+ sodium_malloc(m3_len + crypto_secretstream_xchacha20poly1305_ABYTES);
+
+ m1 = (unsigned char *) sodium_malloc(m1_len);
+ m2 = (unsigned char *) sodium_malloc(m2_len);
+ m3 = (unsigned char *) sodium_malloc(m3_len);
+ m1_ = (unsigned char *) sodium_malloc(m1_len);
+ m2_ = (unsigned char *) sodium_malloc(m2_len);
+ m3_ = (unsigned char *) sodium_malloc(m3_len);
+
+ randombytes_buf(m1, m1_len);
+ memcpy(m1_, m1, m1_len);
+ randombytes_buf(m2, m2_len);
+ memcpy(m2_, m2, m2_len);
+ randombytes_buf(m3, m3_len);
+ memcpy(m3_, m3, m3_len);
+
+ k = (unsigned char *)
+ sodium_malloc(crypto_secretstream_xchacha20poly1305_KEYBYTES);
+ crypto_secretstream_xchacha20poly1305_keygen(k);
+
+ /* push */
+
+ ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c1, NULL, m1, m1_len, NULL, 0, 0);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c2, NULL, m2, m2_len, NULL, 0, 0);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c3, NULL, m3, m3_len, NULL, 0,
+ crypto_secretstream_xchacha20poly1305_TAG_FINAL);
+ assert(ret == 0);
+
+ /* pull */
+
+ ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m1, NULL, &tag,
+ c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+ assert(tag == 0);
+ assert(memcmp(m1, m1_, m1_len) == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m2, NULL, &tag,
+ c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+ assert(tag == 0);
+ assert(memcmp(m2, m2_, m2_len) == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m3, NULL, &tag,
+ c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+ assert(tag == crypto_secretstream_xchacha20poly1305_TAG_FINAL);
+ assert(memcmp(m3, m3_, m3_len) == 0);
+
+ /* previous with FINAL tag */
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m3, NULL, &tag,
+ c3, m3_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == -1);
+
+ /* previous without a tag */
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m2, NULL, &tag,
+ c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == -1);
+
+ /* without explicit rekeying */
+
+ ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
+ assert(ret == 0);
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c1, NULL, m1, m1_len, NULL, 0, 0);
+ assert(ret == 0);
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c2, NULL, m2, m2_len, NULL, 0, 0);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
+ assert(ret == 0);
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m1, NULL, &tag,
+ c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m2, NULL, &tag,
+ c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+
+ /* with explicit rekeying */
+
+ ret = crypto_secretstream_xchacha20poly1305_init_push(state, header, k);
+ assert(ret == 0);
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c1, NULL, m1, m1_len, NULL, 0, 0);
+ assert(ret == 0);
+
+ crypto_secretstream_xchacha20poly1305_rekey(state);
+
+ ret = crypto_secretstream_xchacha20poly1305_push
+ (state, c2, NULL, m2, m2_len, NULL, 0, 0);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_init_pull(state, header, k);
+ assert(ret == 0);
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m1, NULL, &tag,
+ c1, m1_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m2, NULL, &tag,
+ c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == -1);
+
+ crypto_secretstream_xchacha20poly1305_rekey(state);
+
+ ret = crypto_secretstream_xchacha20poly1305_pull
+ (state, m2, NULL, &tag,
+ c2, m2_len + crypto_secretstream_xchacha20poly1305_ABYTES, NULL, 0);
+ assert(ret == 0);
+
+ sodium_free(m3_);
+ sodium_free(m2_);
+ sodium_free(m1_);
+ sodium_free(m3);
+ sodium_free(m2);
+ sodium_free(m1);
+ sodium_free(c3);
+ sodium_free(c2);
+ sodium_free(c1);
+ sodium_free(k);
+ sodium_free(header);
+ sodium_free(state);
+
+ printf("OK\n");
+
+ return 0;
+}
diff --git a/test/default/secretstream.exp b/test/default/secretstream.exp
new file mode 100644
index 00000000..d86bac9d
--- /dev/null
+++ b/test/default/secretstream.exp
@@ -0,0 +1 @@
+OK
diff --git a/test/default/sodium_utils.c b/test/default/sodium_utils.c
index b9b93d53..09c22544 100644
--- a/test/default/sodium_utils.c
+++ b/test/default/sodium_utils.c
@@ -4,20 +4,26 @@
int
main(void)
{
- unsigned char buf_add[1000];
- unsigned char buf1[1000];
- unsigned char buf2[1000];
- unsigned char buf1_rev[1000];
- unsigned char buf2_rev[1000];
- char buf3[33];
- unsigned char buf4[4];
- unsigned char nonce[24];
- char nonce_hex[49];
- const char * hex;
- const char * hex_end;
- size_t bin_len;
- unsigned int i;
- unsigned int j;
+ unsigned char buf_add[1000];
+ unsigned char buf1[1000];
+ unsigned char buf2[1000];
+ unsigned char buf1_rev[1000];
+ unsigned char buf2_rev[1000];
+ char buf3[33];
+ unsigned char buf4[4];
+ unsigned char nonce[24];
+ char nonce_hex[49];
+ const char *b64;
+ char *b64_;
+ const char *b64_end;
+ unsigned char *bin;
+ const char *hex;
+ const char *hex_end;
+ size_t b64_len;
+ size_t bin_len;
+ size_t hex_len;
+ unsigned int i;
+ unsigned int j;
randombytes_buf(buf1, sizeof buf1);
memcpy(buf2, buf1, sizeof buf2);
@@ -41,8 +47,8 @@ main(void)
hex = "Cafe : 6942";
sodium_hex2bin(buf4, sizeof buf4, hex, strlen(hex), ": ", &bin_len, NULL);
- printf("%lu:%02x%02x%02x%02x\n", (unsigned long) bin_len, buf4[2], buf4[3],
- buf4[2], buf4[3]);
+ printf("%lu:%02x%02x%02x%02x\n", (unsigned long) bin_len,
+ buf4[2], buf4[3], buf4[2], buf4[3]);
hex = "deadbeef";
if (sodium_hex2bin(buf1, 1U, hex, 8U, NULL, &bin_len, &hex_end) != -1) {
@@ -72,6 +78,97 @@ main(void)
}
printf("dt5: %ld\n", (long) (hex_end - hex));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 31U, (const unsigned char *) "\xfb\xf0\xf1" "0123456789ABCDEFab",
+ 21U, sodium_base64_VARIANT_ORIGINAL));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 33U, (const unsigned char *) "\xfb\xf0\xf1" "0123456789ABCDEFabc",
+ 22U, sodium_base64_VARIANT_ORIGINAL_NO_PADDING));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 31U, (const unsigned char *) "\xfb\xf0\xf1" "0123456789ABCDEFab",
+ 21U, sodium_base64_VARIANT_URLSAFE));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 33U, (const unsigned char *) "\xfb\xf0\xf1" "0123456789ABCDEFabc",
+ 22U, sodium_base64_VARIANT_URLSAFE_NO_PADDING));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 1U, NULL,
+ 0U, sodium_base64_VARIANT_ORIGINAL));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 5U, (const unsigned char *) "a",
+ 1U, sodium_base64_VARIANT_ORIGINAL));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 5U, (const unsigned char *) "ab",
+ 2U, sodium_base64_VARIANT_ORIGINAL));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 5U, (const unsigned char *) "abc",
+ 3U, sodium_base64_VARIANT_ORIGINAL));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 1U, NULL,
+ 0U, sodium_base64_VARIANT_ORIGINAL_NO_PADDING));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 3U, (const unsigned char *) "a",
+ 1U, sodium_base64_VARIANT_ORIGINAL_NO_PADDING));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 4U, (const unsigned char *) "ab",
+ 2U, sodium_base64_VARIANT_ORIGINAL_NO_PADDING));
+ printf("%s\n",
+ sodium_bin2base64(buf3, 5U, (const unsigned char *) "abc",
+ 3U, sodium_base64_VARIANT_ORIGINAL_NO_PADDING));
+
+ b64 = "VGhpcyBpcyBhIGpvdXJu" "\n" "ZXkgaW50by" " " "Bzb3VuZA==";
+ memset(buf4, '*', sizeof buf4);
+ assert(sodium_base642bin(buf4, sizeof buf4, b64, strlen(b64), "\n\r ", &bin_len,
+ &b64_end, sodium_base64_VARIANT_ORIGINAL) == -1);
+ buf4[bin_len] = 0;
+ printf("[%s]\n", (const char *) buf4);
+ printf("[%s]\n", b64_end);
+
+ memset(buf1, '*', sizeof buf1);
+ sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), "\n\r ", &bin_len,
+ &b64_end, sodium_base64_VARIANT_ORIGINAL);
+ buf1[bin_len] = 0;
+ printf("[%s]\n", (const char *) buf1);
+ assert(*b64_end == 0);
+
+ memset(buf1, '*', sizeof buf1);
+ sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), NULL, &bin_len,
+ &b64_end, sodium_base64_VARIANT_ORIGINAL);
+ buf1[bin_len] = 0;
+ printf("[%s]\n", (const char *) buf1);
+ printf("[%s]\n", b64_end);
+
+ assert(sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), NULL, NULL,
+ NULL, sodium_base64_VARIANT_ORIGINAL) == 0);
+
+ assert(sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), NULL, NULL,
+ NULL, sodium_base64_VARIANT_ORIGINAL_NO_PADDING) == 0);
+ assert(sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), " \r\n", NULL,
+ NULL, sodium_base64_VARIANT_ORIGINAL_NO_PADDING) == 0);
+ assert(sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), NULL, NULL,
+ NULL, sodium_base64_VARIANT_URLSAFE_NO_PADDING) == 0);
+ assert(sodium_base642bin(buf1, sizeof buf1, b64, strlen(b64), " \r\n", NULL,
+ NULL, sodium_base64_VARIANT_URLSAFE_NO_PADDING) == 0);
+
+ for (i = 0; i < 1000; i++) {
+ assert(sizeof buf1 >= 100);
+ bin_len = (size_t) randombytes_uniform(100);
+ bin = (unsigned char *) sodium_malloc(bin_len);
+ b64_len = 1 + (bin_len + 2) / 3 * 4;
+ b64_ = (char *) sodium_malloc(b64_len);
+ randombytes_buf(bin, bin_len);
+ memcpy(buf1, bin, bin_len);
+ b64 = sodium_bin2base64(b64_, b64_len + 10, bin, bin_len,
+ sodium_base64_VARIANT_URLSAFE);
+ assert(b64 != NULL);
+ assert(sodium_base642bin(bin, bin_len + 10, b64, b64_len,
+ NULL, NULL, &b64_end,
+ sodium_base64_VARIANT_URLSAFE) == 0);
+ assert(b64_end == &b64[b64_len - 1]);
+ assert(memcmp(bin, buf1, bin_len) == 0);
+ sodium_free(bin);
+ sodium_free(b64_);
+ }
+
memset(nonce, 0, sizeof nonce);
sodium_increment(nonce, sizeof nonce);
printf("%s\n",
diff --git a/test/default/sodium_utils.exp b/test/default/sodium_utils.exp
index 030a1cb3..233dc687 100644
--- a/test/default/sodium_utils.exp
+++ b/test/default/sodium_utils.exp
@@ -11,6 +11,25 @@ dt2: 2
dt3: 11
dt4: 11
dt5: 11
++/DxMDEyMzQ1Njc4OUFCQ0RFRmFi
++/DxMDEyMzQ1Njc4OUFCQ0RFRmFiYw
+-_DxMDEyMzQ1Njc4OUFCQ0RFRmFi
+-_DxMDEyMzQ1Njc4OUFCQ0RFRmFiYw
+
+YQ==
+YWI=
+YWJj
+
+YQ
+YWI
+YWJj
+[]
+[BpcyBhIGpvdXJu
+ZXkgaW50by Bzb3VuZA==]
+[This is a journey into sound]
+[This is a journ]
+[
+ZXkgaW50by Bzb3VuZA==]
010000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000
010100000000000000000000000000000000000000000000