diff options
Diffstat (limited to 'libs/libtox/src/toxencryptsave')
21 files changed, 3222 insertions, 0 deletions
diff --git a/libs/libtox/src/toxencryptsave/Makefile.inc b/libs/libtox/src/toxencryptsave/Makefile.inc new file mode 100644 index 0000000000..bde026cdaf --- /dev/null +++ b/libs/libtox/src/toxencryptsave/Makefile.inc @@ -0,0 +1,55 @@ +lib_LTLIBRARIES += libtoxencryptsave.la + +libtoxencryptsave_la_include_HEADERS = \ + ../toxencryptsave/toxencryptsave.h + +libtoxencryptsave_la_includedir = $(includedir)/tox + +libtoxencryptsave_la_SOURCES = ../toxencryptsave/toxencryptsave.h \ + ../toxencryptsave/toxencryptsave.c \ + ../toxencryptsave/defines.h + + +if WITH_NACL +libtoxencryptsave_la_SOURCES += ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c \ + ../toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c +endif + +libtoxencryptsave_la_CFLAGS = -I$(top_srcdir) \ + -I$(top_srcdir)/toxcore \ + $(LIBSODIUM_CFLAGS) \ + $(NACL_CFLAGS) \ + $(PTHREAD_CFLAGS) + +libtoxencryptsave_la_LDFLAGS = $(LT_LDFLAGS) \ + $(EXTRA_LT_LDFLAGS) \ + $(LIBSODIUM_LDFLAGS) \ + $(NACL_LDFLAGS) \ + $(MATH_LDFLAGS) \ + $(RT_LIBS) \ + $(WINSOCK2_LIBS) + +libtoxencryptsave_la_LIBADD = $(LIBSODIUM_LIBS) \ + $(NACL_OBJECTS) \ + $(NAC_LIBS) \ + $(PTHREAD_LIBS) \ + libtoxcore.la + +if SET_SO_VERSION + +EXTRA_libtoxencryptsave_la_DEPENDENCIES = ../so.version + +endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h new file mode 100644 index 0000000000..5cb32f8dcf --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h @@ -0,0 +1,92 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifndef crypto_pwhash_scryptsalsa208sha256_H +#define crypto_pwhash_scryptsalsa208sha256_H + +#include <stddef.h> +#include <stdint.h> + +#include "export.h" + +#ifdef __cplusplus +# if __GNUC__ +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +extern "C" { +#endif + +#define crypto_pwhash_scryptsalsa208sha256_SALTBYTES 32U +SODIUM_EXPORT +size_t crypto_pwhash_scryptsalsa208sha256_saltbytes(void); + +#define crypto_pwhash_scryptsalsa208sha256_STRBYTES 102U +SODIUM_EXPORT +size_t crypto_pwhash_scryptsalsa208sha256_strbytes(void); + +#define crypto_pwhash_scryptsalsa208sha256_STRPREFIX "$7$" +SODIUM_EXPORT +const char *crypto_pwhash_scryptsalsa208sha256_strprefix(void); + +#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE 524288ULL +SODIUM_EXPORT +size_t crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void); + +#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE 16777216ULL +SODIUM_EXPORT +size_t crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void); + +#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 33554432ULL +SODIUM_EXPORT +size_t crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void); + +#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 1073741824ULL +SODIUM_EXPORT +size_t crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void); + +SODIUM_EXPORT +int crypto_pwhash_scryptsalsa208sha256(unsigned char * const out, + unsigned long long outlen, + const char * const passwd, + unsigned long long passwdlen, + const unsigned char * const salt, + unsigned long long opslimit, + size_t memlimit); + +SODIUM_EXPORT +int crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], + const char * const passwd, + unsigned long long passwdlen, + unsigned long long opslimit, + size_t memlimit); + +SODIUM_EXPORT +int crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], + const char * const passwd, + unsigned long long passwdlen); + +SODIUM_EXPORT +int crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen, + const uint8_t * salt, size_t saltlen, + uint64_t N, uint32_t r, uint32_t p, + uint8_t * buf, size_t buflen); + +#ifdef __cplusplus +} +#endif + +/* Backward compatibility with version 0.5.0 */ + +#define crypto_pwhash_scryptxsalsa208sha256_SALTBYTES crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#define crypto_pwhash_scryptxsalsa208sha256_saltbytes crypto_pwhash_scryptsalsa208sha256_saltbytes +#define crypto_pwhash_scryptxsalsa208sha256_STRBYTES crypto_pwhash_scryptsalsa208sha256_STRBYTES +#define crypto_pwhash_scryptxsalsa208sha256_strbytes crypto_pwhash_scryptsalsa208sha256_strbytes +#define crypto_pwhash_scryptxsalsa208sha256 crypto_pwhash_scryptsalsa208sha256 +#define crypto_pwhash_scryptxsalsa208sha256_str crypto_pwhash_scryptsalsa208sha256_str +#define crypto_pwhash_scryptxsalsa208sha256_str_verify crypto_pwhash_scryptsalsa208sha256_str_verify + +#endif + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c new file mode 100644 index 0000000000..5a5c5525f3 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt-common.c @@ -0,0 +1,257 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2013 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdint.h> +#include <string.h> + +#include "crypto_pwhash_scryptsalsa208sha256.h" +#include "crypto_scrypt.h" +#include "runtime.h" +#include "utils.h" + +static const char * const itoa64 = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static uint8_t * +encode64_uint32(uint8_t * dst, size_t dstlen, uint32_t src, uint32_t srcbits) +{ + uint32_t bit; + + for (bit = 0; bit < srcbits; bit += 6) { + if (dstlen < 1) { + return NULL; + } + *dst++ = itoa64[src & 0x3f]; + dstlen--; + src >>= 6; + } + + return dst; +} + +static uint8_t * +encode64(uint8_t * dst, size_t dstlen, const uint8_t * src, size_t srclen) +{ + size_t i; + + for (i = 0; i < srclen; ) { + uint8_t * dnext; + uint32_t value = 0, bits = 0; + do { + value |= (uint32_t)src[i++] << bits; + bits += 8; + } while (bits < 24 && i < srclen); + dnext = encode64_uint32(dst, dstlen, value, bits); + if (!dnext) { + return NULL; + } + dstlen -= dnext - dst; + dst = dnext; + } + + return dst; +} + +static int +decode64_one(uint32_t * dst, uint8_t src) +{ + const char *ptr = strchr(itoa64, src); + + if (ptr) { + *dst = ptr - itoa64; + return 0; + } + *dst = 0; + return -1; +} + +static const uint8_t * +decode64_uint32(uint32_t * dst, uint32_t dstbits, const uint8_t * src) +{ + uint32_t bit; + uint32_t value; + + value = 0; + for (bit = 0; bit < dstbits; bit += 6) { + uint32_t one; + if (decode64_one(&one, *src)) { + *dst = 0; + return NULL; + } + src++; + value |= one << bit; + } + + *dst = value; + return src; +} + +uint8_t * +escrypt_r(escrypt_local_t * local, const uint8_t * passwd, size_t passwdlen, + const uint8_t * setting, uint8_t * buf, size_t buflen) +{ + uint8_t hash[crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES]; + escrypt_kdf_t escrypt_kdf; + const uint8_t *src; + const uint8_t *salt; + uint8_t *dst; + size_t prefixlen; + size_t saltlen; + size_t need; + uint64_t N; + uint32_t N_log2; + uint32_t r; + uint32_t p; + + if (setting[0] != '$' || setting[1] != '7' || setting[2] != '$') { + return NULL; + } + src = setting + 3; + + if (decode64_one(&N_log2, *src)) { + return NULL; + } + src++; + N = (uint64_t)1 << N_log2; + + src = decode64_uint32(&r, 30, src); + if (!src) { + return NULL; + } + src = decode64_uint32(&p, 30, src); + if (!src) { + return NULL; + } + prefixlen = src - setting; + + salt = src; + src = (uint8_t *) strrchr((char *)salt, '$'); + if (src) { + saltlen = src - salt; + } else { + saltlen = strlen((char *)salt); + } + need = prefixlen + saltlen + 1 + + crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1; + if (need > buflen || need < saltlen) { + return NULL; + } +#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER) + escrypt_kdf = + sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse; +#else + escrypt_kdf = escrypt_kdf_nosse; +#endif + if (escrypt_kdf(local, passwd, passwdlen, salt, saltlen, + N, r, p, hash, sizeof(hash))) { + return NULL; + } + + dst = buf; + memcpy(dst, setting, prefixlen + saltlen); + dst += prefixlen + saltlen; + *dst++ = '$'; + + dst = encode64(dst, buflen - (dst - buf), hash, sizeof(hash)); + sodium_memzero(hash, sizeof hash); + if (!dst || dst >= buf + buflen) { /* Can't happen */ + return NULL; + } + *dst = 0; /* NUL termination */ + + return buf; +} + +uint8_t * +escrypt_gensalt_r(uint32_t N_log2, uint32_t r, uint32_t p, + const uint8_t * src, size_t srclen, + uint8_t * buf, size_t buflen) +{ + uint8_t *dst; + size_t prefixlen = + (sizeof "$7$" - 1U) + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */); + size_t saltlen = BYTES2CHARS(srclen); + size_t need; + + need = prefixlen + saltlen + 1; + if (need > buflen || need < saltlen || saltlen < srclen) { + return NULL; + } + if (N_log2 > 63 || ((uint64_t)r * (uint64_t)p >= (1U << 30))) { + return NULL; + } + dst = buf; + *dst++ = '$'; + *dst++ = '7'; + *dst++ = '$'; + + *dst++ = itoa64[N_log2]; + + dst = encode64_uint32(dst, buflen - (dst - buf), r, 30); + if (!dst) { /* Can't happen */ + return NULL; + } + dst = encode64_uint32(dst, buflen - (dst - buf), p, 30); + if (!dst) { /* Can't happen */ + return NULL; + } + dst = encode64(dst, buflen - (dst - buf), src, srclen); + if (!dst || dst >= buf + buflen) { /* Can't happen */ + return NULL; + } + *dst = 0; /* NUL termination */ + + return buf; +} + +int +crypto_pwhash_scryptsalsa208sha256_ll(const uint8_t * passwd, size_t passwdlen, + const uint8_t * salt, size_t saltlen, + uint64_t N, uint32_t r, uint32_t p, + uint8_t * buf, size_t buflen) +{ + escrypt_kdf_t escrypt_kdf; + escrypt_local_t local; + int retval; + + if (escrypt_init_local(&local)) { + return -1; + } +#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER) + escrypt_kdf = + sodium_runtime_has_sse2() ? escrypt_kdf_sse : escrypt_kdf_nosse; +#else + escrypt_kdf = escrypt_kdf_nosse; +#endif + retval = escrypt_kdf(&local, + passwd, passwdlen, salt, saltlen, + N, r, p, buf, buflen); + if (escrypt_free_local(&local)) { + return -1; + } + return retval; +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h new file mode 100644 index 0000000000..3f0b7d72f5 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/crypto_scrypt.h @@ -0,0 +1,93 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2009 Colin Percival + * Copyright 2013 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ +#ifndef _CRYPTO_SCRYPT_H_ +#define _CRYPTO_SCRYPT_H_ + +#include <stdint.h> + +#define crypto_pwhash_scryptsalsa208sha256_STRPREFIXBYTES 14 +#define crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES 57 +#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES 32 +#define crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES_ENCODED 43 +#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES 32 +#define crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED 43 + +#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6) + +typedef struct { + void * base, * aligned; + size_t size; +} escrypt_region_t; + +typedef escrypt_region_t escrypt_local_t; + +extern int escrypt_init_local(escrypt_local_t * __local); + +extern int escrypt_free_local(escrypt_local_t * __local); + +extern void *alloc_region(escrypt_region_t * region, size_t size); +extern int free_region(escrypt_region_t * region); + +typedef int (*escrypt_kdf_t)(escrypt_local_t * __local, + const uint8_t * __passwd, size_t __passwdlen, + const uint8_t * __salt, size_t __saltlen, + uint64_t __N, uint32_t __r, uint32_t __p, + uint8_t * __buf, size_t __buflen); + +extern int escrypt_kdf_nosse(escrypt_local_t * __local, + const uint8_t * __passwd, size_t __passwdlen, + const uint8_t * __salt, size_t __saltlen, + uint64_t __N, uint32_t __r, uint32_t __p, + uint8_t * __buf, size_t __buflen); + +extern int escrypt_kdf_sse(escrypt_local_t * __local, + const uint8_t * __passwd, size_t __passwdlen, + const uint8_t * __salt, size_t __saltlen, + uint64_t __N, uint32_t __r, uint32_t __p, + uint8_t * __buf, size_t __buflen); + +extern uint8_t * escrypt_r(escrypt_local_t * __local, + const uint8_t * __passwd, size_t __passwdlen, + const uint8_t * __setting, + uint8_t * __buf, size_t __buflen); + +extern uint8_t * escrypt_gensalt_r( + uint32_t __N_log2, uint32_t __r, uint32_t __p, + const uint8_t * __src, size_t __srclen, + uint8_t * __buf, size_t __buflen); + +#endif /* !_CRYPTO_SCRYPT_H_ */ + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h new file mode 100644 index 0000000000..ee5b30f7f1 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/export.h @@ -0,0 +1,38 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifndef __SODIUM_EXPORT_H__ +#define __SODIUM_EXPORT_H__ + +#ifndef __GNUC__ +# ifdef __attribute__ +# undef __attribute__ +# endif +# define __attribute__(a) +#endif + +#ifdef SODIUM_STATIC +# define SODIUM_EXPORT +#else +# if defined(_MSC_VER) +# ifdef DLL_EXPORT +# define SODIUM_EXPORT __declspec(dllexport) +# else +# define SODIUM_EXPORT __declspec(dllimport) +# endif +# else +# if defined(__SUNPRO_C) +# define SODIUM_EXPORT __attribute__ __global +# elif defined(_MSG_VER) +# define SODIUM_EXPORT extern __declspec(dllexport) +# else +# define SODIUM_EXPORT __attribute__ ((visibility ("default"))) +# endif +# endif +#endif + +#endif + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c new file mode 100644 index 0000000000..97d9ba6878 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c @@ -0,0 +1,309 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2009 Colin Percival + * Copyright 2013 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ + +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "../pbkdf2-sha256.h" +#include "../sysendian.h" +#include "../crypto_scrypt.h" + +static inline void +blkcpy(void * dest, const void * src, size_t len) +{ + size_t * D = (size_t *) dest; + const size_t * S = (const size_t *) src; + size_t L = len / sizeof(size_t); + size_t i; + + for (i = 0; i < L; i++) + D[i] = S[i]; +} + +static inline void +blkxor(void * dest, const void * src, size_t len) +{ + size_t * D = (size_t *) dest; + const size_t * S = (const size_t *) src; + size_t L = len / sizeof(size_t); + size_t i; + + for (i = 0; i < L; i++) + D[i] ^= S[i]; +} + +/** + * salsa20_8(B): + * Apply the salsa20/8 core to the provided block. + */ +static void +salsa20_8(uint32_t B[16]) +{ + uint32_t x[16]; + size_t i; + + blkcpy(x, B, 64); + for (i = 0; i < 8; i += 2) { +#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) + /* Operate on columns. */ + x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); + x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); + + x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); + x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); + + x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); + x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); + + x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); + x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); + + /* Operate on rows. */ + x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); + x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); + + x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); + x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); + + x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); + x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); + + x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); + x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); +#undef R + } + for (i = 0; i < 16; i++) + B[i] += x[i]; +} + +/** + * blockmix_salsa8(Bin, Bout, X, r): + * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r + * bytes in length; the output Bout must also be the same size. The + * temporary space X must be 64 bytes. + */ +static void +blockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) +{ + size_t i; + + /* 1: X <-- B_{2r - 1} */ + blkcpy(X, &Bin[(2 * r - 1) * 16], 64); + + /* 2: for i = 0 to 2r - 1 do */ + for (i = 0; i < 2 * r; i += 2) { + /* 3: X <-- H(X \xor B_i) */ + blkxor(X, &Bin[i * 16], 64); + salsa20_8(X); + + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + blkcpy(&Bout[i * 8], X, 64); + + /* 3: X <-- H(X \xor B_i) */ + blkxor(X, &Bin[i * 16 + 16], 64); + salsa20_8(X); + + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + blkcpy(&Bout[i * 8 + r * 16], X, 64); + } +} + +/** + * integerify(B, r): + * Return the result of parsing B_{2r-1} as a little-endian integer. + */ +static inline uint64_t +integerify(const void * B, size_t r) +{ + const uint32_t * X = (const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64); + + return (((uint64_t)(X[1]) << 32) + X[0]); +} + +/** + * smix(B, r, N, V, XY): + * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; + * the temporary storage V must be 128rN bytes in length; the temporary + * storage XY must be 256r + 64 bytes in length. The value N must be a + * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a + * multiple of 64 bytes. + */ +static void +smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY) +{ + uint32_t * X = XY; + uint32_t * Y = &XY[32 * r]; + uint32_t * Z = &XY[64 * r]; + uint64_t i; + uint64_t j; + size_t k; + + /* 1: X <-- B */ + for (k = 0; k < 32 * r; k++) + X[k] = le32dec(&B[4 * k]); + + /* 2: for i = 0 to N - 1 do */ + for (i = 0; i < N; i += 2) { + /* 3: V_i <-- X */ + blkcpy(&V[i * (32 * r)], X, 128 * r); + + /* 4: X <-- H(X) */ + blockmix_salsa8(X, Y, Z, r); + + /* 3: V_i <-- X */ + blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); + + /* 4: X <-- H(X) */ + blockmix_salsa8(Y, X, Z, r); + } + + /* 6: for i = 0 to N - 1 do */ + for (i = 0; i < N; i += 2) { + /* 7: j <-- Integerify(X) mod N */ + j = integerify(X, r) & (N - 1); + + /* 8: X <-- H(X \xor V_j) */ + blkxor(X, &V[j * (32 * r)], 128 * r); + blockmix_salsa8(X, Y, Z, r); + + /* 7: j <-- Integerify(X) mod N */ + j = integerify(Y, r) & (N - 1); + + /* 8: X <-- H(X \xor V_j) */ + blkxor(Y, &V[j * (32 * r)], 128 * r); + blockmix_salsa8(Y, X, Z, r); + } + /* 10: B' <-- X */ + for (k = 0; k < 32 * r; k++) + le32enc(&B[4 * k], X[k]); +} + +/** + * escrypt_kdf(local, passwd, passwdlen, salt, saltlen, + * N, r, p, buf, buflen): + * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, + * p, buflen) and write the result into buf. The parameters r, p, and buflen + * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N + * must be a power of 2 greater than 1. + * + * Return 0 on success; or -1 on error. + */ +int +escrypt_kdf_nosse(escrypt_local_t * local, + const uint8_t * passwd, size_t passwdlen, + const uint8_t * salt, size_t saltlen, + uint64_t N, uint32_t _r, uint32_t _p, + uint8_t * buf, size_t buflen) +{ + size_t B_size, V_size, XY_size, need; + uint8_t * B; + uint32_t * V, * XY; + size_t r = _r, p = _p; + uint32_t i; + + /* Sanity-check parameters. */ +#if SIZE_MAX > UINT32_MAX + if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { + errno = EFBIG; + return -1; + } +#endif + if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { + errno = EFBIG; + return -1; + } + if (((N & (N - 1)) != 0) || (N < 2)) { + errno = EINVAL; + return -1; + } + if (r == 0 || p == 0) { + errno = EINVAL; + return -1; + } + if ((r > SIZE_MAX / 128 / p) || +#if SIZE_MAX / 256 <= UINT32_MAX + (r > SIZE_MAX / 256) || +#endif + (N > SIZE_MAX / 128 / r)) { + errno = ENOMEM; + return -1; + } + + /* Allocate memory. */ + B_size = (size_t)128 * r * p; + V_size = (size_t)128 * r * N; + need = B_size + V_size; + if (need < V_size) { + errno = ENOMEM; + return -1; + } + XY_size = (size_t)256 * r + 64; + need += XY_size; + if (need < XY_size) { + errno = ENOMEM; + return -1; + } + if (local->size < need) { + if (free_region(local)) + return -1; + if (!alloc_region(local, need)) + return -1; + } + B = (uint8_t *)local->aligned; + V = (uint32_t *)((uint8_t *)B + B_size); + XY = (uint32_t *)((uint8_t *)V + V_size); + + /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ + PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size); + + /* 2: for i = 0 to p - 1 do */ + for (i = 0; i < p; i++) { + /* 3: B_i <-- MF(B_i, N) */ + smix(&B[(size_t)128 * i * r], r, N, V, XY); + } + + /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ + PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen); + + /* Success! */ + return 0; +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt new file mode 100644 index 0000000000..66bbfe2db9 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/note_to_maintainers.txt @@ -0,0 +1,14 @@ +This folder is only meant for use with nacl, i.e. when sodium is unavailable. + + +The files in this folder were mostly copied from +https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/crypto_pwhash/scryptsalsa208sha256, +with #ifdef VANILLA_NACL added around each of them as required for this module. + +export.h, utils.h, and runtime.h were copied from +https://github.com/jedisct1/libsodium/tree/0.7.0/src/libsodium/include/sodium. +utils.h was significantly truncated. + +utils.c and runtime.c were copied from +https://github.com/jedisct1/libsodium/blob/0.7.0/src/libsodium/sodium. +utils.c was also significantly truncated. diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c new file mode 100644 index 0000000000..3dfe54db5f --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.c @@ -0,0 +1,97 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2005,2007,2009 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/types.h> + +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <crypto_hash_sha256.h> +#include <crypto_auth_hmacsha256.h> + +#include "pbkdf2-sha256.h" +#include "sysendian.h" +#include "utils.h" + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void +PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt, + size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen) +{ + uint8_t key[32] = {0}; + size_t i; + uint8_t salt_and_ivec[saltlen + 4]; + uint8_t U[32]; + uint8_t T[32]; + uint64_t j; + int k; + size_t clen; + + if (passwdlen > 32) { + /* For some reason libsodium allows 64byte keys meaning keys + * between 32byte and 64bytes are not compatible with libsodium. + toxencryptsave should only give 32byte passwds so this isn't an issue here.*/ + crypto_hash_sha256(key, passwd, passwdlen); + } else { + memcpy(key, passwd, passwdlen); + } + + memcpy(salt_and_ivec, salt, saltlen); + + for (i = 0; i * 32 < dkLen; i++) { + be32enc(salt_and_ivec + saltlen, (uint32_t)(i + 1)); + crypto_auth_hmacsha256(U, salt_and_ivec, sizeof(salt_and_ivec), key); + + memcpy(T, U, 32); + + for (j = 2; j <= c; j++) { + crypto_auth_hmacsha256(U, U, 32, key); + + for (k = 0; k < 32; k++) { + T[k] ^= U[k]; + } + } + + clen = dkLen - i * 32; + if (clen > 32) { + clen = 32; + } + memcpy(&buf[i * 32], T, clen); + } + sodium_memzero((void *) key, sizeof(key)); +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h new file mode 100644 index 0000000000..b74bc6a340 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pbkdf2-sha256.h @@ -0,0 +1,52 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2005,2007,2009 Colin Percival + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _SHA256_H_ +#define _SHA256_H_ + +#include <sys/types.h> + +#include <stdint.h> + +#include "crypto_auth_hmacsha256.h" + +/** + * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen): + * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and + * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1). + */ +void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t, + uint64_t, uint8_t *, size_t); + +#endif /* !_SHA256_H_ */ + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c new file mode 100644 index 0000000000..52c51abc3b --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c @@ -0,0 +1,211 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#include <errno.h> +#include <limits.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h> +//#include <stdio.h> + +#include "crypto_pwhash_scryptsalsa208sha256.h" +#include "crypto_scrypt.h" +#include "randombytes.h" +#include "utils.h" + +#define SETTING_SIZE(saltbytes) \ + (sizeof "$7$" - 1U) + \ + (1U /* N_log2 */) + (5U /* r */) + (5U /* p */) + BYTES2CHARS(saltbytes) + +static int +pickparams(unsigned long long opslimit, const size_t memlimit, + uint32_t * const N_log2, uint32_t * const p, uint32_t * const r) +{ + unsigned long long maxN; + unsigned long long maxrp; + + if (opslimit < 32768) { + opslimit = 32768; + } + *r = 8; + if (opslimit < memlimit / 32) { + *p = 1; + maxN = opslimit / (*r * 4); + for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { + if ((uint64_t)(1) << *N_log2 > maxN / 2) { + break; + } + } + } else { + maxN = memlimit / (*r * 128); + for (*N_log2 = 1; *N_log2 < 63; *N_log2 += 1) { + if ((uint64_t) (1) << *N_log2 > maxN / 2) { + break; + } + } + maxrp = (opslimit / 4) / ((uint64_t) (1) << *N_log2); + if (maxrp > 0x3fffffff) { + maxrp = 0x3fffffff; + } + *p = (uint32_t) (maxrp) / *r; + } + return 0; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_saltbytes(void) +{ + return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_strbytes(void) +{ + return crypto_pwhash_scryptsalsa208sha256_STRBYTES; +} + +const char * +crypto_pwhash_scryptsalsa208sha256_strprefix(void) +{ + return crypto_pwhash_scryptsalsa208sha256_STRPREFIX; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_opslimit_interactive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_memlimit_interactive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE; +} + +size_t +crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive(void) +{ + return crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE; +} + +int +crypto_pwhash_scryptsalsa208sha256(unsigned char * const out, + unsigned long long outlen, + const char * const passwd, + unsigned long long passwdlen, + const unsigned char * const salt, + unsigned long long opslimit, + size_t memlimit) +{ + //fprintf(stderr, "Doing that dirty thang!!!!\n"); + uint32_t N_log2; + uint32_t p; + uint32_t r; + + memset(out, 0, outlen); + if (passwdlen > SIZE_MAX || outlen > SIZE_MAX) { + errno = EFBIG; + return -1; + } + if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { + errno = EINVAL; + return -1; + } + return crypto_pwhash_scryptsalsa208sha256_ll((const uint8_t *) passwd, + (size_t) passwdlen, + (const uint8_t *) salt, + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, + (uint64_t) (1) << N_log2, r, p, + out, (size_t) outlen); +} + +int +crypto_pwhash_scryptsalsa208sha256_str(char out[crypto_pwhash_scryptsalsa208sha256_STRBYTES], + const char * const passwd, + unsigned long long passwdlen, + unsigned long long opslimit, + size_t memlimit) +{ + uint8_t salt[crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES]; + char setting[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U]; + escrypt_local_t escrypt_local; + uint32_t N_log2; + uint32_t p; + uint32_t r; + + memset(out, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES); + if (passwdlen > SIZE_MAX) { + errno = EFBIG; + return -1; + } + if (pickparams(opslimit, memlimit, &N_log2, &p, &r) != 0) { + errno = EINVAL; + return -1; + } + randombytes(salt, sizeof salt); + if (escrypt_gensalt_r(N_log2, r, p, salt, sizeof salt, + (uint8_t *) setting, sizeof setting) == NULL) { + errno = EINVAL; + return -1; + } + if (escrypt_init_local(&escrypt_local) != 0) { + return -1; + } + if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, + (const uint8_t *) setting, (uint8_t *) out, + crypto_pwhash_scryptsalsa208sha256_STRBYTES) == NULL) { + escrypt_free_local(&escrypt_local); + errno = EINVAL; + return -1; + } + escrypt_free_local(&escrypt_local); + + (void) sizeof + (int[SETTING_SIZE(crypto_pwhash_scryptsalsa208sha256_STRSALTBYTES) + == crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES ? 1 : -1]); + (void) sizeof + (int[crypto_pwhash_scryptsalsa208sha256_STRSETTINGBYTES + 1U + + crypto_pwhash_scryptsalsa208sha256_STRHASHBYTES_ENCODED + 1U + == crypto_pwhash_scryptsalsa208sha256_STRBYTES ? 1 : -1]); + + return 0; +} + +int +crypto_pwhash_scryptsalsa208sha256_str_verify(const char str[crypto_pwhash_scryptsalsa208sha256_STRBYTES], + const char * const passwd, + unsigned long long passwdlen) +{ + char wanted[crypto_pwhash_scryptsalsa208sha256_STRBYTES]; + escrypt_local_t escrypt_local; + int ret = -1; + + if (memchr(str, 0, crypto_pwhash_scryptsalsa208sha256_STRBYTES) != + &str[crypto_pwhash_scryptsalsa208sha256_STRBYTES - 1U]) { + return -1; + } + if (escrypt_init_local(&escrypt_local) != 0) { + return -1; + } + if (escrypt_r(&escrypt_local, (const uint8_t *) passwd, (size_t) passwdlen, + (const uint8_t *) str, (uint8_t *) wanted, + sizeof wanted) == NULL) { + escrypt_free_local(&escrypt_local); + return -1; + } + escrypt_free_local(&escrypt_local); + ret = sodium_memcmp(wanted, str, sizeof wanted); + sodium_memzero(wanted, sizeof wanted); + + return ret; +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c new file mode 100644 index 0000000000..9b5c513193 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.c @@ -0,0 +1,140 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifdef HAVE_ANDROID_GETCPUFEATURES +# include <cpu-features.h> +#endif + +#include "runtime.h" + +typedef struct CPUFeatures_ { + int initialized; + int has_neon; + int has_sse2; + int has_sse3; +} CPUFeatures; + +static CPUFeatures _cpu_features; + +#define CPUID_SSE2 0x04000000 +#define CPUIDECX_SSE3 0x00000001 + +static int +_sodium_runtime_arm_cpu_features(CPUFeatures * const cpu_features) +{ +#ifndef __arm__ + cpu_features->has_neon = 0; + return -1; +#else +# ifdef __APPLE__ +# ifdef __ARM_NEON__ + cpu_features->has_neon = 1; +# else + cpu_features->has_neon = 0; +# endif +# elif defined(HAVE_ANDROID_GETCPUFEATURES) && defined(ANDROID_CPU_ARM_FEATURE_NEON) + cpu_features->has_neon = + (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0x0; +# else + cpu_features->has_neon = 0; +# endif + return 0; +#endif +} + +static void +_cpuid(unsigned int cpu_info[4U], const unsigned int cpu_info_type) +{ +#ifdef _MSC_VER + __cpuidex((int *) cpu_info, cpu_info_type, 0); +#elif defined(HAVE_CPUID) + cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; +# ifdef __i386__ + __asm__ __volatile__ ("pushfl; pushfl; " + "popl %0; " + "movl %0, %1; xorl %2, %0; " + "pushl %0; " + "popfl; pushfl; popl %0; popfl" : + "=&r" (cpu_info[0]), "=&r" (cpu_info[1]) : + "i" (0x200000)); + if (((cpu_info[0] ^ cpu_info[1]) & 0x200000) == 0x0) { + return; + } +# endif +# ifdef __i386__ + __asm__ __volatile__ ("xchgl %%ebx, %k1; cpuid; xchgl %%ebx, %k1" : + "=a" (cpu_info[0]), "=&r" (cpu_info[1]), + "=c" (cpu_info[2]), "=d" (cpu_info[3]) : + "0" (cpu_info_type), "2" (0U)); +# elif defined(__x86_64__) + __asm__ __volatile__ ("xchgq %%rbx, %q1; cpuid; xchgq %%rbx, %q1" : + "=a" (cpu_info[0]), "=&r" (cpu_info[1]), + "=c" (cpu_info[2]), "=d" (cpu_info[3]) : + "0" (cpu_info_type), "2" (0U)); +# else + __asm__ __volatile__ ("cpuid" : + "=a" (cpu_info[0]), "=b" (cpu_info[1]), + "=c" (cpu_info[2]), "=d" (cpu_info[3]) : + "0" (cpu_info_type), "2" (0U)); +# endif +#else + cpu_info[0] = cpu_info[1] = cpu_info[2] = cpu_info[3] = 0; +#endif +} + +static int +_sodium_runtime_intel_cpu_features(CPUFeatures * const cpu_features) +{ + unsigned int cpu_info[4]; + unsigned int id; + + _cpuid(cpu_info, 0x0); + if ((id = cpu_info[0]) == 0U) { + return -1; + } + _cpuid(cpu_info, 0x00000001); +#ifndef HAVE_EMMINTRIN_H + cpu_features->has_sse2 = 0; +#else + cpu_features->has_sse2 = ((cpu_info[3] & CPUID_SSE2) != 0x0); +#endif + +#ifndef HAVE_PMMINTRIN_H + cpu_features->has_sse3 = 0; +#else + cpu_features->has_sse3 = ((cpu_info[2] & CPUIDECX_SSE3) != 0x0); +#endif + + return 0; +} + +int +sodium_runtime_get_cpu_features(void) +{ + int ret = -1; + + ret &= _sodium_runtime_arm_cpu_features(&_cpu_features); + ret &= _sodium_runtime_intel_cpu_features(&_cpu_features); + _cpu_features.initialized = 1; + + return ret; +} + +int +sodium_runtime_has_neon(void) { + return _cpu_features.has_neon; +} + +int +sodium_runtime_has_sse2(void) { + return _cpu_features.has_sse2; +} + +int +sodium_runtime_has_sse3(void) { + return _cpu_features.has_sse3; +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h new file mode 100644 index 0000000000..874915ef42 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/runtime.h @@ -0,0 +1,33 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifndef __SODIUM_RUNTIME_H__ +#define __SODIUM_RUNTIME_H__ 1 + +#include "export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +SODIUM_EXPORT +int sodium_runtime_get_cpu_features(void); + +SODIUM_EXPORT +int sodium_runtime_has_neon(void); + +SODIUM_EXPORT +int sodium_runtime_has_sse2(void); + +SODIUM_EXPORT +int sodium_runtime_has_sse3(void); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c new file mode 100644 index 0000000000..5819651454 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/scrypt_platform.c @@ -0,0 +1,107 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2013 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#include <errno.h> +#include <stdlib.h> + +#include "crypto_scrypt.h" +#include "runtime.h" + +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +# define MAP_ANON MAP_ANONYMOUS +#endif + +void * +alloc_region(escrypt_region_t * region, size_t size) +{ + uint8_t * base, * aligned; +#ifdef MAP_ANON + if ((base = (uint8_t *) mmap(NULL, size, PROT_READ | PROT_WRITE, +#ifdef MAP_NOCORE + MAP_ANON | MAP_PRIVATE | MAP_NOCORE, +#else + MAP_ANON | MAP_PRIVATE, +#endif + -1, 0)) == MAP_FAILED) + base = NULL; + aligned = base; +#elif defined(HAVE_POSIX_MEMALIGN) + if ((errno = posix_memalign((void **) &base, 64, size)) != 0) + base = NULL; + aligned = base; +#else + base = aligned = NULL; + if (size + 63 < size) + errno = ENOMEM; + else if ((base = (uint8_t *) malloc(size + 63)) != NULL) { + aligned = base + 63; + aligned -= (uintptr_t)aligned & 63; + } +#endif + region->base = base; + region->aligned = aligned; + region->size = base ? size : 0; + return aligned; +} + +static inline void +init_region(escrypt_region_t * region) +{ + region->base = region->aligned = NULL; + region->size = 0; +} + +int +free_region(escrypt_region_t * region) +{ + if (region->base) { +#ifdef MAP_ANON + if (munmap(region->base, region->size)) + return -1; +#else + free(region->base); +#endif + } + init_region(region); + return 0; +} + +int +escrypt_init_local(escrypt_local_t * local) +{ + init_region(local); + return 0; +} + +int +escrypt_free_local(escrypt_local_t * local) +{ + return free_region(local); +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c new file mode 100644 index 0000000000..856a655e3f --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c @@ -0,0 +1,398 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +/*- + * Copyright 2009 Colin Percival + * Copyright 2012,2013 Alexander Peslyak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ + +#if defined(HAVE_EMMINTRIN_H) || defined(_MSC_VER) +#if __GNUC__ +# pragma GCC target("sse2") +#endif +#include <emmintrin.h> +#if defined(__XOP__) && defined(DISABLED) +# include <x86intrin.h> +#endif + +#include <errno.h> +#include <limits.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include "../pbkdf2-sha256.h" +#include "../sysendian.h" +#include "../crypto_scrypt.h" + +#if defined(__XOP__) && defined(DISABLED) +#define ARX(out, in1, in2, s) \ + out = _mm_xor_si128(out, _mm_roti_epi32(_mm_add_epi32(in1, in2), s)); +#else +#define ARX(out, in1, in2, s) \ + { \ + __m128i T = _mm_add_epi32(in1, in2); \ + out = _mm_xor_si128(out, _mm_slli_epi32(T, s)); \ + out = _mm_xor_si128(out, _mm_srli_epi32(T, 32-s)); \ + } +#endif + +#define SALSA20_2ROUNDS \ + /* Operate on "columns". */ \ + ARX(X1, X0, X3, 7) \ + ARX(X2, X1, X0, 9) \ + ARX(X3, X2, X1, 13) \ + ARX(X0, X3, X2, 18) \ +\ + /* Rearrange data. */ \ + X1 = _mm_shuffle_epi32(X1, 0x93); \ + X2 = _mm_shuffle_epi32(X2, 0x4E); \ + X3 = _mm_shuffle_epi32(X3, 0x39); \ +\ + /* Operate on "rows". */ \ + ARX(X3, X0, X1, 7) \ + ARX(X2, X3, X0, 9) \ + ARX(X1, X2, X3, 13) \ + ARX(X0, X1, X2, 18) \ +\ + /* Rearrange data. */ \ + X1 = _mm_shuffle_epi32(X1, 0x39); \ + X2 = _mm_shuffle_epi32(X2, 0x4E); \ + X3 = _mm_shuffle_epi32(X3, 0x93); + +/** + * Apply the salsa20/8 core to the block provided in (X0 ... X3) ^ (Z0 ... Z3). + */ +#define SALSA20_8_XOR(in, out) \ + { \ + __m128i Y0 = X0 = _mm_xor_si128(X0, (in)[0]); \ + __m128i Y1 = X1 = _mm_xor_si128(X1, (in)[1]); \ + __m128i Y2 = X2 = _mm_xor_si128(X2, (in)[2]); \ + __m128i Y3 = X3 = _mm_xor_si128(X3, (in)[3]); \ + SALSA20_2ROUNDS \ + SALSA20_2ROUNDS \ + SALSA20_2ROUNDS \ + SALSA20_2ROUNDS \ + (out)[0] = X0 = _mm_add_epi32(X0, Y0); \ + (out)[1] = X1 = _mm_add_epi32(X1, Y1); \ + (out)[2] = X2 = _mm_add_epi32(X2, Y2); \ + (out)[3] = X3 = _mm_add_epi32(X3, Y3); \ + } + +/** + * blockmix_salsa8(Bin, Bout, r): + * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r + * bytes in length; the output Bout must also be the same size. + */ +static inline void +blockmix_salsa8(const __m128i * Bin, __m128i * Bout, size_t r) +{ + __m128i X0, X1, X2, X3; + size_t i; + + /* 1: X <-- B_{2r - 1} */ + X0 = Bin[8 * r - 4]; + X1 = Bin[8 * r - 3]; + X2 = Bin[8 * r - 2]; + X3 = Bin[8 * r - 1]; + + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + SALSA20_8_XOR(Bin, Bout) + + /* 2: for i = 0 to 2r - 1 do */ + r--; + for (i = 0; i < r;) { + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4]) + + i++; + + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + SALSA20_8_XOR(&Bin[i * 8], &Bout[i * 4]) + } + + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + SALSA20_8_XOR(&Bin[i * 8 + 4], &Bout[(r + i) * 4 + 4]) +} + +#define XOR4(in) \ + X0 = _mm_xor_si128(X0, (in)[0]); \ + X1 = _mm_xor_si128(X1, (in)[1]); \ + X2 = _mm_xor_si128(X2, (in)[2]); \ + X3 = _mm_xor_si128(X3, (in)[3]); + +#define XOR4_2(in1, in2) \ + X0 = _mm_xor_si128((in1)[0], (in2)[0]); \ + X1 = _mm_xor_si128((in1)[1], (in2)[1]); \ + X2 = _mm_xor_si128((in1)[2], (in2)[2]); \ + X3 = _mm_xor_si128((in1)[3], (in2)[3]); + +static inline uint32_t +blockmix_salsa8_xor(const __m128i * Bin1, const __m128i * Bin2, __m128i * Bout, + size_t r) +{ + __m128i X0, X1, X2, X3; + size_t i; + + /* 1: X <-- B_{2r - 1} */ + XOR4_2(&Bin1[8 * r - 4], &Bin2[8 * r - 4]) + + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + XOR4(Bin1) + SALSA20_8_XOR(Bin2, Bout) + + /* 2: for i = 0 to 2r - 1 do */ + r--; + for (i = 0; i < r;) { + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + XOR4(&Bin1[i * 8 + 4]) + SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4]) + + i++; + + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + XOR4(&Bin1[i * 8]) + SALSA20_8_XOR(&Bin2[i * 8], &Bout[i * 4]) + } + + /* 3: X <-- H(X \xor B_i) */ + /* 4: Y_i <-- X */ + /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ + XOR4(&Bin1[i * 8 + 4]) + SALSA20_8_XOR(&Bin2[i * 8 + 4], &Bout[(r + i) * 4 + 4]) + + return _mm_cvtsi128_si32(X0); +} + +#undef ARX +#undef SALSA20_2ROUNDS +#undef SALSA20_8_XOR +#undef XOR4 +#undef XOR4_2 + +/** + * integerify(B, r): + * Return the result of parsing B_{2r-1} as a little-endian integer. + */ +static inline uint32_t +integerify(const void * B, size_t r) +{ + return *(const uint32_t *)((uintptr_t)(B) + (2 * r - 1) * 64); +} + +/** + * smix(B, r, N, V, XY): + * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; + * the temporary storage V must be 128rN bytes in length; the temporary + * storage XY must be 256r + 64 bytes in length. The value N must be a + * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a + * multiple of 64 bytes. + */ +static void +smix(uint8_t * B, size_t r, uint32_t N, void * V, void * XY) +{ + size_t s = 128 * r; + __m128i * X = (__m128i *) V, * Y; + uint32_t * X32 = (uint32_t *) V; + uint32_t i, j; + size_t k; + + /* 1: X <-- B */ + /* 3: V_i <-- X */ + for (k = 0; k < 2 * r; k++) { + for (i = 0; i < 16; i++) { + X32[k * 16 + i] = + le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]); + } + } + + /* 2: for i = 0 to N - 1 do */ + for (i = 1; i < N - 1; i += 2) { + /* 4: X <-- H(X) */ + /* 3: V_i <-- X */ + Y = (__m128i *)((uintptr_t)(V) + i * s); + blockmix_salsa8(X, Y, r); + + /* 4: X <-- H(X) */ + /* 3: V_i <-- X */ + X = (__m128i *)((uintptr_t)(V) + (i + 1) * s); + blockmix_salsa8(Y, X, r); + } + + /* 4: X <-- H(X) */ + /* 3: V_i <-- X */ + Y = (__m128i *)((uintptr_t)(V) + i * s); + blockmix_salsa8(X, Y, r); + + /* 4: X <-- H(X) */ + /* 3: V_i <-- X */ + X = (__m128i *) XY; + blockmix_salsa8(Y, X, r); + + X32 = (uint32_t *) XY; + Y = (__m128i *)((uintptr_t)(XY) + s); + + /* 7: j <-- Integerify(X) mod N */ + j = integerify(X, r) & (N - 1); + + /* 6: for i = 0 to N - 1 do */ + for (i = 0; i < N; i += 2) { + __m128i * V_j = (__m128i *)((uintptr_t)(V) + j * s); + + /* 8: X <-- H(X \xor V_j) */ + /* 7: j <-- Integerify(X) mod N */ + j = blockmix_salsa8_xor(X, V_j, Y, r) & (N - 1); + V_j = (__m128i *)((uintptr_t)(V) + j * s); + + /* 8: X <-- H(X \xor V_j) */ + /* 7: j <-- Integerify(X) mod N */ + j = blockmix_salsa8_xor(Y, V_j, X, r) & (N - 1); + } + + /* 10: B' <-- X */ + for (k = 0; k < 2 * r; k++) { + for (i = 0; i < 16; i++) { + le32enc(&B[(k * 16 + (i * 5 % 16)) * 4], + X32[k * 16 + i]); + } + } +} + +/** + * escrypt_kdf(local, passwd, passwdlen, salt, saltlen, + * N, r, p, buf, buflen): + * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, + * p, buflen) and write the result into buf. The parameters r, p, and buflen + * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N + * must be a power of 2 greater than 1. + * + * Return 0 on success; or -1 on error. + */ +int +escrypt_kdf_sse(escrypt_local_t * local, + const uint8_t * passwd, size_t passwdlen, + const uint8_t * salt, size_t saltlen, + uint64_t N, uint32_t _r, uint32_t _p, + uint8_t * buf, size_t buflen) +{ + size_t B_size, V_size, XY_size, need; + uint8_t * B; + uint32_t * V, * XY; + size_t r = _r, p = _p; + uint32_t i; + + /* Sanity-check parameters. */ +#if SIZE_MAX > UINT32_MAX + if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { + errno = EFBIG; + return -1; + } +#endif + if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { + errno = EFBIG; + return -1; + } + if (N > UINT32_MAX) { + errno = EFBIG; + return -1; + } + if (((N & (N - 1)) != 0) || (N < 2)) { + errno = EINVAL; + return -1; + } + if (r == 0 || p == 0) { + errno = EINVAL; + return -1; + } + if ((r > SIZE_MAX / 128 / p) || +#if SIZE_MAX / 256 <= UINT32_MAX + (r > SIZE_MAX / 256) || +#endif + (N > SIZE_MAX / 128 / r)) { + errno = ENOMEM; + return -1; + } + + /* Allocate memory. */ + B_size = (size_t)128 * r * p; + V_size = (size_t)128 * r * N; + need = B_size + V_size; + if (need < V_size) { + errno = ENOMEM; + return -1; + } + XY_size = (size_t)256 * r + 64; + need += XY_size; + if (need < XY_size) { + errno = ENOMEM; + return -1; + } + if (local->size < need) { + if (free_region(local)) + return -1; + if (!alloc_region(local, need)) + return -1; + } + B = (uint8_t *)local->aligned; + V = (uint32_t *)((uint8_t *)B + B_size); + XY = (uint32_t *)((uint8_t *)V + V_size); + + /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ + PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size); + + /* 2: for i = 0 to p - 1 do */ + for (i = 0; i < p; i++) { + /* 3: B_i <-- MF(B_i, N) */ + smix(&B[(size_t)128 * i * r], r, N, V, XY); + } + + /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ + PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen); + + /* Success! */ + return 0; +} +#endif + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h new file mode 100644 index 0000000000..04e5c1ed45 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/sysendian.h @@ -0,0 +1,153 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifndef _SYSENDIAN_H_ +#define _SYSENDIAN_H_ + +#include <stdint.h> + +/* Avoid namespace collisions with BSD <sys/endian.h>. */ +#define be16dec scrypt_be16dec +#define be16enc scrypt_be16enc +#define be32dec scrypt_be32dec +#define be32enc scrypt_be32enc +#define be64dec scrypt_be64dec +#define be64enc scrypt_be64enc +#define le16dec scrypt_le16dec +#define le16enc scrypt_le16enc +#define le32dec scrypt_le32dec +#define le32enc scrypt_le32enc +#define le64dec scrypt_le64dec +#define le64enc scrypt_le64enc + +static inline uint16_t +be16dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint16_t)(p[1]) + ((uint16_t)(p[0]) << 8)); +} + +static inline void +be16enc(void *pp, uint16_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[1] = x & 0xff; + p[0] = (x >> 8) & 0xff; +} + +static inline uint32_t +be32dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) + + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24)); +} + +static inline void +be32enc(void *pp, uint32_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[3] = x & 0xff; + p[2] = (x >> 8) & 0xff; + p[1] = (x >> 16) & 0xff; + p[0] = (x >> 24) & 0xff; +} + +static inline uint64_t +be64dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) + + ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) + + ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) + + ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56)); +} + +static inline void +be64enc(void *pp, uint64_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[7] = x & 0xff; + p[6] = (x >> 8) & 0xff; + p[5] = (x >> 16) & 0xff; + p[4] = (x >> 24) & 0xff; + p[3] = (x >> 32) & 0xff; + p[2] = (x >> 40) & 0xff; + p[1] = (x >> 48) & 0xff; + p[0] = (x >> 56) & 0xff; +} + +static inline uint16_t +le16dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint16_t)(p[0]) + ((uint16_t)(p[1]) << 8)); +} + +static inline void +le16enc(void *pp, uint16_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; +} + +static inline uint32_t +le32dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) + + ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24)); +} + +static inline void +le32enc(void *pp, uint32_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; +} + +static inline uint64_t +le64dec(const void *pp) +{ + const uint8_t *p = (uint8_t const *)pp; + + return ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) + + ((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) + + ((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) + + ((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56)); +} + +static inline void +le64enc(void *pp, uint64_t x) +{ + uint8_t * p = (uint8_t *)pp; + + p[0] = x & 0xff; + p[1] = (x >> 8) & 0xff; + p[2] = (x >> 16) & 0xff; + p[3] = (x >> 24) & 0xff; + p[4] = (x >> 32) & 0xff; + p[5] = (x >> 40) & 0xff; + p[6] = (x >> 48) & 0xff; + p[7] = (x >> 56) & 0xff; +} + +#endif /* !_SYSENDIAN_H_ */ + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c new file mode 100644 index 0000000000..e61ccf3ecf --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.c @@ -0,0 +1,78 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifndef __STDC_WANT_LIB_EXT1__ +# define __STDC_WANT_LIB_EXT1__ 1 +#endif +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif + +#include "utils.h" + +#ifdef _WIN32 +# include <windows.h> +# include <wincrypt.h> +#else +# include <unistd.h> +#endif + +#ifdef HAVE_WEAK_SYMBOLS +__attribute__((weak)) void +__sodium_dummy_symbol_to_prevent_lto(void * const pnt, const size_t len) +{ + (void) pnt; + (void) len; +} +#endif + +void +sodium_memzero(void * const pnt, const size_t len) +{ +#ifdef _WIN32 + SecureZeroMemory(pnt, len); +#elif defined(HAVE_MEMSET_S) + if (memset_s(pnt, (rsize_t) len, 0, (rsize_t) len) != 0) { + abort(); + } +#elif defined(HAVE_EXPLICIT_BZERO) + explicit_bzero(pnt, len); +#elif HAVE_WEAK_SYMBOLS + memset(pnt, 0, len); + __sodium_dummy_symbol_to_prevent_lto(pnt, len); +#else + volatile unsigned char *pnt_ = (volatile unsigned char *) pnt; + size_t i = (size_t) 0U; + + while (i < len) { + pnt_[i++] = 0U; + } +#endif +} + +int +sodium_memcmp(const void * const b1_, const void * const b2_, size_t len) +{ + const unsigned char *b1 = (const unsigned char *) b1_; + const unsigned char *b2 = (const unsigned char *) b2_; + size_t i; + unsigned char d = (unsigned char) 0U; + + for (i = 0U; i < len; i++) { + d |= b1[i] ^ b2[i]; + } + return (int) ((1 & ((d - 1) >> 8)) - 1); +} + +#endif diff --git a/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h new file mode 100644 index 0000000000..fb2020c35d --- /dev/null +++ b/libs/libtox/src/toxencryptsave/crypto_pwhash_scryptsalsa208sha256/utils.h @@ -0,0 +1,40 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VANILLA_NACL /* toxcore only uses this when libsodium is unavailable */ + +#ifndef __SODIUM_UTILS_H__ +#define __SODIUM_UTILS_H__ + +#include <stddef.h> + +#include "export.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__cplusplus) || !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L +# define _SODIUM_C99(X) +#else +# define _SODIUM_C99(X) X +#endif + +SODIUM_EXPORT +void sodium_memzero(void * const pnt, const size_t len); + +/* WARNING: sodium_memcmp() must be used to verify if two secret keys + * are equal, in constant time. + * It returns 0 if the keys are equal, and -1 if they differ. + * This function is not designed for lexicographical comparisons. + */ +SODIUM_EXPORT +int sodium_memcmp(const void * const b1_, const void * const b2_, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/libs/libtox/src/toxencryptsave/defines.h b/libs/libtox/src/toxencryptsave/defines.h new file mode 100644 index 0000000000..e3fca073e3 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/defines.h @@ -0,0 +1,2 @@ +#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave" +#define TOX_ENC_SAVE_MAGIC_LENGTH 8 diff --git a/libs/libtox/src/toxencryptsave/toxencryptsave.api.h b/libs/libtox/src/toxencryptsave/toxencryptsave.api.h new file mode 100644 index 0000000000..61f685f86b --- /dev/null +++ b/libs/libtox/src/toxencryptsave/toxencryptsave.api.h @@ -0,0 +1,327 @@ +%{ +/* + * Batch encryption functions. + */ + +/* + * Copyright © 2016-2017 The TokTok team. + * Copyright © 2013-2016 Tox Developers. + * + * This file is part of Tox, the free peer to peer instant messenger. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TOXENCRYPTSAVE_H +#define TOXENCRYPTSAVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +%} + +/******************************************************************************* + * + * This module is organized into two parts. + * + * 1. A simple API operating on plain text/cipher text data and a password to + * encrypt or decrypt it. + * 2. A more advanced API that splits key derivation and encryption into two + * separate function calls. + * + * The first part is implemented in terms of the second part and simply calls + * the separate functions in sequence. Since key derivation is very expensive + * compared to the actual encryption, clients that do a lot of crypto should + * prefer the advanced API and reuse pass-key objects. + * + * To use the second part, first derive an encryption key from a password with + * ${tox.pass_Key.derive}, then use the derived key to encrypt the data. + * + * The encrypted data is prepended with a magic number, to aid validity + * checking (no guarantees are made of course). Any data to be decrypted must + * start with the magic number. + * + * Clients should consider alerting their users that, unlike plain data, if + * even one bit becomes corrupted, the data will be entirely unrecoverable. + * Ditto if they forget their password, there is no way to recover the data. + * + *******************************************************************************/ + +class tox { + +/** + * The size of the salt part of a pass-key. + */ +const PASS_SALT_LENGTH = 32; +/** + * The size of the key part of a pass-key. + */ +const PASS_KEY_LENGTH = 32; +/** + * The amount of additional data required to store any encrypted byte array. + * Encrypting an array of N bytes requires N + $PASS_ENCRYPTION_EXTRA_LENGTH + * bytes in the encrypted byte array. + */ +const PASS_ENCRYPTION_EXTRA_LENGTH = 80; + +error for key_derivation { + NULL, + /** + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. + */ + FAILED, +} + +error for encryption { + NULL, + /** + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. + */ + KEY_DERIVATION_FAILED, + /** + * The encryption itself failed. + */ + FAILED, +} + +error for decryption { + NULL, + /** + * The input data was shorter than $PASS_ENCRYPTION_EXTRA_LENGTH bytes + */ + INVALID_LENGTH, + /** + * The input data is missing the magic number (i.e. wasn't created by this + * module, or is corrupted). + */ + BAD_FORMAT, + /** + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. + */ + KEY_DERIVATION_FAILED, + /** + * The encrypted byte array could not be decrypted. Either the data was + * corrupted or the password/key was incorrect. + */ + FAILED, +} + + +/******************************************************************************* + * + * BEGIN PART 1 + * + * The simple API is presented first. If your code spends too much time using + * these functions, consider using the advanced functions instead and caching + * the generated pass-key. + * + *******************************************************************************/ + +/** + * Encrypts the given data with the given passphrase. + * + * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. This delegates to ${pass_Key.derive} and + * ${pass_Key.encrypt}. + * + * @param plaintext A byte array of length `plaintext_len`. + * @param plaintext_len The length of the plain text array. Bigger than 0. + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * @param ciphertext The cipher text array to write the encrypted data to. + * + * @return true on success. + */ +static bool pass_encrypt(const uint8_t[plaintext_len] plaintext, const uint8_t[passphrase_len] passphrase, uint8_t *ciphertext) + with error for encryption; + + +/** + * Decrypts the given data with the given passphrase. + * + * The output array must be at least `ciphertext_len - $PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. This delegates to ${pass_Key.decrypt}. + * + * @param ciphertext A byte array of length `ciphertext_len`. + * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH. + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * @param plaintext The plain text array to write the decrypted data to. + * + * @return true on success. + */ +static bool pass_decrypt(const uint8_t[ciphertext_len] ciphertext, const uint8_t[passphrase_len] passphrase, uint8_t *plaintext) + with error for decryption; + + +/******************************************************************************* + * + * BEGIN PART 2 + * + * And now part 2, which does the actual encryption, and can be used to write + * less CPU intensive client code than part one. + * + *******************************************************************************/ + +class pass_Key { + /** + * This type represents a pass-key. + * + * A pass-key and a password are two different concepts: a password is given + * by the user in plain text. A pass-key is the generated symmetric key used + * for encryption and decryption. It is derived from a salt and the user- + * provided password. + * + * The $this structure is hidden in the implementation. It can be allocated + * using $new and must be deallocated using $free. + */ + struct this; + + /** + * Create a new $this. The initial value of it is indeterminate. To + * initialise it, use one of the derive_* functions below. + * + * In case of failure, this function returns NULL. The only failure mode at + * this time is memory allocation failure, so this function has no error code. + */ + static this new(); + + /** + * Deallocate a $this. This function behaves like free(), so NULL is an + * acceptable argument value. + */ + void free(); + + /** + * Generates a secret symmetric key from the given passphrase. + * + * Be sure to not compromise the key! Only keep it in memory, do not write + * it to disk. + * + * Note that this function is not deterministic; to derive the same key from + * a password, you also must know the random salt that was used. A + * deterministic version of this function is $derive_with_salt. + * + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * + * @return true on success. + */ + bool derive(const uint8_t[passphrase_len] passphrase) + with error for key_derivation; + + /** + * Same as above, except use the given salt for deterministic key derivation. + * + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * @param salt An array of at least $PASS_SALT_LENGTH bytes. + * + * @return true on success. + */ + bool derive_with_salt(const uint8_t[passphrase_len] passphrase, const uint8_t[PASS_SALT_LENGTH] salt) + with error for key_derivation; + + /** + * Encrypt a plain text with a key produced by $derive or $derive_with_salt. + * + * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. + * + * @param plaintext A byte array of length `plaintext_len`. + * @param plaintext_len The length of the plain text array. Bigger than 0. + * @param ciphertext The cipher text array to write the encrypted data to. + * + * @return true on success. + */ + const bool encrypt(const uint8_t[plaintext_len] plaintext, uint8_t *ciphertext) + with error for encryption; + + /** + * This is the inverse of $encrypt, also using only keys produced by + * $derive or $derive_with_salt. + * + * @param ciphertext A byte array of length `ciphertext_len`. + * @param ciphertext_len The length of the cipher text array. At least $PASS_ENCRYPTION_EXTRA_LENGTH. + * @param plaintext The plain text array to write the decrypted data to. + * + * @return true on success. + */ + const bool decrypt(const uint8_t[ciphertext_len] ciphertext, uint8_t *plaintext) + with error for decryption; +} + +/** + * Retrieves the salt used to encrypt the given data. + * + * The retrieved salt can then be passed to ${pass_Key.derive_with_salt} to + * produce the same key as was previously used. Any data encrypted with this + * module can be used as input. + * + * The cipher text must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. + * The salt must be $PASS_SALT_LENGTH bytes in length. + * If the passed byte arrays are smaller than required, the behaviour is + * undefined. + * + * If the cipher text pointer or the salt is NULL, this function returns false. + * + * Success does not say anything about the validity of the data, only that + * data of the appropriate size was copied. + * + * @return true on success. + */ +static bool get_salt(const uint8_t *ciphertext, uint8_t[PASS_SALT_LENGTH] salt) { + NULL, + /** + * The input data is missing the magic number (i.e. wasn't created by this + * module, or is corrupted). + */ + BAD_FORMAT, +} + +/** + * Determines whether or not the given data is encrypted by this module. + * + * It does this check by verifying that the magic number is the one put in + * place by the encryption functions. + * + * The data must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. + * If the passed byte array is smaller than required, the behaviour is + * undefined. + * + * If the data pointer is NULL, the behaviour is undefined + * + * @return true if the data is encrypted by this module. + */ +static bool is_data_encrypted(const uint8_t *data); + +} + +%{ + +#ifdef __cplusplus +} +#endif + +#endif +%} diff --git a/libs/libtox/src/toxencryptsave/toxencryptsave.c b/libs/libtox/src/toxencryptsave/toxencryptsave.c new file mode 100644 index 0000000000..5640e82fc7 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/toxencryptsave.c @@ -0,0 +1,338 @@ +/* + * Batch encryption functions. + */ + +/* + * Copyright © 2016-2017 The TokTok team. + * Copyright © 2013 Tox project. + * + * This file is part of Tox, the free peer to peer instant messenger. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see <http://www.gnu.org/licenses/>. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "../toxcore/crypto_core.h" +#include "defines.h" +#include "toxencryptsave.h" +#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} + +#ifdef VANILLA_NACL +#include <crypto_box.h> +#include <crypto_hash_sha256.h> +#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h" +#define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) +#else +#include <sodium.h> +#endif + +#include <string.h> + +#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#endif + +#if TOX_PASS_KEY_LENGTH != CRYPTO_SHARED_KEY_SIZE +#error TOX_PASS_KEY_LENGTH is assumed to be equal to CRYPTO_SHARED_KEY_SIZE +#endif + +#if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) +#error TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) +#endif + +uint32_t tox_pass_salt_length(void) +{ + return TOX_PASS_SALT_LENGTH; +} +uint32_t tox_pass_key_length(void) +{ + return TOX_PASS_KEY_LENGTH; +} +uint32_t tox_pass_encryption_extra_length(void) +{ + return TOX_PASS_ENCRYPTION_EXTRA_LENGTH; +} + +struct Tox_Pass_Key { + uint8_t salt[TOX_PASS_SALT_LENGTH]; + uint8_t key[TOX_PASS_KEY_LENGTH]; +}; + +Tox_Pass_Key *tox_pass_key_new(void) +{ + return (Tox_Pass_Key *)malloc(sizeof(Tox_Pass_Key)); +} + +void tox_pass_key_free(Tox_Pass_Key *pass_key) +{ + free(pass_key); +} + +/* Clients should consider alerting their users that, unlike plain data, if even one bit + * becomes corrupted, the data will be entirely unrecoverable. + * Ditto if they forget their password, there is no way to recover the data. + */ + +/* This retrieves the salt used to encrypt the given data, which can then be passed to + * tox_pass_key_derive_with_salt to produce the same key as was previously used. Any encrpyted + * data with this module can be used as input. + * + * returns true if magic number matches + * success does not say anything about the validity of the data, only that data of + * the appropriate size was copied + */ +bool tox_get_salt(const uint8_t *data, uint8_t *salt, TOX_ERR_GET_SALT *error) +{ + if (!data || !salt) { + SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_NULL); + return false; + } + + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_BAD_FORMAT); + return false; + } + + data += TOX_ENC_SAVE_MAGIC_LENGTH; + memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); + SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_OK); + return true; +} + +/* Generates a secret symmetric key from the given passphrase. out_key must be at least + * TOX_PASS_KEY_LENGTH bytes long. + * Be sure to not compromise the key! Only keep it in memory, do not write to disk. + * The password is zeroed after key derivation. + * The key should only be used with the other functions in this module, as it + * includes a salt. + * Note that this function is not deterministic; to derive the same key from a + * password, you also must know the random salt that was used. See below. + * + * returns true on success + */ +bool tox_pass_key_derive(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength, + TOX_ERR_KEY_DERIVATION *error) +{ + uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; + randombytes(salt, sizeof salt); + return tox_pass_key_derive_with_salt(out_key, passphrase, pplength, salt, error); +} + +/* Same as above, except with use the given salt for deterministic key derivation. + * The salt must be TOX_PASS_SALT_LENGTH bytes in length. + */ +bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength, + const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error) +{ + if (!salt || !out_key || (!passphrase && pplength != 0)) { + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); + return 0; + } + + uint8_t passkey[crypto_hash_sha256_BYTES]; + crypto_hash_sha256(passkey, passphrase, pplength); + + uint8_t key[CRYPTO_SHARED_KEY_SIZE]; + + /* Derive a key from the password */ + /* http://doc.libsodium.org/key_derivation/README.html */ + /* note that, according to the documentation, a generic pwhash interface will be created + * once the pwhash competition (https://password-hashing.net/) is over */ + if (crypto_pwhash_scryptsalsa208sha256( + key, sizeof(key), (char *)passkey, sizeof(passkey), salt, + crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ + crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { + /* out of memory most likely */ + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); + return 0; + } + + sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ + memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); + memcpy(out_key->key, key, CRYPTO_SHARED_KEY_SIZE); + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); + return 1; +} + +/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output + * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. + * key must be TOX_PASS_KEY_LENGTH bytes. + * If you already have a symmetric key from somewhere besides this module, simply + * call encrypt_data_symmetric in toxcore/crypto_core directly. + * + * returns true on success + */ +bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t data_len, uint8_t *out, + TOX_ERR_ENCRYPTION *error) +{ + if (data_len == 0 || !data || !key || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); + return 0; + } + + /* the output data consists of, in order: + * salt, nonce, mac, enc_data + * where the mac is automatically prepended by the encrypt() + * the salt+nonce is called the prefix + * I'm not sure what else I'm supposed to do with the salt and nonce, since we + * need them to decrypt the data + */ + + /* first add the magic number */ + memcpy(out, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); + out += TOX_ENC_SAVE_MAGIC_LENGTH; + + /* then add the rest prefix */ + memcpy(out, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); + out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; + + uint8_t nonce[crypto_box_NONCEBYTES]; + random_nonce(nonce); + memcpy(out, nonce, crypto_box_NONCEBYTES); + out += crypto_box_NONCEBYTES; + + /* now encrypt */ + if (encrypt_data_symmetric(key->key, nonce, data, data_len, out) + != data_len + crypto_box_MACBYTES) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK); + return 1; +} + +/* Encrypts the given data with the given passphrase. The output array must be + * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates + * to tox_derive_key and tox_pass_key_encrypt. + * + * returns true on success + */ +bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out, + TOX_ERR_ENCRYPTION *error) +{ + Tox_Pass_Key key; + TOX_ERR_KEY_DERIVATION _error; + + if (!tox_pass_key_derive(&key, passphrase, pplength, &_error)) { + if (_error == TOX_ERR_KEY_DERIVATION_NULL) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); + } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED); + } + + return 0; + } + + return tox_pass_key_encrypt(&key, data, data_len, out, error); +} + +/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by + * tox_derive_key. + * + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH + * + * returns true on success + */ +bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t length, uint8_t *out, + TOX_ERR_DECRYPTION *error) +{ + if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); + return 0; + } + + if (!data || !key || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL); + return 0; + } + + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); + return 0; + } + + data += TOX_ENC_SAVE_MAGIC_LENGTH; + data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // salt only affects key derivation + + size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + + uint8_t nonce[crypto_box_NONCEBYTES]; + memcpy(nonce, data, crypto_box_NONCEBYTES); + data += crypto_box_NONCEBYTES; + + /* decrypt the data */ + if (decrypt_data_symmetric(key->key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) + != decrypt_length) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED); + return 0; + } + + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK); + return 1; +} + +/* Decrypts the given data with the given passphrase. The output array must be + * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates + * to tox_pass_key_decrypt. + * + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH + * + * returns true on success + */ +bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out, + TOX_ERR_DECRYPTION *error) +{ + if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); + return 0; + } + + if (!data || !passphrase || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL); + return 0; + } + + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); + return 0; + } + + uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; + memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); + + /* derive the key */ + Tox_Pass_Key key; + + if (!tox_pass_key_derive_with_salt(&key, passphrase, pplength, salt, NULL)) { + /* out of memory most likely */ + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); + return 0; + } + + return tox_pass_key_decrypt(&key, data, length, out, error); +} + +/* Determines whether or not the given data is encrypted (by checking the magic number) + */ +bool tox_is_data_encrypted(const uint8_t *data) +{ + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) { + return 1; + } + + return 0; +} diff --git a/libs/libtox/src/toxencryptsave/toxencryptsave.h b/libs/libtox/src/toxencryptsave/toxencryptsave.h new file mode 100644 index 0000000000..ef1ab15289 --- /dev/null +++ b/libs/libtox/src/toxencryptsave/toxencryptsave.h @@ -0,0 +1,388 @@ +/* + * Batch encryption functions. + */ + +/* + * Copyright © 2016-2017 The TokTok team. + * Copyright © 2013-2016 Tox Developers. + * + * This file is part of Tox, the free peer to peer instant messenger. + * + * Tox is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tox is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tox. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TOXENCRYPTSAVE_H +#define TOXENCRYPTSAVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + + +/******************************************************************************* + * + * This module is organized into two parts. + * + * 1. A simple API operating on plain text/cipher text data and a password to + * encrypt or decrypt it. + * 2. A more advanced API that splits key derivation and encryption into two + * separate function calls. + * + * The first part is implemented in terms of the second part and simply calls + * the separate functions in sequence. Since key derivation is very expensive + * compared to the actual encryption, clients that do a lot of crypto should + * prefer the advanced API and reuse pass-key objects. + * + * To use the second part, first derive an encryption key from a password with + * tox_pass_key_derive, then use the derived key to encrypt the data. + * + * The encrypted data is prepended with a magic number, to aid validity + * checking (no guarantees are made of course). Any data to be decrypted must + * start with the magic number. + * + * Clients should consider alerting their users that, unlike plain data, if + * even one bit becomes corrupted, the data will be entirely unrecoverable. + * Ditto if they forget their password, there is no way to recover the data. + * + ******************************************************************************/ + + + +/** + * The size of the salt part of a pass-key. + */ +#define TOX_PASS_SALT_LENGTH 32 + +uint32_t tox_pass_salt_length(void); + +/** + * The size of the key part of a pass-key. + */ +#define TOX_PASS_KEY_LENGTH 32 + +uint32_t tox_pass_key_length(void); + +/** + * The amount of additional data required to store any encrypted byte array. + * Encrypting an array of N bytes requires N + TOX_PASS_ENCRYPTION_EXTRA_LENGTH + * bytes in the encrypted byte array. + */ +#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80 + +uint32_t tox_pass_encryption_extra_length(void); + +typedef enum TOX_ERR_KEY_DERIVATION { + + /** + * The function returned successfully. + */ + TOX_ERR_KEY_DERIVATION_OK, + + /** + * One of the arguments to the function was NULL when it was not expected. + */ + TOX_ERR_KEY_DERIVATION_NULL, + + /** + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. + */ + TOX_ERR_KEY_DERIVATION_FAILED, + +} TOX_ERR_KEY_DERIVATION; + + +typedef enum TOX_ERR_ENCRYPTION { + + /** + * The function returned successfully. + */ + TOX_ERR_ENCRYPTION_OK, + + /** + * One of the arguments to the function was NULL when it was not expected. + */ + TOX_ERR_ENCRYPTION_NULL, + + /** + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. + */ + TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED, + + /** + * The encryption itself failed. + */ + TOX_ERR_ENCRYPTION_FAILED, + +} TOX_ERR_ENCRYPTION; + + +typedef enum TOX_ERR_DECRYPTION { + + /** + * The function returned successfully. + */ + TOX_ERR_DECRYPTION_OK, + + /** + * One of the arguments to the function was NULL when it was not expected. + */ + TOX_ERR_DECRYPTION_NULL, + + /** + * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes + */ + TOX_ERR_DECRYPTION_INVALID_LENGTH, + + /** + * The input data is missing the magic number (i.e. wasn't created by this + * module, or is corrupted). + */ + TOX_ERR_DECRYPTION_BAD_FORMAT, + + /** + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. + */ + TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED, + + /** + * The encrypted byte array could not be decrypted. Either the data was + * corrupted or the password/key was incorrect. + */ + TOX_ERR_DECRYPTION_FAILED, + +} TOX_ERR_DECRYPTION; + + + +/******************************************************************************* + * + * BEGIN PART 1 + * + * The simple API is presented first. If your code spends too much time using + * these functions, consider using the advanced functions instead and caching + * the generated pass-key. + * + ******************************************************************************/ + + + +/** + * Encrypts the given data with the given passphrase. + * + * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. This delegates to tox_pass_key_derive and + * tox_pass_key_encrypt. + * + * @param plaintext A byte array of length `plaintext_len`. + * @param plaintext_len The length of the plain text array. Bigger than 0. + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * @param ciphertext The cipher text array to write the encrypted data to. + * + * @return true on success. + */ +bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len, + uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error); + +/** + * Decrypts the given data with the given passphrase. + * + * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. This delegates to tox_pass_key_decrypt. + * + * @param ciphertext A byte array of length `ciphertext_len`. + * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH. + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * @param plaintext The plain text array to write the decrypted data to. + * + * @return true on success. + */ +bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase, + size_t passphrase_len, uint8_t *plaintext, TOX_ERR_DECRYPTION *error); + + +/******************************************************************************* + * + * BEGIN PART 2 + * + * And now part 2, which does the actual encryption, and can be used to write + * less CPU intensive client code than part one. + * + ******************************************************************************/ + + + +/** + * This type represents a pass-key. + * + * A pass-key and a password are two different concepts: a password is given + * by the user in plain text. A pass-key is the generated symmetric key used + * for encryption and decryption. It is derived from a salt and the user- + * provided password. + * + * The Tox_Pass_Key structure is hidden in the implementation. It can be allocated + * using tox_pass_key_new and must be deallocated using tox_pass_key_free. + */ +#ifndef TOX_PASS_KEY_DEFINED +#define TOX_PASS_KEY_DEFINED +typedef struct Tox_Pass_Key Tox_Pass_Key; +#endif /* TOX_PASS_KEY_DEFINED */ + +/** + * Create a new Tox_Pass_Key. The initial value of it is indeterminate. To + * initialise it, use one of the derive_* functions below. + * + * In case of failure, this function returns NULL. The only failure mode at + * this time is memory allocation failure, so this function has no error code. + */ +struct Tox_Pass_Key *tox_pass_key_new(void); + +/** + * Deallocate a Tox_Pass_Key. This function behaves like free(), so NULL is an + * acceptable argument value. + */ +void tox_pass_key_free(struct Tox_Pass_Key *_key); + +/** + * Generates a secret symmetric key from the given passphrase. + * + * Be sure to not compromise the key! Only keep it in memory, do not write + * it to disk. + * + * Note that this function is not deterministic; to derive the same key from + * a password, you also must know the random salt that was used. A + * deterministic version of this function is tox_pass_key_derive_with_salt. + * + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * + * @return true on success. + */ +bool tox_pass_key_derive(struct Tox_Pass_Key *_key, const uint8_t *passphrase, size_t passphrase_len, + TOX_ERR_KEY_DERIVATION *error); + +/** + * Same as above, except use the given salt for deterministic key derivation. + * + * @param passphrase The user-provided password. Can be empty. + * @param passphrase_len The length of the password. + * @param salt An array of at least TOX_PASS_SALT_LENGTH bytes. + * + * @return true on success. + */ +bool tox_pass_key_derive_with_salt(struct Tox_Pass_Key *_key, const uint8_t *passphrase, size_t passphrase_len, + const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error); + +/** + * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt. + * + * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` + * bytes long. + * + * @param plaintext A byte array of length `plaintext_len`. + * @param plaintext_len The length of the plain text array. Bigger than 0. + * @param ciphertext The cipher text array to write the encrypted data to. + * + * @return true on success. + */ +bool tox_pass_key_encrypt(const struct Tox_Pass_Key *_key, const uint8_t *plaintext, size_t plaintext_len, + uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error); + +/** + * This is the inverse of tox_pass_key_encrypt, also using only keys produced by + * tox_pass_key_derive or tox_pass_key_derive_with_salt. + * + * @param ciphertext A byte array of length `ciphertext_len`. + * @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH. + * @param plaintext The plain text array to write the decrypted data to. + * + * @return true on success. + */ +bool tox_pass_key_decrypt(const struct Tox_Pass_Key *_key, const uint8_t *ciphertext, size_t ciphertext_len, + uint8_t *plaintext, TOX_ERR_DECRYPTION *error); + +typedef enum TOX_ERR_GET_SALT { + + /** + * The function returned successfully. + */ + TOX_ERR_GET_SALT_OK, + + /** + * One of the arguments to the function was NULL when it was not expected. + */ + TOX_ERR_GET_SALT_NULL, + + /** + * The input data is missing the magic number (i.e. wasn't created by this + * module, or is corrupted). + */ + TOX_ERR_GET_SALT_BAD_FORMAT, + +} TOX_ERR_GET_SALT; + + +/** + * Retrieves the salt used to encrypt the given data. + * + * The retrieved salt can then be passed to tox_pass_key_derive_with_salt to + * produce the same key as was previously used. Any data encrypted with this + * module can be used as input. + * + * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. + * The salt must be TOX_PASS_SALT_LENGTH bytes in length. + * If the passed byte arrays are smaller than required, the behaviour is + * undefined. + * + * If the cipher text pointer or the salt is NULL, this function returns false. + * + * Success does not say anything about the validity of the data, only that + * data of the appropriate size was copied. + * + * @return true on success. + */ +bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, TOX_ERR_GET_SALT *error); + +/** + * Determines whether or not the given data is encrypted by this module. + * + * It does this check by verifying that the magic number is the one put in + * place by the encryption functions. + * + * The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. + * If the passed byte array is smaller than required, the behaviour is + * undefined. + * + * If the data pointer is NULL, the behaviour is undefined + * + * @return true if the data is encrypted by this module. + */ +bool tox_is_data_encrypted(const uint8_t *data); + + +#ifdef __cplusplus +} +#endif + +#endif |