summaryrefslogtreecommitdiffstats
path: root/3rd_party/libsrp6a-sha512
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2022-02-09 04:04:36 +0100
committerGravatar Nikias Bassen2022-02-09 04:04:36 +0100
commite41dbc3ddbe30a414e73fa25d9c7c304ffe6989e (patch)
tree599c99a2f32bc18f1e9ebc740d0a12d71c49bb10 /3rd_party/libsrp6a-sha512
parentee9104bcb8d494b579e122a2dcc94a2b79d38e4b (diff)
downloadlibimobiledevice-e41dbc3ddbe30a414e73fa25d9c7c304ffe6989e.tar.gz
libimobiledevice-e41dbc3ddbe30a414e73fa25d9c7c304ffe6989e.tar.bz2
Add support for wireless pairing
Diffstat (limited to '3rd_party/libsrp6a-sha512')
-rw-r--r--3rd_party/libsrp6a-sha512/LICENSE62
-rw-r--r--3rd_party/libsrp6a-sha512/Makefile.am31
-rw-r--r--3rd_party/libsrp6a-sha512/README.md35
-rw-r--r--3rd_party/libsrp6a-sha512/cstr.c226
-rw-r--r--3rd_party/libsrp6a-sha512/cstr.h94
-rw-r--r--3rd_party/libsrp6a-sha512/srp.c274
-rw-r--r--3rd_party/libsrp6a-sha512/srp.h372
-rw-r--r--3rd_party/libsrp6a-sha512/srp6a_sha512_client.c363
-rw-r--r--3rd_party/libsrp6a-sha512/srp_aux.h146
-rw-r--r--3rd_party/libsrp6a-sha512/t_conv.c258
-rw-r--r--3rd_party/libsrp6a-sha512/t_defines.h137
-rw-r--r--3rd_party/libsrp6a-sha512/t_math.c1008
-rw-r--r--3rd_party/libsrp6a-sha512/t_misc.c450
-rw-r--r--3rd_party/libsrp6a-sha512/t_pwd.h246
-rw-r--r--3rd_party/libsrp6a-sha512/t_sha.c276
-rw-r--r--3rd_party/libsrp6a-sha512/t_sha.h125
-rw-r--r--3rd_party/libsrp6a-sha512/t_truerand.c241
17 files changed, 4344 insertions, 0 deletions
diff --git a/3rd_party/libsrp6a-sha512/LICENSE b/3rd_party/libsrp6a-sha512/LICENSE
new file mode 100644
index 0000000..7f70640
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/LICENSE
@@ -0,0 +1,62 @@
+Licensing
+---------
+
+SRP is royalty-free worldwide for commercial and non-commercial use.
+The SRP library has been carefully written not to depend on any
+encumbered algorithms, and it is distributed under a standard
+BSD-style Open Source license which is shown below. This license
+covers implementations based on the SRP library as well as
+independent implementations based on RFC 2945.
+
+The SRP distribution itself contains algorithms and code from
+various freeware packages; these parts fall under both the SRP
+Open Source license and the packages' own licenses. Care has
+been taken to ensure that these licenses are compatible with
+Open Source distribution, but it is the responsibility of the
+licensee to comply with the terms of these licenses. This
+disclaimer also applies to third-party libraries that may be
+linked into the distribution, since they may contain patented
+intellectual property. The file "Copyrights" contains a list
+of the copyrights incorporated by portions of the software.
+
+Broader use of the SRP authentication technology, such as variants
+incorporating the use of an explicit server secret (SRP-Z), may
+require a license; please contact the Stanford Office of Technology
+Licensing (http://otl.stanford.edu/) for more information about
+terms and conditions.
+
+This software is covered under the following copyright:
+
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+Address all questions regarding this license to:
+
+ Tom Wu
+ tjw@cs.Stanford.EDU
diff --git a/3rd_party/libsrp6a-sha512/Makefile.am b/3rd_party/libsrp6a-sha512/Makefile.am
new file mode 100644
index 0000000..8c6e2f5
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/Makefile.am
@@ -0,0 +1,31 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir) \
+ -Wno-incompatible-pointer-types
+
+include_HEADERS = srp.h srp_aux.h cstr.h
+
+AM_CFLAGS = -DHAVE_CONFIG_H
+if HAVE_OPENSSL
+AM_CFLAGS += -DOPENSSL=1 -DOPENSSL_ENGINE=1 $(openssl_CFLAGS)
+else
+if HAVE_GCRYPT
+AM_CFLAGS += -DGCRYPT=1 $(libgcrypt_CFLAGS)
+else
+if HAVE_MBEDTLS
+AM_CFLAGS += -DMBEDTLS=1 $(mbedtls_CFLAGS)
+endif
+endif
+endif
+
+noinst_LTLIBRARIES = libsrp6a-sha512.la
+
+libsrp6a_sha512_la_SOURCES = \
+ t_conv.c t_math.c t_misc.c \
+ t_truerand.c cstr.c \
+ srp.c srp6a_sha512_client.c
+if !HAVE_OPENSSL
+libsrp6a_sha512_la_SOURCES += t_sha.c
+endif
diff --git a/3rd_party/libsrp6a-sha512/README.md b/3rd_party/libsrp6a-sha512/README.md
new file mode 100644
index 0000000..4affe4a
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/README.md
@@ -0,0 +1,35 @@
+# SRP6a-sha512 library
+
+## About
+
+This library is based on Stanford's Secure Remote Password (SRP) protocol
+implementation, or more precise on the `libsrp` part thereof.
+The entire source code for the SRP project can be obtained from [here](https://github.com/secure-remote-password/stanford-srp).
+
+It has been adapted to the needs of the libimobiledevice project, and
+contains just a part of the original code; it only supports the SRP6a
+client method which has been modified to use SHA512 instead of SHA1.
+The only supported SRP method is `SRP6a_sha512_client_method()`.
+Besides that, support for MbedTLS has been added.
+
+Also, all server-side code has been removed, and the client-side code
+has been reduced to a minimum, so that basically only the following
+functions remain operational:
+
+- `SRP_initialize_library`
+- `SRP_new`
+- `SRP_free`
+- `SRP_set_user_raw`
+- `SRP_set_params`
+- `SRP_set_auth_password`
+- `SRP_gen_pub`
+- `SRP_compute_key`
+- `SRP_respond`
+- `SRP_verify`
+
+Anything else has not been tested and must be considered non-functional.
+
+## License
+
+The license of the original work does still apply and can be found in the
+LICENSE file that comes with the code.
diff --git a/3rd_party/libsrp6a-sha512/cstr.c b/3rd_party/libsrp6a-sha512/cstr.c
new file mode 100644
index 0000000..9856f46
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/cstr.c
@@ -0,0 +1,226 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "cstr.h"
+
+#define EXPFACTOR 2 /* Minimum expansion factor */
+#define MINSIZE 4 /* Absolute minimum - one word */
+
+static char cstr_empty_string[] = { '\0' };
+static cstr_allocator * default_alloc = NULL;
+
+/*
+ * It is assumed, for efficiency, that it is okay to pass more arguments
+ * to a function than are called for, as long as the required arguments
+ * are in proper form. If extra arguments to malloc() and free() cause
+ * problems, define PEDANTIC_ARGS below.
+ */
+#ifdef PEDANTIC_ARGS
+static void * Cmalloc(int n, void * heap) { return malloc(n); }
+static void Cfree(void * p, void * heap) { free(p); }
+static cstr_allocator malloc_allocator = { Cmalloc, Cfree, NULL };
+#else
+static cstr_allocator malloc_allocator = { malloc, free, NULL };
+#endif
+
+_TYPE( void )
+cstr_set_allocator(cstr_allocator * alloc)
+{
+ default_alloc = alloc;
+}
+
+_TYPE( cstr * )
+cstr_new_alloc(cstr_allocator * alloc)
+{
+ cstr * str;
+
+ if(alloc == NULL) {
+ if(default_alloc == NULL) {
+ default_alloc = &malloc_allocator;
+ }
+ alloc = default_alloc;
+ }
+
+ str = (cstr *) (*alloc->alloc)(sizeof(cstr), alloc->heap);
+ if(str) {
+ str->data = cstr_empty_string;
+ str->length = str->cap = 0;
+ str->ref = 1;
+ str->allocator = alloc;
+ }
+ return str;
+}
+
+_TYPE( cstr * )
+cstr_new()
+{
+ return cstr_new_alloc(NULL);
+}
+
+_TYPE( cstr * )
+cstr_dup_alloc(const cstr * str, cstr_allocator * alloc)
+{
+ cstr * nstr = cstr_new_alloc(alloc);
+ if(nstr)
+ cstr_setn(nstr, str->data, str->length);
+ return nstr;
+}
+
+_TYPE( cstr * )
+cstr_dup(const cstr * str)
+{
+ return cstr_dup_alloc(str, NULL);
+}
+
+_TYPE( cstr * )
+cstr_create(const char * s)
+{
+ return cstr_createn(s, strlen(s));
+}
+
+_TYPE( cstr * )
+cstr_createn(const char * s, int len)
+{
+ cstr * str = cstr_new();
+ if(str) {
+ cstr_setn(str, s, len);
+ }
+ return str;
+}
+
+_TYPE( void )
+cstr_use(cstr * str)
+{
+ ++str->ref;
+}
+
+_TYPE( void )
+cstr_clear_free(cstr * str)
+{
+ if(--str->ref == 0) {
+ if(str->cap > 0) {
+ memset(str->data, 0, str->cap);
+ (*str->allocator->free)(str->data, str->allocator->heap);
+ }
+ (*str->allocator->free)(str, str->allocator->heap);
+ }
+}
+
+_TYPE( void )
+cstr_free(cstr * str)
+{
+ if(--str->ref == 0) {
+ if(str->cap > 0)
+ (*str->allocator->free)(str->data, str->allocator->heap);
+ (*str->allocator->free)(str, str->allocator->heap);
+ }
+}
+
+_TYPE( void )
+cstr_empty(cstr * str)
+{
+ if(str->cap > 0)
+ (*str->allocator->free)(str->data, str->allocator->heap);
+ str->data = cstr_empty_string;
+ str->length = str->cap = 0;
+}
+
+static int
+cstr_alloc(cstr * str, int len)
+{
+ char * t;
+
+ if(len > str->cap) {
+ if(len < EXPFACTOR * str->cap)
+ len = EXPFACTOR * str->cap;
+ if(len < MINSIZE)
+ len = MINSIZE;
+
+ t = (char *) (*str->allocator->alloc)(len * sizeof(char),
+ str->allocator->heap);
+ if(t) {
+ if(str->data) {
+ t[str->length] = 0;
+ if(str->cap > 0) {
+ if(str->length > 0)
+ memcpy(t, str->data, str->length);
+ free(str->data);
+ }
+ }
+ str->data = t;
+ str->cap = len;
+ return 1;
+ }
+ else
+ return -1;
+ }
+ else
+ return 0;
+}
+
+_TYPE( int )
+cstr_copy(cstr * dst, const cstr * src)
+{
+ return cstr_setn(dst, src->data, src->length);
+}
+
+_TYPE( int )
+cstr_set(cstr * str, const char * s)
+{
+ return cstr_setn(str, s, strlen(s));
+}
+
+_TYPE( int )
+cstr_setn(cstr * str, const char * s, int len)
+{
+ if(cstr_alloc(str, len + 1) < 0)
+ return -1;
+ str->data[len] = 0;
+ if(s != NULL && len > 0)
+ memmove(str->data, s, len);
+ str->length = len;
+ return 1;
+}
+
+_TYPE( int )
+cstr_set_length(cstr * str, int len)
+{
+ if(len < str->length) {
+ str->data[len] = 0;
+ str->length = len;
+ return 1;
+ }
+ else if(len > str->length) {
+ if(cstr_alloc(str, len + 1) < 0)
+ return -1;
+ memset(str->data + str->length, 0, len - str->length + 1);
+ str->length = len;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+_TYPE( int )
+cstr_append(cstr * str, const char * s)
+{
+ return cstr_appendn(str, s, strlen(s));
+}
+
+_TYPE( int )
+cstr_appendn(cstr * str, const char * s, int len)
+{
+ if(cstr_alloc(str, str->length + len + 1) < 0)
+ return -1;
+ memcpy(str->data + str->length, s, len);
+ str->length += len;
+ str->data[str->length] = 0;
+ return 1;
+}
+
+_TYPE( int )
+cstr_append_str(cstr * dst, const cstr * src)
+{
+ return cstr_appendn(dst, src->data, src->length);
+}
diff --git a/3rd_party/libsrp6a-sha512/cstr.h b/3rd_party/libsrp6a-sha512/cstr.h
new file mode 100644
index 0000000..7cc019a
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/cstr.h
@@ -0,0 +1,94 @@
+#ifndef _CSTR_H_
+#define _CSTR_H_
+
+/* A general-purpose string "class" for C */
+
+#if !defined(P)
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+/* For building dynamic link libraries under windows, windows NT
+ * using MSVC1.5 or MSVC2.0
+ */
+
+#ifndef _DLLDECL
+#define _DLLDECL
+
+#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
+#define _MSVC15EXPORT _export
+#define _MSVC20EXPORT
+#define _DLLAPI _export _pascal
+#define _CDECL
+#define _TYPE(a) a _MSVC15EXPORT
+#define DLLEXPORT 1
+
+#elif defined(MSVC20) || (defined(_USRDLL) && defined(SRP_EXPORTS))
+#define _MSVC15EXPORT
+#define _MSVC20EXPORT _declspec(dllexport)
+#define _DLLAPI
+#define _CDECL
+#define _TYPE(a) _MSVC20EXPORT a
+#define DLLEXPORT 1
+
+#else /* Default, non-dll. Use this for Unix or DOS */
+#define _MSVC15DEXPORT
+#define _MSVC20EXPORT
+#define _DLLAPI
+#if defined(WINDOWS) || defined(WIN32)
+#define _CDECL _cdecl
+#else
+#define _CDECL
+#endif
+#define _TYPE(a) a _CDECL
+#endif
+#endif /* _DLLDECL */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Arguments to allocator methods ordered this way for compatibility */
+typedef struct cstr_alloc_st {
+ void * (_CDECL * alloc)(size_t n, void * heap);
+ void (_CDECL * free)(void * p, void * heap);
+ void * heap;
+} cstr_allocator;
+
+typedef struct cstr_st {
+ char * data; /* Okay to access data and length fields directly */
+ int length;
+ int cap;
+ int ref; /* Simple reference counter */
+ cstr_allocator * allocator;
+} cstr;
+
+_TYPE( void ) cstr_set_allocator P((cstr_allocator * alloc));
+
+_TYPE( cstr * ) cstr_new P((void));
+_TYPE( cstr * ) cstr_new_alloc P((cstr_allocator * alloc));
+_TYPE( cstr * ) cstr_dup P((const cstr * str));
+_TYPE( cstr * ) cstr_dup_alloc P((const cstr * str, cstr_allocator * alloc));
+_TYPE( cstr * ) cstr_create P((const char * s));
+_TYPE( cstr * ) cstr_createn P((const char * s, int len));
+
+_TYPE( void ) cstr_free P((cstr * str));
+_TYPE( void ) cstr_clear_free P((cstr * str));
+_TYPE( void ) cstr_use P((cstr * str));
+_TYPE( void ) cstr_empty P((cstr * str));
+_TYPE( int ) cstr_copy P((cstr * dst, const cstr * src));
+_TYPE( int ) cstr_set P((cstr * str, const char * s));
+_TYPE( int ) cstr_setn P((cstr * str, const char * s, int len));
+_TYPE( int ) cstr_set_length P((cstr * str, int len));
+_TYPE( int ) cstr_append P((cstr * str, const char * s));
+_TYPE( int ) cstr_appendn P((cstr * str, const char * s, int len));
+_TYPE( int ) cstr_append_str P((cstr * dst, const cstr * src));
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _CSTR_H_ */
diff --git a/3rd_party/libsrp6a-sha512/srp.c b/3rd_party/libsrp6a-sha512/srp.c
new file mode 100644
index 0000000..74e1f98
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/srp.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+#include "t_defines.h"
+#include "srp.h"
+
+static int library_initialized = 0;
+
+_TYPE( SRP_RESULT )
+SRP_initialize_library()
+{
+ if(library_initialized == 0) {
+ BigIntegerInitialize();
+ t_stronginitrand();
+ library_initialized = 1;
+ }
+ return SRP_SUCCESS;
+}
+
+_TYPE( SRP_RESULT )
+SRP_finalize_library()
+{
+ if(library_initialized > 0) {
+ library_initialized = 0;
+ BigIntegerFinalize();
+ }
+ return SRP_SUCCESS;
+}
+
+static int srp_modulus_min_bits = SRP_DEFAULT_MIN_BITS;
+
+_TYPE( SRP_RESULT )
+SRP_set_modulus_min_bits(int minbits)
+{
+ srp_modulus_min_bits = minbits;
+ return SRP_SUCCESS;
+}
+
+_TYPE( int )
+SRP_get_modulus_min_bits()
+{
+ return srp_modulus_min_bits;
+}
+
+static int
+default_secret_bits_cb(int modsize)
+{
+ return 256;
+ /*return modsize;*/ /* Warning: Very Slow */
+}
+
+static SRP_SECRET_BITS_CB srp_sb_cb = default_secret_bits_cb;
+
+_TYPE( SRP_RESULT )
+SRP_set_secret_bits_cb(SRP_SECRET_BITS_CB cb)
+{
+ srp_sb_cb = cb;
+ return SRP_SUCCESS;
+}
+
+_TYPE( int )
+SRP_get_secret_bits(int modsize)
+{
+ return (*srp_sb_cb)(modsize);
+}
+
+_TYPE( SRP * )
+SRP_new(SRP_METHOD * meth)
+{
+ SRP * srp = (SRP *) malloc(sizeof(SRP));
+
+ if(srp == NULL)
+ return NULL;
+
+ srp->flags = 0;
+ srp->username = cstr_new();
+ srp->bctx = BigIntegerCtxNew();
+ srp->modulus = NULL;
+ srp->accel = NULL;
+ srp->generator = NULL;
+ srp->salt = NULL;
+ srp->verifier = NULL;
+ srp->password = NULL;
+ srp->pubkey = NULL;
+ srp->secret = NULL;
+ srp->u = NULL;
+ srp->key = NULL;
+ srp->ex_data = cstr_new();
+ srp->param_cb = NULL;
+ srp->meth = meth;
+ srp->meth_data = NULL;
+ //srp->slu = NULL;
+ if(srp->meth->init == NULL || (*srp->meth->init)(srp) == SRP_SUCCESS)
+ return srp;
+ free(srp);
+ return NULL;
+}
+
+_TYPE( SRP_RESULT )
+SRP_free(SRP * srp)
+{
+ if(srp->meth->finish)
+ (*srp->meth->finish)(srp);
+
+ if(srp->username)
+ cstr_clear_free(srp->username);
+ if(srp->modulus)
+ BigIntegerFree(srp->modulus);
+ if(srp->accel)
+ BigIntegerModAccelFree(srp->accel);
+ if(srp->generator)
+ BigIntegerFree(srp->generator);
+ if(srp->salt)
+ cstr_clear_free(srp->salt);
+ if(srp->verifier)
+ BigIntegerClearFree(srp->verifier);
+ if(srp->password)
+ BigIntegerClearFree(srp->password);
+ if(srp->pubkey)
+ BigIntegerFree(srp->pubkey);
+ if(srp->secret)
+ BigIntegerClearFree(srp->secret);
+ if(srp->u)
+ BigIntegerFree(srp->u);
+ if(srp->key)
+ BigIntegerClearFree(srp->key);
+ if(srp->bctx)
+ BigIntegerCtxFree(srp->bctx);
+ if(srp->ex_data)
+ cstr_clear_free(srp->ex_data);
+ free(srp);
+ return SRP_SUCCESS;
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_client_param_verify_cb(SRP * srp, SRP_CLIENT_PARAM_VERIFY_CB cb)
+{
+ srp->param_cb = cb;
+ return SRP_SUCCESS;
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_username(SRP * srp, const char * username)
+{
+ cstr_set(srp->username, username);
+ return SRP_SUCCESS;
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_user_raw(SRP * srp, const unsigned char * user, int userlen)
+{
+ cstr_setn(srp->username, (const char*)user, userlen);
+ return SRP_SUCCESS;
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_params(SRP * srp, const unsigned char * modulus, int modlen,
+ const unsigned char * generator, int genlen,
+ const unsigned char * salt, int saltlen)
+{
+ SRP_RESULT rc;
+
+ if(modulus == NULL || generator == NULL || salt == NULL)
+ return SRP_ERROR;
+
+ /* Set fields in SRP context */
+ srp->modulus = BigIntegerFromBytes(modulus, modlen);
+ if(srp->flags & SRP_FLAG_MOD_ACCEL)
+ srp->accel = BigIntegerModAccelNew(srp->modulus, srp->bctx);
+ srp->generator = BigIntegerFromBytes(generator, genlen);
+ if(srp->salt == NULL)
+ srp->salt = cstr_new();
+ cstr_setn(srp->salt, (const char*)salt, saltlen);
+
+ /* Now attempt to validate parameters */
+ if(BigIntegerBitLen(srp->modulus) < SRP_get_modulus_min_bits())
+ return SRP_ERROR;
+
+ if(srp->param_cb) {
+ rc = (*srp->param_cb)(srp, modulus, modlen, generator, genlen);
+ if(!SRP_OK(rc))
+ return rc;
+ }
+
+ return (*srp->meth->params)(srp, modulus, modlen, generator, genlen,
+ salt, saltlen);
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_authenticator(SRP * srp, const unsigned char * a, int alen)
+{
+ return (*srp->meth->auth)(srp, a, alen);
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_auth_password(SRP * srp, const char * password)
+{
+ return (*srp->meth->passwd)(srp, (const unsigned char *)password,
+ strlen(password));
+}
+
+_TYPE( SRP_RESULT )
+SRP_set_auth_password_raw(SRP * srp,
+ const unsigned char * password, int passlen)
+{
+ return (*srp->meth->passwd)(srp, password, passlen);
+}
+
+_TYPE( SRP_RESULT )
+SRP_gen_pub(SRP * srp, cstr ** result)
+{
+ return (*srp->meth->genpub)(srp, result);
+}
+
+_TYPE( SRP_RESULT )
+SRP_add_ex_data(SRP * srp, const unsigned char * data, int datalen)
+{
+ cstr_appendn(srp->ex_data, (const char*)data, datalen);
+ return SRP_SUCCESS;
+}
+
+_TYPE( SRP_RESULT )
+SRP_compute_key(SRP * srp, cstr ** result,
+ const unsigned char * pubkey, int pubkeylen)
+{
+ return (*srp->meth->key)(srp, result, pubkey, pubkeylen);
+}
+
+_TYPE( SRP_RESULT )
+SRP_verify(SRP * srp, const unsigned char * proof, int prooflen)
+{
+ return (*srp->meth->verify)(srp, proof, prooflen);
+}
+
+_TYPE( SRP_RESULT )
+SRP_respond(SRP * srp, cstr ** proof)
+{
+ return (*srp->meth->respond)(srp, proof);
+}
+
+_TYPE( SRP_RESULT )
+SRP_use_engine(const char * engine)
+{
+ if(BigIntegerOK(BigIntegerUseEngine(engine)))
+ return SRP_SUCCESS;
+ else
+ return SRP_ERROR;
+}
diff --git a/3rd_party/libsrp6a-sha512/srp.h b/3rd_party/libsrp6a-sha512/srp.h
new file mode 100644
index 0000000..b1d46af
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/srp.h
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+#ifndef _SRP_H_
+#define _SRP_H_
+
+#include "cstr.h"
+#include "srp_aux.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* SRP library version identification */
+#define SRP_VERSION_MAJOR 2
+#define SRP_VERSION_MINOR 0
+#define SRP_VERSION_PATCHLEVEL 1
+
+typedef int SRP_RESULT;
+/* Returned codes for SRP API functions */
+#define SRP_OK(v) ((v) == SRP_SUCCESS)
+#define SRP_SUCCESS 0
+#define SRP_ERROR -1
+
+/* Set the minimum number of bits acceptable in an SRP modulus */
+#define SRP_DEFAULT_MIN_BITS 512
+_TYPE( SRP_RESULT ) SRP_set_modulus_min_bits P((int minbits));
+_TYPE( int ) SRP_get_modulus_min_bits P((void));
+
+/*
+ * Sets the "secret size callback" function.
+ * This function is called with the modulus size in bits,
+ * and returns the size of the secret exponent in bits.
+ * The default function always returns 256 bits.
+ */
+typedef int (_CDECL * SRP_SECRET_BITS_CB)(int modsize);
+_TYPE( SRP_RESULT ) SRP_set_secret_bits_cb P((SRP_SECRET_BITS_CB cb));
+_TYPE( int ) SRP_get_secret_bits P((int modsize));
+
+typedef struct srp_st SRP;
+
+#if 0
+/* Server Lookup API */
+typedef struct srp_server_lu_st SRP_SERVER_LOOKUP;
+
+typedef struct srp_s_lu_meth_st {
+ const char * name;
+
+ SRP_RESULT (_CDECL * init)(SRP_SERVER_LOOKUP * slu);
+ SRP_RESULT (_CDECL * finish)(SRP_SERVER_LOOKUP * slu);
+
+ SRP_RESULT (_CDECL * lookup)(SRP_SERVER_LOOKUP * slu, SRP * srp, cstr * username);
+
+ void * meth_data;
+} SRP_SERVER_LOOKUP_METHOD;
+
+struct srp_server_lu_st {
+ SRP_SERVER_LOOKUP_METHOD * meth;
+ void * data;
+};
+
+/*
+ * The Server Lookup API deals with the server-side issue of
+ * mapping usernames to verifiers. Given a username, a lookup
+ * mechanism needs to provide parameters (N, g), salt (s), and
+ * password verifier (v) for that user.
+ *
+ * A SRP_SERVER_LOOKUP_METHOD describes the general mechanism
+ * for performing lookups (e.g. files, LDAP, database, etc.)
+ * A SRP_SERVER_LOOKUP is an active "object" that is actually
+ * called to do lookups.
+ */
+_TYPE( SRP_SERVER_LOOKUP * )
+ SRP_SERVER_LOOKUP_new P((SRP_SERVER_LOOKUP_METHOD * meth));
+_TYPE( SRP_RESULT ) SRP_SERVER_LOOKUP_free P((SRP_SERVER_LOOKUP * slu));
+_TYPE( SRP_RESULT ) SRP_SERVER_do_lookup P((SRP_SERVER_LOOKUP * slu,
+ SRP * srp, cstr * username));
+
+/*
+ * SRP_SERVER_system_lookup supercedes SRP_server_init_user.
+ */
+_TYPE( SRP_SERVER_LOOKUP * ) SRP_SERVER_system_lookup P((void));
+#endif
+
+/*
+ * Client Parameter Verification API
+ *
+ * This callback is called from the SRP client when the
+ * parameters (modulus and generator) are set. The callback
+ * should return SRP_SUCCESS if the parameters are okay,
+ * otherwise some error code to indicate that the parameters
+ * should be rejected.
+ */
+typedef SRP_RESULT (_CDECL * SRP_CLIENT_PARAM_VERIFY_CB)(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
+
+#if 0
+/* The default parameter verifier function */
+_TYPE( SRP_RESULT ) SRP_CLIENT_default_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
+/* A parameter verifier that only accepts builtin params (no prime test) */
+_TYPE( SRP_RESULT ) SRP_CLIENT_builtin_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
+/* The "classic" parameter verifier that accepts either builtin params
+ * immediately, and performs safe-prime tests on N and primitive-root
+ * tests on g otherwise. SECURITY WARNING: This may allow for certain
+ * attacks based on "trapdoor" moduli, so this is not recommended. */
+_TYPE( SRP_RESULT ) SRP_CLIENT_compat_param_verify_cb(SRP * srp, const unsigned char * mod, int modlen, const unsigned char * gen, int genlen);
+
+#endif
+
+/*
+ * Main SRP API - SRP and SRP_METHOD
+ */
+
+/* SRP method definitions */
+typedef struct srp_meth_st {
+ const char * name;
+
+ SRP_RESULT (_CDECL * init)(SRP * srp);
+ SRP_RESULT (_CDECL * finish)(SRP * srp);
+
+ SRP_RESULT (_CDECL * params)(SRP * srp,
+ const unsigned char * modulus, int modlen,
+ const unsigned char * generator, int genlen,
+ const unsigned char * salt, int saltlen);
+ SRP_RESULT (_CDECL * auth)(SRP * srp, const unsigned char * a, int alen);
+ SRP_RESULT (_CDECL * passwd)(SRP * srp,
+ const unsigned char * pass, int passlen);
+ SRP_RESULT (_CDECL * genpub)(SRP * srp, cstr ** result);
+ SRP_RESULT (_CDECL * key)(SRP * srp, cstr ** result,
+ const unsigned char * pubkey, int pubkeylen);
+ SRP_RESULT (_CDECL * verify)(SRP * srp,
+ const unsigned char * proof, int prooflen);
+ SRP_RESULT (_CDECL * respond)(SRP * srp, cstr ** proof);
+
+ void * data;
+} SRP_METHOD;
+
+/* Magic numbers for the SRP context header */
+#define SRP_MAGIC_CLIENT 12
+#define SRP_MAGIC_SERVER 28
+
+/* Flag bits for SRP struct */
+#define SRP_FLAG_MOD_ACCEL 0x1 /* accelerate modexp operations */
+#define SRP_FLAG_LEFT_PAD 0x2 /* left-pad to length-of-N inside hashes */
+
+/*
+ * A hybrid structure that represents either client or server state.
+ */
+struct srp_st {
+ int magic; /* To distinguish client from server (and for sanity) */
+
+ int flags;
+
+ cstr * username;
+
+ BigInteger modulus;
+ BigInteger generator;
+ cstr * salt;
+
+ BigInteger verifier;
+ BigInteger password;
+
+ BigInteger pubkey;
+ BigInteger secret;
+ BigInteger u;
+
+ BigInteger key;
+
+ cstr * ex_data;
+
+ SRP_METHOD * meth;
+ void * meth_data;
+
+ BigIntegerCtx bctx; /* to cache temporaries if available */
+ BigIntegerModAccel accel; /* to accelerate modexp if available */
+
+ SRP_CLIENT_PARAM_VERIFY_CB param_cb; /* to verify params */
+ //SRP_SERVER_LOOKUP * slu; /* to look up users */
+};
+
+/*
+ * Global initialization/de-initialization functions.
+ * Call SRP_initialize_library before using the library,
+ * and SRP_finalize_library when done.
+ */
+_TYPE( SRP_RESULT ) SRP_initialize_library();
+_TYPE( SRP_RESULT ) SRP_finalize_library();
+
+/*
+ * SRP_new() creates a new SRP context object -
+ * the method determines which "sense" (client or server)
+ * the object operates in. SRP_free() frees it.
+ * (See RFC2945 method definitions below.)
+ */
+_TYPE( SRP * ) SRP_new P((SRP_METHOD * meth));
+_TYPE( SRP_RESULT ) SRP_free P((SRP * srp));
+
+#if 0
+/*
+ * Use the supplied lookup object to look up user parameters and
+ * password verifier. The lookup function gets called during
+ * SRP_set_username/SRP_set_user_raw below. Using this function
+ * means that the server can avoid calling SRP_set_params and
+ * SRP_set_authenticator, since the lookup function handles that
+ * internally.
+ */
+_TYPE( SRP_RESULT ) SRP_set_server_lookup P((SRP * srp,
+ SRP_SERVER_LOOKUP * lookup));
+#endif
+
+/*
+ * Use the supplied callback function to verify parameters
+ * (modulus, generator) given to the client.
+ */
+_TYPE( SRP_RESULT )
+ SRP_set_client_param_verify_cb P((SRP * srp,
+ SRP_CLIENT_PARAM_VERIFY_CB cb));
+
+/*
+ * Both client and server must call both SRP_set_username and
+ * SRP_set_params, in that order, before calling anything else.
+ * SRP_set_user_raw is an alternative to SRP_set_username that
+ * accepts an arbitrary length-bounded octet string as input.
+ */
+_TYPE( SRP_RESULT ) SRP_set_username P((SRP * srp, const char * username));
+_TYPE( SRP_RESULT ) SRP_set_user_raw P((SRP * srp, const unsigned char * user,
+ int userlen));
+_TYPE( SRP_RESULT )
+ SRP_set_params P((SRP * srp,
+ const unsigned char * modulus, int modlen,
+ const unsigned char * generator, int genlen,
+ const unsigned char * salt, int saltlen));
+
+/*
+ * On the client, SRP_set_authenticator, SRP_gen_exp, and
+ * SRP_add_ex_data can be called in any order.
+ * On the server, SRP_set_authenticator must come first,
+ * followed by SRP_gen_exp and SRP_add_ex_data in either order.
+ */
+/*
+ * The authenticator is the secret possessed by either side.
+ * For the server, this is the bigendian verifier, as an octet string.
+ * For the client, this is the bigendian raw secret, as an octet string.
+ * The server's authenticator must be the generator raised to the power
+ * of the client's raw secret modulo the common modulus for authentication
+ * to succeed.
+ *
+ * SRP_set_auth_password computes the authenticator from a plaintext
+ * password and then calls SRP_set_authenticator automatically. This is
+ * usually used on the client side, while the server usually uses
+ * SRP_set_authenticator (since it doesn't know the plaintext password).
+ */
+_TYPE( SRP_RESULT )
+ SRP_set_authenticator P((SRP * srp, const unsigned char * a, int alen));
+_TYPE( SRP_RESULT )
+ SRP_set_auth_password P((SRP * srp, const char * password));
+_TYPE( SRP_RESULT )
+ SRP_set_auth_password_raw P((SRP * srp,
+ const unsigned char * password,
+ int passlen));
+
+/*
+ * SRP_gen_pub generates the random exponential residue to send
+ * to the other side. If using SRP-3/RFC2945, the server must
+ * withhold its result until it receives the client's number.
+ * If using SRP-6, the server can send its value immediately
+ * without waiting for the client.
+ *
+ * If "result" points to a NULL pointer, a new cstr object will be
+ * created to hold the result, and "result" will point to it.
+ * If "result" points to a non-NULL cstr pointer, the result will be
+ * placed there.
+ * If "result" itself is NULL, no result will be returned,
+ * although the big integer value will still be available
+ * through srp->pubkey in the SRP struct.
+ */
+_TYPE( SRP_RESULT ) SRP_gen_pub P((SRP * srp, cstr ** result));
+/*
+ * Append the data to the extra data segment. Authentication will
+ * not succeed unless both sides add precisely the same data in
+ * the same order.
+ */
+_TYPE( SRP_RESULT ) SRP_add_ex_data P((SRP * srp, const unsigned char * data,
+ int datalen));
+
+/*
+ * SRP_compute_key must be called after the previous three methods.
+ */
+_TYPE( SRP_RESULT ) SRP_compute_key P((SRP * srp, cstr ** result,
+ const unsigned char * pubkey,
+ int pubkeylen));
+
+/*
+ * On the client, call SRP_respond first to get the response to send
+ * to the server, and call SRP_verify to verify the server's response.
+ * On the server, call SRP_verify first to verify the client's response,
+ * and call SRP_respond ONLY if verification succeeds.
+ *
+ * It is an error to call SRP_respond with a NULL pointer.
+ */
+_TYPE( SRP_RESULT ) SRP_verify P((SRP * srp,
+ const unsigned char * proof, int prooflen));
+_TYPE( SRP_RESULT ) SRP_respond P((SRP * srp, cstr ** response));
+
+/* RFC2945-style SRP authentication */
+
+#define RFC2945_KEY_LEN 40 /* length of session key (bytes) */
+#define RFC2945_RESP_LEN 20 /* length of proof hashes (bytes) */
+
+/*
+ * RFC2945-style SRP authentication methods. Use these like:
+ * SRP * srp = SRP_new(SRP_RFC2945_client_method());
+ */
+_TYPE( SRP_METHOD * ) SRP_RFC2945_client_method P((void));
+_TYPE( SRP_METHOD * ) SRP_RFC2945_server_method P((void));
+
+/*
+ * SRP-6 and SRP-6a authentication methods.
+ * SRP-6a is recommended for better resistance to 2-for-1 attacks.
+ */
+_TYPE( SRP_METHOD * ) SRP6_client_method P((void));
+_TYPE( SRP_METHOD * ) SRP6_server_method P((void));
+_TYPE( SRP_METHOD * ) SRP6a_client_method P((void));
+_TYPE( SRP_METHOD * ) SRP6a_server_method P((void));
+
+_TYPE( SRP_METHOD * ) SRP6a_sha512_client_method P((void));
+
+/*
+ * Convenience function - SRP_server_init_user
+ * Looks up the username from the system EPS configuration and calls
+ * SRP_set_username, SRP_set_params, and SRP_set_authenticator to
+ * initialize server state for that user.
+ *
+ * This is deprecated in favor of SRP_SERVER_system_lookup() and
+ * the Server Lookup API.
+ */
+_TYPE( SRP_RESULT ) SRP_server_init_user P((SRP * srp, const char * username));
+
+/*
+ * Use the named engine for acceleration.
+ */
+_TYPE( SRP_RESULT ) SRP_use_engine P((const char * engine));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SRP_H_ */
diff --git a/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c b/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c
new file mode 100644
index 0000000..db59fe8
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/srp6a_sha512_client.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+#include "t_defines.h"
+#include "srp.h"
+#include "t_sha.h"
+
+/*
+ * SRP-6/6a has two minor refinements relative to SRP-3/RFC2945:
+ * 1. The "g^x" value is multipled by three in the client's
+ * calculation of its session key.
+ * SRP-6a: The "g^x" value is multiplied by the hash of
+ * N and g in the client's session key calculation.
+ * 2. The value of u is taken as the hash of A and B,
+ * instead of the top 32 bits of the hash of B.
+ * This eliminates the old restriction where the
+ * server had to receive A before it could send B.
+ */
+
+/****************************/
+#define SHA512_DIGESTSIZE 64
+#define SRP6_SHA512_KEY_LEN 64
+
+/*
+ * The client keeps track of the running hash
+ * state via SHA512_CTX structures pointed to by the
+ * meth_data pointer. The "hash" member is the hash value that
+ * will be sent to the other side; the "ckhash" member is the
+ * hash value expected from the other side.
+ */
+struct sha512_client_meth_st {
+ SHA512_CTX hash;
+ SHA512_CTX ckhash;
+ unsigned char k[SRP6_SHA512_KEY_LEN];
+};
+
+#define SHA512_CLIENT_CTXP(srp) ((struct sha512_client_meth_st *)(srp)->meth_data)
+
+static SRP_RESULT
+srp6a_sha512_client_init(SRP * srp)
+{
+ srp->magic = SRP_MAGIC_CLIENT;
+ srp->flags = SRP_FLAG_MOD_ACCEL | SRP_FLAG_LEFT_PAD;
+ srp->meth_data = malloc(sizeof(struct sha512_client_meth_st));
+ SHA512Init(&SHA512_CLIENT_CTXP(srp)->hash);
+ SHA512Init(&SHA512_CLIENT_CTXP(srp)->ckhash);
+ return SRP_SUCCESS;
+}
+
+static SRP_RESULT
+srp6_sha512_client_finish(SRP * srp)
+{
+ if(srp->meth_data) {
+ memset(srp->meth_data, 0, sizeof(struct sha512_client_meth_st));
+ free(srp->meth_data);
+ }
+ return SRP_SUCCESS;
+}
+
+static SRP_RESULT
+srp6_sha512_client_params(SRP * srp, const unsigned char * modulus, int modlen,
+ const unsigned char * generator, int genlen,
+ const unsigned char * salt, int saltlen)
+{
+ int i;
+ unsigned char buf1[SHA512_DIGESTSIZE], buf2[SHA512_DIGESTSIZE];
+ SHA512_CTX ctxt;
+
+ /* Fields set by SRP_set_params */
+
+ /* Update hash state */
+ SHA512Init(&ctxt);
+ SHA512Update(&ctxt, modulus, modlen);
+ SHA512Final(buf1, &ctxt); /* buf1 = H(modulus) */
+
+ SHA512Init(&ctxt);
+ SHA512Update(&ctxt, generator, genlen);
+ SHA512Final(buf2, &ctxt); /* buf2 = H(generator) */
+
+ for(i = 0; i < sizeof(buf1); ++i)
+ buf1[i] ^= buf2[i]; /* buf1 = H(modulus) xor H(generator) */
+
+ /* hash: H(N) xor H(g) */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, buf1, sizeof(buf1));
+
+ SHA512Init(&ctxt);
+ SHA512Update(&ctxt, srp->username->data, srp->username->length);
+ SHA512Final(buf1, &ctxt); /* buf1 = H(user) */
+
+ /* hash: (H(N) xor H(g)) | H(U) */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, buf1, sizeof(buf1));
+
+ /* hash: (H(N) xor H(g)) | H(U) | s */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, salt, saltlen);
+
+ return SRP_SUCCESS;
+}
+
+static SRP_RESULT
+srp6_sha512_client_auth(SRP * srp, const unsigned char * a, int alen)
+{
+ /* On the client, the authenticator is the raw password-derived hash */
+ srp->password = BigIntegerFromBytes(a, alen);
+
+ /* verifier = g^x mod N */
+ srp->verifier = BigIntegerFromInt(0);
+ BigIntegerModExp(srp->verifier, srp->generator, srp->password, srp->modulus, srp->bctx, srp->accel);
+
+ return SRP_SUCCESS;
+}
+
+static SRP_RESULT
+srp6_sha512_client_passwd(SRP * srp, const unsigned char * p, int plen)
+{
+ SHA512_CTX ctxt;
+ unsigned char dig[SHA512_DIGESTSIZE];
+ int r;
+
+ SHA512Init(&ctxt);
+ SHA512Update(&ctxt, srp->username->data, srp->username->length);
+ SHA512Update(&ctxt, ":", 1);
+ SHA512Update(&ctxt, p, plen);
+ SHA512Final(dig, &ctxt); /* dig = H(U | ":" | P) */
+
+ SHA512Init(&ctxt);
+ SHA512Update(&ctxt, srp->salt->data, srp->salt->length);
+ SHA512Update(&ctxt, dig, sizeof(dig));
+ SHA512Final(dig, &ctxt); /* dig = H(s | H(U | ":" | P)) */
+ memset(&ctxt, 0, sizeof(ctxt));
+
+ r = SRP_set_authenticator(srp, dig, sizeof(dig));
+ memset(dig, 0, sizeof(dig));
+
+ return r;
+}
+
+static SRP_RESULT
+srp6_sha512_client_genpub(SRP * srp, cstr ** result)
+{
+ cstr * astr;
+ int slen = (SRP_get_secret_bits(BigIntegerBitLen(srp->modulus)) + 7) / 8;
+
+ if(result == NULL)
+ astr = cstr_new();
+ else {
+ if(*result == NULL)
+ *result = cstr_new();
+ astr = *result;
+ }
+
+ cstr_set_length(astr, BigIntegerByteLen(srp->modulus));
+ t_random((unsigned char*)astr->data, slen);
+ srp->secret = BigIntegerFromBytes((const unsigned char*)astr->data, slen);
+ /* Force g^a mod n to "wrap around" by adding log[2](n) to "a". */
+ BigIntegerAddInt(srp->secret, srp->secret, BigIntegerBitLen(srp->modulus));
+ /* A = g^a mod n */
+ srp->pubkey = BigIntegerFromInt(0);
+ BigIntegerModExp(srp->pubkey, srp->generator, srp->secret, srp->modulus, srp->bctx, srp->accel);
+ BigIntegerToCstr(srp->pubkey, astr);
+
+ /* hash: (H(N) xor H(g)) | H(U) | s | A */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, astr->data, astr->length);
+ /* ckhash: A */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, astr->data, astr->length);
+
+ if(result == NULL) /* astr was a temporary */
+ cstr_clear_free(astr);
+
+ return SRP_SUCCESS;
+}
+
+static SRP_RESULT
+srp6_sha512_client_key_ex(SRP * srp, cstr ** result,
+ const unsigned char * pubkey, int pubkeylen, BigInteger k)
+{
+ SHA512_CTX ctxt;
+ unsigned char dig[SHA512_DIGESTSIZE];
+ BigInteger gb, e;
+ cstr * s;
+ int modlen;
+
+ modlen = BigIntegerByteLen(srp->modulus);
+ if(pubkeylen > modlen)
+ return SRP_ERROR;
+
+ /* Compute u from client's and server's values */
+ SHA512Init(&ctxt);
+ /* Use s as a temporary to store client's value */
+ s = cstr_new();
+ if(srp->flags & SRP_FLAG_LEFT_PAD) {
+ BigIntegerToCstrEx(srp->pubkey, s, modlen);
+ SHA512Update(&ctxt, s->data, s->length);
+ if(pubkeylen < modlen) {
+ memcpy(s->data + (modlen - pubkeylen), pubkey, pubkeylen);
+ memset(s->data, 0, modlen - pubkeylen);
+ SHA512Update(&ctxt, s->data, modlen);
+ }
+ else
+ SHA512Update(&ctxt, pubkey, pubkeylen);
+ }
+ else {
+ BigIntegerToCstr(srp->pubkey, s);
+ SHA512Update(&ctxt, s->data, s->length);
+ SHA512Update(&ctxt, pubkey, pubkeylen);
+ }
+ SHA512Final(dig, &ctxt);
+ srp->u = BigIntegerFromBytes(dig, SHA512_DIGESTSIZE);
+
+ /* hash: (H(N) xor H(g)) | H(U) | s | A | B */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, pubkey, pubkeylen);
+
+ gb = BigIntegerFromBytes(pubkey, pubkeylen);
+ /* reject B == 0, B >= modulus */
+ if(BigIntegerCmp(gb, srp->modulus) >= 0 || BigIntegerCmpInt(gb, 0) == 0) {
+ BigIntegerFree(gb);
+ cstr_clear_free(s);
+ return SRP_ERROR;
+ }
+ e = BigIntegerFromInt(0);
+ srp->key = BigIntegerFromInt(0);
+ /* unblind g^b (mod N) */
+ BigIntegerSub(srp->key, srp->modulus, srp->verifier);
+ /* use e as temporary, e == -k*v (mod N) */
+ BigIntegerMul(e, k, srp->key, srp->bctx);
+ BigIntegerAdd(e, e, gb);
+ BigIntegerMod(gb, e, srp->modulus, srp->bctx);
+
+ /* compute gb^(a + ux) (mod N) */
+ BigIntegerMul(e, srp->password, srp->u, srp->bctx);
+ BigIntegerAdd(e, e, srp->secret); /* e = a + ux */
+
+ BigIntegerModExp(srp->key, gb, e, srp->modulus, srp->bctx, srp->accel);
+ BigIntegerClearFree(e);
+ BigIntegerClearFree(gb);
+
+ /* convert srp->key into a session key, update hash states */
+ BigIntegerToCstr(srp->key, s);
+ SHA512Init(&ctxt);
+ SHA512Update(&ctxt, s->data, s->length);
+ SHA512Final((unsigned char*)&SHA512_CLIENT_CTXP(srp)->k, &ctxt);
+ cstr_clear_free(s);
+
+ /* hash: (H(N) xor H(g)) | H(U) | s | A | B | K */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash, SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
+ /* hash: (H(N) xor H(g)) | H(U) | s | A | B | K | ex_data */
+ if(srp->ex_data->length > 0)
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->hash,
+ srp->ex_data->data, srp->ex_data->length);
+ if(result) {
+ if(*result == NULL)
+ *result = cstr_new();
+ cstr_setn(*result, (const char*)SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
+ }
+
+ return SRP_SUCCESS;
+}
+
+static SRP_RESULT
+srp6a_sha512_client_key(SRP * srp, cstr ** result,
+ const unsigned char * pubkey, int pubkeylen)
+{
+ SRP_RESULT ret;
+ BigInteger k;
+ cstr * s;
+ SHA512_CTX ctxt;
+ unsigned char dig[SHA512_DIGESTSIZE];
+
+ SHA512Init(&ctxt);
+ s = cstr_new();
+ BigIntegerToCstr(srp->modulus, s);
+ SHA512Update(&ctxt, s->data, s->length);
+ if(srp->flags & SRP_FLAG_LEFT_PAD)
+ BigIntegerToCstrEx(srp->generator, s, s->length);
+ else
+ BigIntegerToCstr(srp->generator, s);
+ SHA512Update(&ctxt, s->data, s->length);
+ SHA512Final(dig, &ctxt);
+ cstr_free(s);
+
+ k = BigIntegerFromBytes(dig, SHA512_DIGESTSIZE);
+ if(BigIntegerCmpInt(k, 0) == 0)
+ ret = SRP_ERROR;
+ else
+ ret = srp6_sha512_client_key_ex(srp, result, pubkey, pubkeylen, k);
+ BigIntegerClearFree(k);
+ return ret;
+}
+
+static SRP_RESULT
+srp6_sha512_client_verify(SRP * srp, const unsigned char * proof, int prooflen)
+{
+ unsigned char expected[SHA512_DIGESTSIZE];
+
+ SHA512Final(expected, &SHA512_CLIENT_CTXP(srp)->ckhash);
+ if(prooflen == SHA512_DIGESTSIZE && memcmp(expected, proof, prooflen) == 0)
+ return SRP_SUCCESS;
+ else
+ return SRP_ERROR;
+}
+
+static SRP_RESULT
+srp6_sha512_client_respond(SRP * srp, cstr ** proof)
+{
+ if(proof == NULL)
+ return SRP_ERROR;
+
+ if(*proof == NULL)
+ *proof = cstr_new();
+
+ /* proof contains client's response */
+ cstr_set_length(*proof, SHA512_DIGESTSIZE);
+ SHA512Final((unsigned char*)(*proof)->data, &SHA512_CLIENT_CTXP(srp)->hash);
+
+ /* ckhash: A | M | K */
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, (*proof)->data, (*proof)->length);
+ SHA512Update(&SHA512_CLIENT_CTXP(srp)->ckhash, SHA512_CLIENT_CTXP(srp)->k, SRP6_SHA512_KEY_LEN);
+ return SRP_SUCCESS;
+}
+
+static SRP_METHOD srp6a_sha512_client_meth = {
+ "SRP-6a sha512 client (tjw)",
+ srp6a_sha512_client_init,
+ srp6_sha512_client_finish,
+ srp6_sha512_client_params,
+ srp6_sha512_client_auth,
+ srp6_sha512_client_passwd,
+ srp6_sha512_client_genpub,
+ srp6a_sha512_client_key,
+ srp6_sha512_client_verify,
+ srp6_sha512_client_respond,
+ NULL
+};
+
+_TYPE( SRP_METHOD * )
+SRP6a_sha512_client_method()
+{
+ return &srp6a_sha512_client_meth;
+}
diff --git a/3rd_party/libsrp6a-sha512/srp_aux.h b/3rd_party/libsrp6a-sha512/srp_aux.h
new file mode 100644
index 0000000..5088f08
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/srp_aux.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+#ifndef SRP_AUX_H
+#define SRP_AUX_H
+
+#include "cstr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BigInteger abstraction API */
+
+#ifndef MATH_PRIV
+typedef void * BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+#endif
+
+/*
+ * Some functions return a BigIntegerResult.
+ * Use BigIntegerOK to test for success.
+ */
+#define BIG_INTEGER_SUCCESS 0
+#define BIG_INTEGER_ERROR -1
+#define BigIntegerOK(v) ((v) == BIG_INTEGER_SUCCESS)
+typedef int BigIntegerResult;
+
+_TYPE( BigInteger ) BigIntegerFromInt P((unsigned int number));
+_TYPE( BigInteger ) BigIntegerFromBytes P((const unsigned char * bytes,
+ int length));
+#define BigIntegerByteLen(X) ((BigIntegerBitLen(X)+7)/8)
+_TYPE( int ) BigIntegerToBytes P((BigInteger src,
+ unsigned char * dest, int destlen));
+_TYPE( BigIntegerResult ) BigIntegerToCstr P((BigInteger src, cstr * dest));
+_TYPE( BigIntegerResult ) BigIntegerToCstrEx P((BigInteger src, cstr * dest, int len));
+_TYPE( BigIntegerResult ) BigIntegerToHex P((BigInteger src,
+ char * dest, int destlen));
+_TYPE( BigIntegerResult ) BigIntegerToString P((BigInteger src,
+ char * dest, int destlen,
+ unsigned int radix));
+_TYPE( int ) BigIntegerBitLen P((BigInteger b));
+_TYPE( int ) BigIntegerCmp P((BigInteger c1, BigInteger c2));
+_TYPE( int ) BigIntegerCmpInt P((BigInteger c1, unsigned int c2));
+_TYPE( BigIntegerResult ) BigIntegerLShift P((BigInteger result, BigInteger x,
+ unsigned int bits));
+_TYPE( BigIntegerResult ) BigIntegerAdd P((BigInteger result,
+ BigInteger a1, BigInteger a2));
+_TYPE( BigIntegerResult ) BigIntegerAddInt P((BigInteger result,
+ BigInteger a1, unsigned int a2));
+_TYPE( BigIntegerResult ) BigIntegerSub P((BigInteger result,
+ BigInteger s1, BigInteger s2));
+_TYPE( BigIntegerResult ) BigIntegerSubInt P((BigInteger result,
+ BigInteger s1, unsigned int s2));
+/* For BigIntegerMul{,Int}: result != m1, m2 */
+_TYPE( BigIntegerResult ) BigIntegerMul P((BigInteger result, BigInteger m1,
+ BigInteger m2, BigIntegerCtx ctx));
+_TYPE( BigIntegerResult ) BigIntegerMulInt P((BigInteger result,
+ BigInteger m1, unsigned int m2,
+ BigIntegerCtx ctx));
+_TYPE( BigIntegerResult ) BigIntegerDivInt P((BigInteger result,
+ BigInteger d, unsigned int m,
+ BigIntegerCtx ctx));
+_TYPE( BigIntegerResult ) BigIntegerMod P((BigInteger result, BigInteger d,
+ BigInteger m, BigIntegerCtx ctx));
+_TYPE( unsigned int ) BigIntegerModInt P((BigInteger d, unsigned int m,
+ BigIntegerCtx ctx));
+_TYPE( BigIntegerResult ) BigIntegerModMul P((BigInteger result,
+ BigInteger m1, BigInteger m2,
+ BigInteger m, BigIntegerCtx ctx));
+_TYPE( BigIntegerResult ) BigIntegerModExp P((BigInteger result,
+ BigInteger base, BigInteger expt,
+ BigInteger modulus,
+ BigIntegerCtx ctx,
+ BigIntegerModAccel accel));
+_TYPE( int ) BigIntegerCheckPrime P((BigInteger n, BigIntegerCtx ctx));
+
+_TYPE( BigIntegerResult ) BigIntegerFree P((BigInteger b));
+_TYPE( BigIntegerResult ) BigIntegerClearFree P((BigInteger b));
+
+_TYPE( BigIntegerCtx ) BigIntegerCtxNew();
+_TYPE( BigIntegerResult ) BigIntegerCtxFree P((BigIntegerCtx ctx));
+
+_TYPE( BigIntegerModAccel ) BigIntegerModAccelNew P((BigInteger m,
+ BigIntegerCtx ctx));
+_TYPE( BigIntegerResult ) BigIntegerModAccelFree P((BigIntegerModAccel accel));
+
+_TYPE( BigIntegerResult ) BigIntegerInitialize();
+_TYPE( BigIntegerResult ) BigIntegerFinalize();
+
+_TYPE( BigIntegerResult ) BigIntegerUseEngine P((const char * engine));
+_TYPE( BigIntegerResult ) BigIntegerReleaseEngine();
+
+/* Miscellaneous functions - formerly in t_pwd.h */
+
+/*
+ * "t_random" is a cryptographic random number generator, which is seeded
+ * from various high-entropy sources and uses a one-way hash function
+ * in a feedback configuration.
+ * "t_sessionkey" is the interleaved hash used to generate session keys
+ * from a large integer.
+ * "t_mgf1" is an implementation of MGF1 using SHA1 to generate session
+ * keys from large integers, and is preferred over the older
+ * interleaved hash, and is used with SRP6.
+ * "t_getpass" reads a password from the terminal without echoing.
+ */
+_TYPE( void ) t_random P((unsigned char *, unsigned));
+_TYPE( void ) t_stronginitrand();
+_TYPE( unsigned char * )
+ t_sessionkey P((unsigned char *, unsigned char *, unsigned));
+_TYPE( void ) t_mgf1 P((unsigned char *, unsigned,
+ const unsigned char *, unsigned));
+_TYPE( int ) t_getpass P((char *, unsigned, const char *));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SRP_AUX_H */
diff --git a/3rd_party/libsrp6a-sha512/t_conv.c b/3rd_party/libsrp6a-sha512/t_conv.c
new file mode 100644
index 0000000..f7f50e2
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_conv.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+/*#define _POSIX_SOURCE*/
+#include <stdio.h>
+#include "t_defines.h"
+#include "cstr.h"
+
+static int
+hexDigitToInt(c)
+ char c;
+{
+ if(c >= '0' && c <= '9')
+ return c - '0';
+ else if(c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if(c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else
+ return 0;
+}
+
+/*
+ * Convert a hex string to a string of bytes; return size of dst
+ */
+_TYPE( int )
+t_fromhex(dst, src)
+ char * dst;
+ const char * src;
+{
+ register char *chp = dst;
+ register unsigned size = strlen(src);
+
+ /* FIXME: handle whitespace and non-hex digits by setting size and src
+ appropriately. */
+
+ if(size % 2 == 1) {
+ *chp++ = hexDigitToInt(*src++);
+ --size;
+ }
+ while(size > 0) {
+ *chp++ = (hexDigitToInt(*src) << 4) | hexDigitToInt(*(src + 1));
+ src += 2;
+ size -= 2;
+ }
+ return chp - dst;
+}
+
+/*
+ * Convert a string of bytes to their hex representation
+ */
+_TYPE( char * )
+t_tohex(dst, src, size)
+ char * dst;
+ const char * src;
+ unsigned size;
+{
+ int notleading = 0;
+
+ register char *chp = dst;
+ *dst = '\0';
+ if (size != 0) do {
+ if(notleading || *src != '\0') {
+ if(!notleading && (*src & 0xf0) == 0) {
+ sprintf(chp, "%.1X", * (unsigned char *) src);
+ chp += 1;
+ }
+ else {
+ sprintf(chp, "%.2X", * (unsigned char *) src);
+ chp += 2;
+ }
+ notleading = 1;
+ }
+ ++src;
+ } while (--size != 0);
+ return dst;
+}
+
+_TYPE( char * )
+t_tohexcstr(dst, src, size)
+ cstr * dst;
+ const char * src;
+ unsigned size;
+{
+ cstr_set_length(dst, 2 * size + 1);
+ return t_tohex(dst->data, src, size);
+}
+
+static char b64table[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
+
+/*
+ * Convert a base64 string into raw byte array representation.
+ */
+_TYPE( int )
+t_fromb64(dst, src)
+ char * dst;
+ const char * src;
+{
+ unsigned char *a;
+ char *loc;
+ int i, j;
+ unsigned int size;
+
+ while(*src && (*src == ' ' || *src == '\t' || *src == '\n'))
+ ++src;
+ size = strlen(src);
+
+ a = malloc((size + 1) * sizeof(unsigned char));
+ if(a == (unsigned char *) 0)
+ return -1;
+
+ i = 0;
+ while(i < size) {
+ loc = strchr(b64table, src[i]);
+ if(loc == (char *) 0)
+ break;
+ else
+ a[i] = loc - b64table;
+ ++i;
+ }
+ size = i;
+
+ i = size - 1;
+ j = size;
+ while(1) {
+ a[j] = a[i];
+ if(--i < 0)
+ break;
+ a[j] |= (a[i] & 3) << 6;
+ --j;
+ a[j] = (unsigned char) ((a[i] & 0x3c) >> 2);
+ if(--i < 0)
+ break;
+ a[j] |= (a[i] & 0xf) << 4;
+ --j;
+ a[j] = (unsigned char) ((a[i] & 0x30) >> 4);
+ if(--i < 0)
+ break;
+ a[j] |= (a[i] << 2);
+
+ a[--j] = 0;
+ if(--i < 0)
+ break;
+ }
+
+ while(a[j] == 0 && j <= size)
+ ++j;
+
+ memcpy(dst, a + j, size - j + 1);
+ free(a);
+ return size - j + 1;
+}
+
+_TYPE( int )
+t_cstrfromb64(dst, src)
+ cstr * dst;
+ const char * src;
+{
+ int len;
+ cstr_set_length(dst, (strlen(src) * 6 + 7) / 8);
+ len = t_fromb64(dst->data, src);
+ cstr_set_length(dst, len);
+ return len;
+}
+
+/*
+ * Convert a raw byte string into a null-terminated base64 ASCII string.
+ */
+_TYPE( char * )
+t_tob64(dst, src, size)
+ char * dst;
+ const char * src;
+ unsigned size;
+{
+ int c, pos = size % 3;
+ unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0;
+ char *olddst = dst;
+
+ switch(pos) {
+ case 1:
+ b2 = src[0];
+ break;
+ case 2:
+ b1 = src[0];
+ b2 = src[1];
+ break;
+ }
+
+ while(1) {
+ c = (b0 & 0xfc) >> 2;
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4);
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6);
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ c = b2 & 0x3f;
+ if(notleading || c != 0) {
+ *dst++ = b64table[c];
+ notleading = 1;
+ }
+ if(pos >= size)
+ break;
+ else {
+ b0 = src[pos++];
+ b1 = src[pos++];
+ b2 = src[pos++];
+ }
+ }
+
+ *dst++ = '\0';
+ return olddst;
+}
+
+_TYPE( char * )
+t_tob64cstr(dst, src, sz)
+ cstr * dst;
+ const char * src;
+ unsigned int sz;
+{
+ cstr_set_length(dst, (sz * 8 + 5) / 6 + 1);
+ return t_tob64(dst->data, src, sz);
+}
diff --git a/3rd_party/libsrp6a-sha512/t_defines.h b/3rd_party/libsrp6a-sha512/t_defines.h
new file mode 100644
index 0000000..447263f
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_defines.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+#ifndef T_DEFINES_H
+#define T_DEFINES_H
+
+#ifndef P
+#if defined(__STDC__) || defined(__cplusplus)
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#ifndef _DLLDECL
+#define _DLLDECL
+
+#ifdef MSVC15 /* MSVC1.5 support for 16 bit apps */
+#define _MSVC15EXPORT _export
+#define _MSVC20EXPORT
+#define _DLLAPI _export _pascal
+#define _CDECL
+#define _TYPE(a) a _MSVC15EXPORT
+#define DLLEXPORT 1
+
+#elif defined(MSVC20) || (defined(_USRDLL) && defined(SRP_EXPORTS))
+#define _MSVC15EXPORT
+#define _MSVC20EXPORT _declspec(dllexport)
+#define _DLLAPI
+#define _CDECL
+#define _TYPE(a) _MSVC20EXPORT a
+#define DLLEXPORT 1
+
+#else /* Default, non-dll. Use this for Unix or DOS */
+#define _MSVC15DEXPORT
+#define _MSVC20EXPORT
+#define _DLLAPI
+#if defined(WINDOWS) || defined(WIN32)
+#define _CDECL _cdecl
+#else
+#define _CDECL
+#endif
+#define _TYPE(a) a _CDECL
+#endif
+#endif
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#else /* not STDC_HEADERS */
+#ifndef HAVE_STRCHR
+#define strchr index
+#define strrchr rindex
+#endif
+char *strchr(), *strrchr(), *strtok();
+#ifndef HAVE_MEMCPY
+#define memcpy(d, s, n) bcopy((s), (d), (n))
+#endif
+#endif /* not STDC_HEADERS */
+
+#include <sys/types.h>
+
+#if TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#else /* not TIME_WITH_SYS_TIME */
+#if HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#endif /* not TIME_WITH_SYS_TIME */
+
+#if HAVE_TERMIOS_H
+#include <termios.h>
+#define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
+#define GTTY(fd, termio) tcgetattr(fd, termio)
+#define TERMIO struct termios
+#define USE_TERMIOS
+#elif HAVE_TERMIO_H
+#include <sys/ioctl.h>
+#include <termio.h>
+#define STTY(fd, termio) ioctl(fd, TCSETA, termio)
+#define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
+#define TEMRIO struct termio
+#define USE_TERMIO
+#elif HAVE_SGTTY_H
+#include <sgtty.h>
+#define STTY(fd, termio) stty(fd, termio)
+#define GTTY(fd, termio) gtty(fd, termio)
+#define TERMIO struct sgttyb
+#define USE_SGTTY
+#endif
+
+#ifdef WIN32
+#define USE_FTIME 1
+#define USE_RENAME 1
+#define NO_FCHMOD 1
+#endif
+
+#ifdef USE_FTIME
+#include <sys/timeb.h>
+#endif
+
+/* Looking for BigInteger math functions? They've moved to <srp_aux.h>. */
+
+#endif
diff --git a/3rd_party/libsrp6a-sha512/t_math.c b/3rd_party/libsrp6a-sha512/t_math.c
new file mode 100644
index 0000000..88ae12f
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_math.c
@@ -0,0 +1,1008 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+#ifdef OPENSSL
+# include "openssl/opensslv.h"
+# include "openssl/bn.h"
+typedef BIGNUM * BigInteger;
+typedef BN_CTX * BigIntegerCtx;
+typedef BN_MONT_CTX * BigIntegerModAccel;
+#include <limits.h>
+# ifdef OPENSSL_ENGINE
+# include "openssl/engine.h"
+static ENGINE * default_engine = NULL;
+# endif /* OPENSSL_ENGINE */
+typedef int (*modexp_meth)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *mctx);
+static modexp_meth default_modexp = NULL;
+#elif defined(CRYPTOLIB)
+# include "libcrypt.h"
+typedef BigInt BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+#elif defined(GNU_MP)
+# include "gmp.h"
+typedef MP_INT * BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+# if __GNU_MP_VERSION >= 4 || (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR >= 1)
+/* GMP 4.1 and up has fast import/export routines for integer conversion */
+# define GMP_IMPEXP 1
+# endif
+#elif defined(TOMMATH)
+# ifdef TOMCRYPT
+ /* as of v0.96 */
+# include "ltc_tommath.h"
+# else
+# include "tommath.h"
+# endif
+typedef mp_int * BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+#elif defined(GCRYPT)
+# include "gcrypt.h"
+typedef gcry_mpi_t BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+#elif defined(MPI)
+# include "mpi.h"
+typedef mp_int * BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+#elif defined(MBEDTLS)
+#include <mbedtls/bignum.h>
+#include <mbedtls/error.h>
+typedef mbedtls_mpi* BigInteger;
+typedef void * BigIntegerCtx;
+typedef void * BigIntegerModAccel;
+#else
+# error "no math library specified"
+#endif
+#define MATH_PRIV
+
+#include "t_defines.h"
+#include "t_pwd.h"
+#include "srp_aux.h"
+
+/* Math library interface stubs */
+
+BigInteger
+BigIntegerFromInt(n)
+ unsigned int n;
+{
+#ifdef OPENSSL
+ BIGNUM * a = BN_new();
+ if(a)
+ BN_set_word(a, n);
+ return a;
+#elif defined(CRYPTOLIB)
+ return bigInit(n);
+#elif defined(GNU_MP)
+ BigInteger rv = (BigInteger) malloc(sizeof(MP_INT));
+ if(rv)
+ mpz_init_set_ui(rv, n);
+ return rv;
+#elif defined(GCRYPT)
+ BigInteger rv = gcry_mpi_new(32);
+ gcry_mpi_set_ui(rv, n);
+ return rv;
+#elif defined(MPI) || defined(TOMMATH)
+ BigInteger rv = (BigInteger) malloc(sizeof(mp_int));
+ if(rv) {
+ mp_init(rv);
+ mp_set_int(rv, n);
+ }
+ return rv;
+#elif defined(MBEDTLS)
+ mbedtls_mpi* a = (mbedtls_mpi*)malloc(sizeof(mbedtls_mpi));
+ if (a) {
+ mbedtls_mpi_init(a);
+ mbedtls_mpi_lset(a, n);
+ }
+ return a;
+#endif
+}
+
+BigInteger
+BigIntegerFromBytes(bytes, length)
+ const unsigned char * bytes;
+ int length;
+{
+#ifdef OPENSSL
+ BIGNUM * a = BN_new();
+ BN_bin2bn(bytes, length, a);
+ return a;
+#elif defined(CRYPTOLIB)
+ BigInteger rv, t;
+ int i, n;
+
+ rv = bigInit(0);
+ if(rv == NULL)
+ return rv;
+ if(length % 4 == 0)
+ RSA_bufToBig(bytes, length, rv);
+ else { /* Wouldn't need this if cryptolib behaved better */
+ i = length & 0x3;
+ if(length > i)
+ RSA_bufToBig(bytes + i, length - i, rv);
+ for(n = 0; i > 0; --i)
+ n = (n << 8) | *bytes++;
+ t = bigInit(n);
+ bigLeftShift(t, (length & ~0x3) << 3, t);
+ bigAdd(rv, t, rv);
+ freeBignum(t);
+ }
+ return rv;
+#elif defined(GNU_MP)
+ BigInteger rv = (BigInteger) malloc(sizeof(MP_INT));
+
+# ifdef GMP_IMPEXP
+ if(rv) {
+ mpz_init(rv);
+ mpz_import(rv, length, 1, 1, 1, 0, bytes);
+ }
+# else
+ cstr * hexbuf = cstr_new();
+
+ if(hexbuf) {
+ if(rv)
+ mpz_init_set_str(rv, t_tohexcstr(hexbuf, bytes, length), 16);
+ cstr_clear_free(hexbuf);
+ }
+# endif /* GMP_IMPEXP */
+
+ return rv;
+#elif defined(GCRYPT)
+ BigInteger rv;
+ gcry_mpi_scan(&rv, GCRYMPI_FMT_USG, bytes, length, NULL);
+ return rv;
+#elif defined(MPI) || defined(TOMMATH)
+ BigInteger rv = (BigInteger) malloc(sizeof(mp_int));
+ if(rv) {
+ mp_init(rv);
+ mp_read_unsigned_bin(rv, (unsigned char *)bytes, length);
+ }
+ return rv;
+#elif defined(MBEDTLS)
+ mbedtls_mpi* a = (mbedtls_mpi*)malloc(sizeof(mbedtls_mpi));
+ if (a) {
+ mbedtls_mpi_init(a);
+ mbedtls_mpi_read_binary(a, bytes, length);
+ }
+ return a;
+#endif
+}
+
+int
+BigIntegerToBytes(src, dest, destlen)
+ BigInteger src;
+ unsigned char * dest;
+ int destlen;
+{
+#ifdef OPENSSL
+ return BN_bn2bin(src, dest);
+#elif defined(CRYPTOLIB)
+ int i, j;
+ cstr * rawbuf;
+
+ trim(src);
+ i = bigBytes(src);
+ j = (bigBits(src) + 7) / 8;
+ if(i == j)
+ RSA_bigToBuf(src, i, dest);
+ else { /* Wouldn't need this if cryptolib behaved better */
+ rawbuf = cstr_new();
+ cstr_set_length(rawbuf, i);
+ RSA_bigToBuf(src, i, rawbuf->data);
+ memcpy(dest, rawbuf->data + (i-j), j);
+ cstr_clear_free(rawbuf);
+ }
+ return j;
+#elif defined(GNU_MP)
+ size_t r = 0;
+# ifdef GMP_IMPEXP
+ mpz_export(dest, &r, 1, 1, 1, 0, src);
+# else
+ cstr * hexbuf = cstr_new();
+
+ if(hexbuf) {
+ cstr_set_length(hexbuf, mpz_sizeinbase(src, 16) + 1);
+ mpz_get_str(hexbuf->data, 16, src);
+ r = t_fromhex(dest, hexbuf->data);
+ cstr_clear_free(hexbuf);
+ }
+# endif
+ return r;
+#elif defined(GCRYPT)
+ size_t r = 0;
+ gcry_mpi_print(GCRYMPI_FMT_USG, dest, destlen, &r, src);
+ return r;
+#elif defined(MPI) || defined(TOMMATH)
+ mp_to_unsigned_bin(src, dest);
+ return mp_unsigned_bin_size(src);
+#elif defined(MBEDTLS)
+ size_t r = mbedtls_mpi_size(src);
+ mbedtls_mpi_write_binary(src, dest, r);
+ return r;
+#endif
+}
+
+BigIntegerResult
+BigIntegerToCstr(BigInteger x, cstr * out)
+{
+ int n = BigIntegerByteLen(x);
+ if(cstr_set_length(out, n) < 0)
+ return BIG_INTEGER_ERROR;
+ if(cstr_set_length(out, BigIntegerToBytes(x, (unsigned char*)out->data, n)) < 0)
+ return BIG_INTEGER_ERROR;
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerToCstrEx(BigInteger x, cstr * out, int len)
+{
+ int n;
+ if(cstr_set_length(out, len) < 0)
+ return BIG_INTEGER_ERROR;
+#if defined(MBEDTLS)
+ /* mbedtls will prefix the output with zeros if the buffer is larger */
+ mbedtls_mpi_write_binary(x, (unsigned char*)out->data, len);
+#else
+ n = BigIntegerToBytes(x, (unsigned char*)out->data, len);
+ if(n < len) {
+ memmove(out->data + (len - n), out->data, n);
+ memset(out->data, 0, len - n);
+ }
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerToHex(src, dest, destlen)
+ BigInteger src;
+ char * dest;
+ int destlen;
+{
+#ifdef OPENSSL
+ strncpy(dest, BN_bn2hex(src), destlen);
+#elif defined(CRYPTOLIB)
+ trim(src);
+ bigsprint(src, dest);
+#elif defined(GNU_MP)
+ mpz_get_str(dest, 16, src);
+#elif defined(GCRYPT)
+ gcry_mpi_print(GCRYMPI_FMT_HEX, dest, destlen, NULL, src);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_toradix(src, dest, 16);
+#elif defined(MBEDTLS)
+ size_t olen = 0;
+ mbedtls_mpi_write_string(src, 16, dest, destlen, &olen);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+static char b64table[] =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
+
+BigIntegerResult
+BigIntegerToString(src, dest, destlen, radix)
+ BigInteger src;
+ char * dest;
+ int destlen;
+ unsigned int radix;
+{
+ BigInteger t = BigIntegerFromInt(0);
+ char * p = dest;
+ char c;
+
+ *p++ = b64table[BigIntegerModInt(src, radix, NULL)];
+ BigIntegerDivInt(t, src, radix, NULL);
+ while(BigIntegerCmpInt(t, 0) > 0) {
+ *p++ = b64table[BigIntegerModInt(t, radix, NULL)];
+ BigIntegerDivInt(t, t, radix, NULL);
+ }
+ BigIntegerFree(t);
+ *p-- = '\0';
+ /* reverse the string */
+ while(p > dest) {
+ c = *p;
+ *p-- = *dest;
+ *dest++ = c;
+ }
+ return BIG_INTEGER_SUCCESS;
+}
+
+int
+BigIntegerBitLen(b)
+ BigInteger b;
+{
+#ifdef OPENSSL
+ return BN_num_bits(b);
+#elif defined(CRYPTOLIB)
+ return bigBits(b);
+#elif defined(GNU_MP)
+ return mpz_sizeinbase(b, 2);
+#elif defined(GCRYPT)
+ return gcry_mpi_get_nbits(b);
+#elif defined(MPI) || defined(TOMMATH)
+ return mp_count_bits(b);
+#elif defined(MBEDTLS)
+ return (int)mbedtls_mpi_bitlen(b);
+#endif
+}
+
+int
+BigIntegerCmp(c1, c2)
+ BigInteger c1, c2;
+{
+#ifdef OPENSSL
+ return BN_cmp(c1, c2);
+#elif defined(CRYPTOLIB)
+ return bigCompare(c1, c2);
+#elif defined(GNU_MP)
+ return mpz_cmp(c1, c2);
+#elif defined(GCRYPT)
+ return gcry_mpi_cmp(c1, c2);
+#elif defined(MPI) || defined(TOMMATH)
+ return mp_cmp(c1, c2);
+#elif defined(MBEDTLS)
+ return mbedtls_mpi_cmp_mpi(c1, c2);
+#endif
+}
+
+int
+BigIntegerCmpInt(c1, c2)
+ BigInteger c1;
+ unsigned int c2;
+{
+#ifdef OPENSSL
+ BigInteger bc2 = BigIntegerFromInt(c2);
+ int rv = BigIntegerCmp(c1, bc2);
+ BigIntegerFree(bc2);
+ return rv;
+#elif defined(CRYPTOLIB)
+ BigInteger t;
+ int rv;
+
+ t = bigInit(c2);
+ rv = bigCompare(c1, t);
+ freeBignum(t);
+ return rv;
+#elif defined(GNU_MP)
+ return mpz_cmp_ui(c1, c2);
+#elif defined(TOMMATH)
+ return mp_cmp_d(c1, c2);
+#elif defined(GCRYPT)
+ return gcry_mpi_cmp_ui(c1, c2);
+#elif defined(MPI)
+ return mp_cmp_int(c1, c2);
+#elif defined(MBEDTLS)
+ return mbedtls_mpi_cmp_int(c1, c2);
+#endif
+}
+
+BigIntegerResult
+BigIntegerLShift(result, x, bits)
+ BigInteger result, x;
+ unsigned int bits;
+{
+#ifdef OPENSSL
+ BN_lshift(result, x, bits);
+#elif defined(CRYPTOLIB)
+ bigLeftShift(x, bits, result);
+#elif defined(GNU_MP)
+ mpz_mul_2exp(result, x, bits);
+#elif defined(GCRYPT)
+ gcry_mpi_mul_2exp(result, x, bits);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_mul_2d(x, bits, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_copy(result, x);
+ mbedtls_mpi_shift_l(result, bits);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerAdd(result, a1, a2)
+ BigInteger result, a1, a2;
+{
+#ifdef OPENSSL
+ BN_add(result, a1, a2);
+#elif defined(CRYPTOLIB)
+ bigAdd(a1, a2, result);
+#elif defined(GNU_MP)
+ mpz_add(result, a1, a2);
+#elif defined(GCRYPT)
+ gcry_mpi_add(result, a1, a2);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_add(a1, a2, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_add_mpi(result, a1, a2);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerAddInt(result, a1, a2)
+ BigInteger result, a1;
+ unsigned int a2;
+{
+#ifdef OPENSSL
+ if(result != a1)
+ BN_copy(result, a1);
+ BN_add_word(result, a2);
+#elif defined(CRYPTOLIB)
+ BigInteger t;
+
+ t = bigInit(a2);
+ bigAdd(a1, t, result);
+ freeBignum(t);
+#elif defined(GNU_MP)
+ mpz_add_ui(result, a1, a2);
+#elif defined(GCRYPT)
+ gcry_mpi_add_ui(result, a1, a2);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_add_d(a1, a2, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_add_int(result, a1, a2);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerSub(result, s1, s2)
+ BigInteger result, s1, s2;
+{
+#ifdef OPENSSL
+ BN_sub(result, s1, s2);
+#elif defined(CRYPTOLIB)
+ bigSubtract(s1, s2, result);
+#elif defined(GNU_MP)
+ mpz_sub(result, s1, s2);
+#elif defined(GCRYPT)
+ gcry_mpi_sub(result, s1, s2);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_sub(s1, s2, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_sub_mpi(result, s1, s2);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerSubInt(result, s1, s2)
+ BigInteger result, s1;
+ unsigned int s2;
+{
+#ifdef OPENSSL
+ if(result != s1)
+ BN_copy(result, s1);
+ BN_sub_word(result, s2);
+#elif defined(CRYPTOLIB)
+ BigInteger t;
+
+ t = bigInit(s2);
+ bigSubtract(s1, t, result);
+ freeBignum(t);
+#elif defined(GNU_MP)
+ mpz_sub_ui(result, s1, s2);
+#elif defined(GCRYPT)
+ gcry_mpi_sub_ui(result, s1, s2);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_sub_d(s1, s2, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_sub_int(result, s1, s2);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerMul(result, m1, m2, c)
+ BigInteger result, m1, m2;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ BN_CTX * ctx = NULL;
+ if(c == NULL)
+ c = ctx = BN_CTX_new();
+ BN_mul(result, m1, m2, c);
+ if(ctx)
+ BN_CTX_free(ctx);
+#elif defined(CRYPTOLIB)
+ bigMultiply(m1, m2, result);
+#elif defined(GNU_MP)
+ mpz_mul(result, m1, m2);
+#elif defined(GCRYPT)
+ gcry_mpi_mul(result, m1, m2);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_mul(m1, m2, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_mul_mpi(result, m1, m2);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerMulInt(result, m1, m2, c)
+ BigInteger result, m1;
+ unsigned int m2;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ if(result != m1)
+ BN_copy(result, m1);
+ BN_mul_word(result, m2);
+#elif defined(CRYPTOLIB)
+ BigInteger t;
+
+ t = bigInit(m2);
+ bigMultiply(m1, t, result);
+ freeBignum(t);
+#elif defined(GNU_MP)
+ mpz_mul_ui(result, m1, m2);
+#elif defined(GCRYPT)
+ gcry_mpi_mul_ui(result, m1, m2);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_mul_d(m1, m2, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_mul_int(result, m1, m2);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerDivInt(result, d, m, c)
+ BigInteger result, d;
+ unsigned int m;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ if(result != d)
+ BN_copy(result, d);
+ BN_div_word(result, m);
+#elif defined(CRYPTOLIB)
+ BigInteger t, u, q;
+
+ t = bigInit(m);
+ u = bigInit(0);
+ /* We use a separate variable q because cryptolib breaks if result == d */
+ q = bigInit(0);
+ bigDivide(d, t, q, u);
+ freeBignum(t);
+ freeBignum(u);
+ bigCopy(q, result);
+ freeBignum(q);
+#elif defined(GNU_MP)
+# ifdef GMP2
+ mpz_fdiv_q_ui(result, d, m);
+# else
+ mpz_div_ui(result, d, m);
+# endif
+#elif defined(GCRYPT)
+ BigInteger t = BigIntegerFromInt(m);
+ gcry_mpi_div(result, NULL, d, t, -1);
+ BigIntegerFree(t);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_div_d(d, m, result, NULL);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_div_int(result, NULL, d, m);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerMod(result, d, m, c)
+ BigInteger result, d, m;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ BN_CTX * ctx = NULL;
+ if(c == NULL)
+ c = ctx = BN_CTX_new();
+ BN_mod(result, d, m, c);
+ if(ctx)
+ BN_CTX_free(ctx);
+#elif defined(CRYPTOLIB)
+ bigMod(d, m, result);
+#elif defined(GNU_MP)
+ mpz_mod(result, d, m);
+#elif defined(GCRYPT)
+ gcry_mpi_mod(result, d, m);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_mod(d, m, result);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_mod_mpi(result, d, m);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+unsigned int
+BigIntegerModInt(d, m, c)
+ BigInteger d;
+ unsigned int m;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ return BN_mod_word(d, m);
+#elif defined(CRYPTOLIB)
+ BigInteger t, u;
+ unsigned char r[4];
+
+ t = bigInit(m);
+ u = bigInit(0);
+ bigMod(d, t, u);
+ bigToBuf(u, sizeof(r), r);
+ freeBignum(t);
+ freeBignum(u);
+ return r[0] | (r[1] << 8) | (r[2] << 16) | (r[3] << 24);
+#elif defined(GNU_MP)
+ MP_INT result;
+ unsigned int i;
+
+ mpz_init(&result);
+
+/* Define GMP2 if you're using an old gmp.h but want to link against a
+ * newer libgmp.a (e.g. 2.0 or later). */
+
+# ifdef GMP2
+ mpz_fdiv_r_ui(&result, d, m);
+# else
+ mpz_mod_ui(&result, d, m);
+# endif
+ i = mpz_get_ui(&result);
+ mpz_clear(&result);
+ return i;
+#elif defined(GCRYPT)
+ /* TODO: any way to clean this up??? */
+ unsigned char r[4];
+ size_t len, i;
+ unsigned int ret = 0;
+ BigInteger t = BigIntegerFromInt(m);
+ BigInteger a = BigIntegerFromInt(0);
+ gcry_mpi_mod(a, d, t);
+ gcry_mpi_print(GCRYMPI_FMT_USG, r, 4, &len, a);
+ for(i = 0; i < len; ++i)
+ ret = (ret << 8) | r[i];
+ BigIntegerFree(t);
+ BigIntegerFree(a);
+ return ret;
+#elif defined(MPI) || defined(TOMMATH)
+ mp_digit r;
+ mp_mod_d(d, m, &r);
+ return r;
+#elif defined(MBEDTLS)
+ mbedtls_mpi_uint r = 0;
+ mbedtls_mpi_mod_int(&r, d, m);
+ return r;
+#endif
+}
+
+BigIntegerResult
+BigIntegerModMul(r, m1, m2, modulus, c)
+ BigInteger r, m1, m2, modulus;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ BN_CTX * ctx = NULL;
+ if(c == NULL)
+ c = ctx = BN_CTX_new();
+ BN_mod_mul(r, m1, m2, modulus, c);
+ if(ctx)
+ BN_CTX_free(ctx);
+#elif defined(CRYPTOLIB)
+ bigMultiply(m1, m2, r);
+ bigMod(r, modulus, r);
+#elif defined(GNU_MP)
+ mpz_mul(r, m1, m2);
+ mpz_mod(r, r, modulus);
+#elif defined(GCRYPT)
+ gcry_mpi_mulm(r, m1, m2, modulus);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_mulmod(m1, m2, modulus, r);
+#elif defined(MBEDTLS)
+ mbedtls_mpi d;
+ mbedtls_mpi_init(&d);
+ mbedtls_mpi_mul_mpi(&d, m1, m2);
+ mbedtls_mpi_mod_mpi(r, &d, modulus);
+ mbedtls_mpi_free(&d);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerModExp(r, b, e, m, c, a)
+ BigInteger r, b, e, m;
+ BigIntegerCtx c;
+ BigIntegerModAccel a;
+{
+#ifdef OPENSSL
+#if OPENSSL_VERSION_NUMBER >= 0x00906000
+ BN_ULONG B = BN_get_word(b);
+#endif
+ BN_CTX * ctx = NULL;
+ if(c == NULL)
+ c = ctx = BN_CTX_new();
+ if(default_modexp) {
+ (*default_modexp)(r, b, e, m, c, a);
+ }
+ else if(a == NULL) {
+ BN_mod_exp(r, b, e, m, c);
+ }
+#if OPENSSL_VERSION_NUMBER >= 0x00906000
+ else if(B > 0 && B < ULONG_MAX) { /* 0.9.6 and above has mont_word optimization */
+ BN_mod_exp_mont_word(r, B, e, m, c, a);
+ }
+#endif
+ else
+ BN_mod_exp_mont(r, b, e, m, c, a);
+ if(ctx)
+ BN_CTX_free(ctx);
+#elif defined(CRYPTOLIB)
+ bigPow(b, e, m, r);
+#elif defined(GNU_MP)
+ mpz_powm(r, b, e, m);
+#elif defined(GCRYPT)
+ gcry_mpi_powm(r, b, e, m);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_exptmod(b, e, m, r);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_exp_mod(r, b, e, m, NULL);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+#if defined(MBEDTLS)
+int _mbedtls_f_rng(void* unused, unsigned char *buf, size_t size)
+{
+ t_random(buf, size);
+ return 0;
+}
+#endif
+
+int
+BigIntegerCheckPrime(n, c)
+ BigInteger n;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ int rv;
+ BN_CTX * ctx = NULL;
+ if(c == NULL)
+ c = ctx = BN_CTX_new();
+#if OPENSSL_VERSION_NUMBER >= 0x00908000
+ rv = BN_is_prime_ex(n, 25, c, NULL);
+#else
+ rv = BN_is_prime(n, 25, NULL, c, NULL);
+#endif
+ if(ctx)
+ BN_CTX_free(ctx);
+ return rv;
+#elif defined(CRYPTOLIB)
+#if 0
+ /*
+ * Ugh. Not only is cryptolib's bigDivide sensitive to inputs
+ * and outputs being the same, but now the primeTest needs random
+ * numbers, which it gets by calling cryptolib's broken truerand
+ * implementation(!) We have to fake it out by doing our own
+ * seeding explicitly.
+ */
+ static int seeded = 0;
+ static unsigned char seedbuf[64];
+ if(!seeded) {
+ t_random(seedbuf, sizeof(seedbuf));
+ seedDesRandom(seedbuf, sizeof(seedbuf));
+ memset(seedbuf, 0, sizeof(seedbuf));
+ seeded = 1;
+ }
+#endif /* 0 */
+ t_random(NULL, 0);
+ return primeTest(n);
+#elif defined(GNU_MP)
+ return mpz_probab_prime_p(n, 25);
+#elif defined(GCRYPT)
+ return (gcry_prime_check(n, 0) == GPG_ERR_NO_ERROR);
+#elif defined(TOMMATH)
+ int rv;
+ mp_prime_is_prime(n, 25, &rv);
+ return rv;
+#elif defined(MPI)
+ return (mpp_pprime(n, 25) == MP_YES);
+#elif defined(MBEDTLS)
+ return mbedtls_mpi_is_prime_ext(n, 25, _mbedtls_f_rng, NULL);
+#endif
+}
+
+BigIntegerResult
+BigIntegerFree(b)
+ BigInteger b;
+{
+#ifdef OPENSSL
+ BN_free(b);
+#elif defined(CRYPTOLIB)
+ freeBignum(b);
+#elif defined(GNU_MP)
+ mpz_clear(b);
+ free(b);
+#elif defined(GCRYPT)
+ gcry_mpi_release(b);
+#elif defined(MPI) || defined(TOMMATH)
+ mp_clear(b);
+ free(b);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_free(b);
+ free(b);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerClearFree(b)
+ BigInteger b;
+{
+#ifdef OPENSSL
+ BN_clear_free(b);
+#elif defined(CRYPTOLIB)
+ /* TODO */
+ freeBignum(b);
+#elif defined(GNU_MP)
+ /* TODO */
+ mpz_clear(b);
+ free(b);
+#elif defined(GCRYPT)
+ /* TODO */
+ gcry_mpi_release(b);
+#elif defined(MPI) || defined(TOMMATH)
+ /* TODO */
+ mp_clear(b);
+ free(b);
+#elif defined(MBEDTLS)
+ mbedtls_mpi_free(b);
+ free(b);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerCtx
+BigIntegerCtxNew()
+{
+#ifdef OPENSSL
+ return BN_CTX_new();
+#else
+ return NULL;
+#endif
+}
+
+BigIntegerResult
+BigIntegerCtxFree(ctx)
+ BigIntegerCtx ctx;
+{
+#ifdef OPENSSL
+ if(ctx)
+ BN_CTX_free(ctx);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerModAccel
+BigIntegerModAccelNew(m, c)
+ BigInteger m;
+ BigIntegerCtx c;
+{
+#ifdef OPENSSL
+ BN_CTX * ctx = NULL;
+ BN_MONT_CTX * mctx;
+ if(default_modexp)
+ return NULL;
+ if(c == NULL)
+ c = ctx = BN_CTX_new();
+ mctx = BN_MONT_CTX_new();
+ BN_MONT_CTX_set(mctx, m, c);
+ if(ctx)
+ BN_CTX_free(ctx);
+ return mctx;
+#else
+ return NULL;
+#endif
+}
+
+BigIntegerResult
+BigIntegerModAccelFree(accel)
+ BigIntegerModAccel accel;
+{
+#ifdef OPENSSL
+ if(accel)
+ BN_MONT_CTX_free(accel);
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerInitialize()
+{
+#if OPENSSL_VERSION_NUMBER >= 0x00907000
+ ENGINE_load_builtin_engines();
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
+
+BigIntegerResult
+BigIntegerFinalize()
+{
+ return BigIntegerReleaseEngine();
+}
+
+BigIntegerResult
+BigIntegerUseEngine(const char * engine)
+{
+#if defined(OPENSSL) && defined(OPENSSL_ENGINE)
+ ENGINE * e = ENGINE_by_id(engine);
+ if(e) {
+ if(ENGINE_init(e) > 0) {
+#if OPENSSL_VERSION_NUMBER >= 0x00907000
+ /* 0.9.7 loses the BN_mod_exp method. Pity. */
+ const RSA_METHOD * rsa = ENGINE_get_RSA(e);
+ if(rsa)
+#if (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3000000fL) || (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100005L)
+ default_modexp = (modexp_meth)RSA_meth_get_bn_mod_exp(rsa);
+#else
+ default_modexp = (modexp_meth)rsa->bn_mod_exp;
+#endif
+#else
+ default_modexp = (modexp_meth)ENGINE_get_BN_mod_exp(e);
+#endif
+ BigIntegerReleaseEngine();
+ default_engine = e;
+ return BIG_INTEGER_SUCCESS;
+ }
+ else
+ ENGINE_free(e);
+ }
+#endif
+ return BIG_INTEGER_ERROR;
+}
+
+BigIntegerResult
+BigIntegerReleaseEngine()
+{
+#if defined(OPENSSL) && defined(OPENSSL_ENGINE)
+ if(default_engine) {
+ ENGINE_finish(default_engine);
+ ENGINE_free(default_engine);
+ default_engine = NULL;
+ default_modexp = NULL;
+ }
+#endif
+ return BIG_INTEGER_SUCCESS;
+}
diff --git a/3rd_party/libsrp6a-sha512/t_misc.c b/3rd_party/libsrp6a-sha512/t_misc.c
new file mode 100644
index 0000000..3053358
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_misc.c
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+#include "t_defines.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+#include <process.h>
+#include <io.h>
+#endif
+
+#include "t_sha.h"
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef OPENSSL
+#include <openssl/opensslv.h>
+#include <openssl/rand.h>
+#elif defined(TOMCRYPT)
+#include "tomcrypt.h"
+static prng_state g_rng;
+static unsigned char entropy[32];
+#elif defined(CRYPTOLIB)
+# include "libcrypt.h"
+static unsigned char crpool[64];
+#else
+static unsigned char randpool[SHA_DIGESTSIZE], randout[SHA_DIGESTSIZE];
+static unsigned long randcnt = 0;
+static unsigned int outpos = 0;
+SHA1_CTX randctxt;
+#endif /* OPENSSL */
+
+/*
+ * t_envhash - Generate a 160-bit SHA hash of the environment
+ *
+ * This routine performs an SHA hash of all the "name=value" pairs
+ * in the environment concatenated together and dumps them in the
+ * output. While it is true that anyone on the system can see
+ * your environment, someone not on the system will have a very
+ * difficult time guessing it, especially since some systems play
+ * tricks with variable ordering and sometimes define quirky
+ * environment variables like $WINDOWID or $_.
+ */
+extern char ** environ;
+
+static void
+t_envhash(out)
+ unsigned char * out;
+{
+ char ** ptr;
+ char ebuf[256];
+ SHA1_CTX ctxt;
+
+ SHA1Init(&ctxt);
+ for(ptr = environ; *ptr; ++ptr) {
+ strncpy(ebuf, *ptr, 255);
+ ebuf[255] = '\0';
+ SHA1Update(&ctxt, ebuf, strlen(ebuf));
+ }
+ SHA1Final(out, &ctxt);
+}
+
+/*
+ * t_fshash - Generate a 160-bit SHA hash from the file system
+ *
+ * This routine climbs up the directory tree from the current
+ * directory, running stat() on each directory until it hits the
+ * root directory. This information is sensitive to the last
+ * access/modification times of all the directories above you,
+ * so someone who lists one of those directories injects some
+ * entropy into the system. Obviously, this hash is very sensitive
+ * to your current directory when the program is run.
+ *
+ * For good measure, it also performs an fstat on the standard input,
+ * usually your tty, throws that into the buffer, creates a file in
+ * /tmp (the inode is unpredictable on a busy system), and runs stat()
+ * on that before deleting it.
+ *
+ * The entire buffer is run once through SHA to obtain the final result.
+ */
+static void
+t_fshash(out)
+ unsigned char * out;
+{
+ char dotpath[128];
+ struct stat st;
+ SHA1_CTX ctxt;
+ int i, pinode;
+ dev_t pdev;
+
+ SHA1Init(&ctxt);
+ if(stat(".", &st) >= 0) {
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+ pinode = st.st_ino;
+ pdev = st.st_dev;
+ strcpy(dotpath, "..");
+ for(i = 0; i < 40; ++i) {
+ if(stat(dotpath, &st) < 0)
+ break;
+ if(st.st_ino == pinode && st.st_dev == pdev)
+ break;
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+ pinode = st.st_ino;
+ pdev = st.st_dev;
+ strcat(dotpath, "/..");
+ }
+ }
+
+ if(fstat(0, &st) >= 0)
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+
+ sprintf(dotpath, "/tmp/rnd.%d", getpid());
+ if(creat(dotpath, 0600) >= 0 && stat(dotpath, &st) >= 0)
+ SHA1Update(&ctxt, (unsigned char *) &st, sizeof(st));
+ unlink(dotpath);
+
+ SHA1Final(out, &ctxt);
+}
+
+/*
+ * Generate a high-entropy seed for the strong random number generator.
+ * This uses a wide variety of quickly gathered and somewhat unpredictable
+ * system information. The 'preseed' structure is assembled from:
+ *
+ * The system time in seconds
+ * The system time in microseconds
+ * The current process ID
+ * The parent process ID
+ * A hash of the user's environment
+ * A hash gathered from the file system
+ * Input from a random device, if available
+ * Timings of system interrupts
+ *
+ * The entire structure (60 bytes on most systems) is fed to SHA to produce
+ * a 160-bit seed for the strong random number generator. It is believed
+ * that in the worst case (on a quiet system with no random device versus
+ * an attacker who has access to the system already), the seed contains at
+ * least about 80 bits of entropy. Versus an attacker who does not have
+ * access to the system, the entropy should be slightly over 128 bits.
+ */
+static char initialized = 0;
+
+static struct {
+ unsigned int trand1;
+ time_t sec;
+ time_t subsec;
+ short pid;
+ short ppid;
+ unsigned char envh[SHA_DIGESTSIZE];
+ unsigned char fsh[SHA_DIGESTSIZE];
+ unsigned char devrand[20];
+ unsigned int trand2;
+} preseed;
+
+unsigned long raw_truerand();
+
+static void
+t_initrand()
+{
+ SHA1_CTX ctxt;
+#ifdef USE_FTIME
+ struct timeb t;
+#else
+ struct timeval t;
+#endif
+ int i, r=0;
+
+ if(initialized)
+ return;
+
+ initialized = 1;
+
+#if defined(OPENSSL) /* OpenSSL has nifty win32 entropy-gathering code */
+#if OPENSSL_VERSION_NUMBER >= 0x00905100
+ r = RAND_status();
+#if defined(WINDOWS) || defined(WIN32)
+ if(r) /* Don't do the Unix-y stuff on Windows if possible */
+ return;
+#else
+#endif
+#endif
+
+#elif defined(TOMCRYPT)
+ yarrow_start(&g_rng);
+ r = rng_get_bytes(entropy, sizeof(entropy), NULL);
+ if(r > 0) {
+ yarrow_add_entropy(entropy, r, &g_rng);
+ memset(entropy, 0, sizeof(entropy));
+# if defined(WINDOWS) || defined(WIN32)
+ /* Don't do the Unix-y stuff on Windows if possible */
+ yarrow_ready(&g_rng);
+ return;
+# endif
+ }
+#endif
+
+#if !defined(WINDOWS) && !defined(WIN32)
+ i = open("/dev/urandom", O_RDONLY);
+ if(i > 0) {
+ r += read(i, preseed.devrand, sizeof(preseed.devrand));
+ close(i);
+ }
+#endif /* !WINDOWS && !WIN32 */
+
+ /* Resort to truerand only if desperate for some Real entropy */
+ if(r == 0)
+ preseed.trand1 = raw_truerand();
+
+#ifdef USE_FTIME
+ ftime(&t);
+ preseed.sec = t.time;
+ preseed.subsec = t.millitm;
+#else
+ gettimeofday(&t, NULL);
+ preseed.sec = t.tv_sec;
+ preseed.subsec = t.tv_usec;
+#endif
+ preseed.pid = getpid();
+#ifndef WIN32
+ preseed.ppid = getppid();
+#endif
+ t_envhash(preseed.envh);
+ t_fshash(preseed.fsh);
+
+ if(r == 0)
+ preseed.trand2 = raw_truerand();
+
+#ifdef OPENSSL
+ RAND_seed((unsigned char *)&preseed, sizeof(preseed));
+#elif defined(TOMCRYPT)
+ yarrow_add_entropy((unsigned char *)&preseed, sizeof(preseed), &g_rng);
+ yarrow_ready(&g_rng);
+#elif defined(CRYPTOLIB)
+ t_mgf1(crpool, sizeof(crpool), (unsigned char *) &preseed, sizeof(preseed));
+ seedDesRandom(crpool, sizeof(crpool));
+ memset(crpool, 0, sizeof(crpool));
+#elif defined(GCRYPT)
+ gcry_random_add_bytes((unsigned char *)&preseed, sizeof(preseed), -1);
+#else
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, (unsigned char *) &preseed, sizeof(preseed));
+ SHA1Final(randpool, &ctxt);
+ memset((unsigned char *) &ctxt, 0, sizeof(ctxt));
+ outpos = 0;
+#endif /* OPENSSL */
+ memset((unsigned char *) &preseed, 0, sizeof(preseed));
+}
+
+#define NUM_RANDOMS 12
+
+_TYPE( void )
+t_stronginitrand()
+{
+#if 1 /* t_initrand() has been improved enough to make this unnecessary */
+ t_initrand();
+#else
+ SHA1_CTX ctxt;
+ unsigned int rawrand[NUM_RANDOMS];
+ int i;
+
+ if(!initialized)
+ t_initrand();
+ for(i = 0; i < NUM_RANDOMS; ++i)
+ rawrand[i] = raw_truerand();
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, (unsigned char *) rawrand, sizeof(rawrand));
+ SHA1Final(randkey2, &ctxt);
+ memset(rawrand, 0, sizeof(rawrand));
+#endif
+}
+
+/*
+ * The strong random number generator. This uses a 160-bit seed
+ * and uses SHA-1 in a feedback configuration to generate successive
+ * outputs. If S[0] is set to the initial seed, then:
+ *
+ * S[i+1] = SHA-1(i || S[i])
+ * A[i] = SHA-1(S[i])
+ *
+ * where the A[i] are the output blocks starting with i=0.
+ * Each cycle generates 20 bytes of new output.
+ */
+_TYPE( void )
+t_random(data, size)
+ unsigned char * data;
+ unsigned size;
+{
+ if(!initialized)
+ t_initrand();
+
+ if(size <= 0) /* t_random(NULL, 0) forces seed initialization */
+ return;
+
+#ifdef OPENSSL
+ RAND_bytes(data, size);
+#elif defined(TOMCRYPT)
+ yarrow_read(data, size, &g_rng);
+#elif defined(GCRYPT)
+ gcry_randomize(data, size, GCRY_STRONG_RANDOM);
+#elif defined(CRYPTOLIB)
+ randomBytes(data, size, PSEUDO);
+#else
+ while(size > outpos) {
+ if(outpos > 0) {
+ memcpy(data, randout + (sizeof(randout) - outpos), outpos);
+ data += outpos;
+ size -= outpos;
+ }
+
+ /* Recycle */
+ SHA1Init(&randctxt);
+ SHA1Update(&randctxt, randpool, sizeof(randpool));
+ SHA1Final(randout, &randctxt);
+ SHA1Init(&randctxt);
+ SHA1Update(&randctxt, (unsigned char *) &randcnt, sizeof(randcnt));
+ SHA1Update(&randctxt, randpool, sizeof(randpool));
+ SHA1Final(randpool, &randctxt);
+ ++randcnt;
+ outpos = sizeof(randout);
+ }
+
+ if(size > 0) {
+ memcpy(data, randout + (sizeof(randout) - outpos), size);
+ outpos -= size;
+ }
+#endif
+}
+
+/*
+ * The interleaved session-key hash. This separates the even and the odd
+ * bytes of the input (ignoring the first byte if the input length is odd),
+ * hashes them separately, and re-interleaves the two outputs to form a
+ * single 320-bit value.
+ */
+_TYPE( unsigned char * )
+t_sessionkey(key, sk, sklen)
+ unsigned char * key;
+ unsigned char * sk;
+ unsigned sklen;
+{
+ unsigned i, klen;
+ unsigned char * hbuf;
+ unsigned char hout[SHA_DIGESTSIZE];
+ SHA1_CTX ctxt;
+
+ while(sklen > 0 && *sk == 0) { /* Skip leading 0's */
+ --sklen;
+ ++sk;
+ }
+
+ klen = sklen / 2;
+ if((hbuf = malloc(klen * sizeof(char))) == 0)
+ return 0;
+
+ for(i = 0; i < klen; ++i)
+ hbuf[i] = sk[sklen - 2 * i - 1];
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, hbuf, klen);
+ SHA1Final(hout, &ctxt);
+ for(i = 0; i < sizeof(hout); ++i)
+ key[2 * i] = hout[i];
+
+ for(i = 0; i < klen; ++i)
+ hbuf[i] = sk[sklen - 2 * i - 2];
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, hbuf, klen);
+ SHA1Final(hout, &ctxt);
+ for(i = 0; i < sizeof(hout); ++i)
+ key[2 * i + 1] = hout[i];
+
+ memset(hout, 0, sizeof(hout));
+ memset(hbuf, 0, klen);
+ free(hbuf);
+ return key;
+}
+
+_TYPE( void )
+t_mgf1(mask, masklen, seed, seedlen)
+ unsigned char * mask;
+ unsigned masklen;
+ const unsigned char * seed;
+ unsigned seedlen;
+{
+ SHA1_CTX ctxt;
+ unsigned i = 0;
+ unsigned pos = 0;
+ unsigned char cnt[4];
+ unsigned char hout[SHA_DIGESTSIZE];
+
+ while(pos < masklen) {
+ cnt[0] = (i >> 24) & 0xFF;
+ cnt[1] = (i >> 16) & 0xFF;
+ cnt[2] = (i >> 8) & 0xFF;
+ cnt[3] = i & 0xFF;
+ SHA1Init(&ctxt);
+ SHA1Update(&ctxt, seed, seedlen);
+ SHA1Update(&ctxt, cnt, 4);
+
+ if(pos + SHA_DIGESTSIZE > masklen) {
+ SHA1Final(hout, &ctxt);
+ memcpy(mask + pos, hout, masklen - pos);
+ pos = masklen;
+ }
+ else {
+ SHA1Final(mask + pos, &ctxt);
+ pos += SHA_DIGESTSIZE;
+ }
+
+ ++i;
+ }
+
+ memset(hout, 0, sizeof(hout));
+ memset((unsigned char *)&ctxt, 0, sizeof(ctxt));
+}
diff --git a/3rd_party/libsrp6a-sha512/t_pwd.h b/3rd_party/libsrp6a-sha512/t_pwd.h
new file mode 100644
index 0000000..a90a364
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_pwd.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
+ * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Redistributions in source or binary form must retain an intact copy
+ * of this copyright notice.
+ */
+
+#ifndef T_PWD_H
+#define T_PWD_H
+
+#include <stdio.h>
+#include "cstr.h"
+
+#define MAXPARAMBITS 2048
+#define MAXPARAMLEN ((MAXPARAMBITS + 7) / 8)
+#define MAXB64PARAMLEN ((MAXPARAMBITS + 5) / 6 + 1)
+#define MAXHEXPARAMLEN ((MAXPARAMBITS + 3) / 4 + 1)
+#define MAXOCTPARAMLEN ((MAXPARAMBITS + 2) / 3 + 1)
+
+#define MAXUSERLEN 32
+#define MAXSALTLEN 32
+#define MAXB64SALTLEN 44 /* 256 bits in b64 + null */
+#define SALTLEN 10 /* Normally 80 bits */
+
+#define RESPONSE_LEN 20 /* 160-bit proof hashes */
+#define SESSION_KEY_LEN (2 * RESPONSE_LEN) /* 320-bit session key */
+
+#define DEFAULT_PASSWD "/etc/tpasswd"
+#define DEFAULT_CONF "/etc/tpasswd.conf"
+
+struct t_num { /* Standard byte-oriented integer representation */
+ int len;
+ unsigned char * data;
+};
+
+struct t_preconf { /* Structure returned by t_getpreparam() */
+ char * mod_b64;
+ char * gen_b64;
+ char * comment;
+
+ struct t_num modulus;
+ struct t_num generator;
+};
+
+/*
+ * The built-in (known good) parameters access routines
+ *
+ * "t_getprecount" returns the number of precompiled parameter sets.
+ * "t_getpreparam" returns the indicated parameter set.
+ * Memory is statically allocated - callers need not perform any memory mgmt.
+ */
+_TYPE( int ) t_getprecount();
+_TYPE( struct t_preconf * ) t_getpreparam P((int));
+
+struct t_confent { /* One configuration file entry (index, N, g) */
+ int index;
+ struct t_num modulus;
+ struct t_num generator;
+};
+
+struct t_conf { /* An open configuration file */
+ FILE * instream;
+ char close_on_exit;
+ cstr * modbuf;
+ cstr * genbuf;
+ struct t_confent tcbuf;
+};
+
+/*
+ * The configuration file routines are designed along the lines of the
+ * "getpw" functions in the standard C library.
+ *
+ * "t_openconf" accepts a stdio stream and interprets it as a config file.
+ * "t_openconfbyname" accepts a filename and does the same thing.
+ * "t_closeconf" closes the config file.
+ * "t_getconfent" fetches the next sequential configuration entry.
+ * "t_getconfbyindex" fetches the configuration entry whose index
+ * matches the one supplied, or NULL if one can't be found.
+ * "t_getconflast" fetches the last configuration entry in the file.
+ * "t_makeconfent" generates a set of configuration entry parameters
+ * randomly.
+ * "t_newconfent" returns an empty configuration entry.
+ * "t_cmpconfent" compares two configuration entries a la strcmp.
+ * "t_checkconfent" verifies that a set of configuration parameters
+ * are suitable. N must be prime and should be a safe prime.
+ * "t_putconfent" writes a configuration entry to a stream.
+ */
+_TYPE( struct t_conf * ) t_openconf P((FILE *));
+_TYPE( struct t_conf * ) t_openconfbyname P((const char *));
+_TYPE( void ) t_closeconf P((struct t_conf *));
+_TYPE( void ) t_rewindconf P((struct t_conf *));
+_TYPE( struct t_confent * ) t_getconfent P((struct t_conf *));
+_TYPE( struct t_confent * ) t_getconfbyindex P((struct t_conf *, int));
+_TYPE( struct t_confent * ) t_getconflast P((struct t_conf *));
+_TYPE( struct t_confent * ) t_makeconfent P((struct t_conf *, int));
+_TYPE( struct t_confent * ) t_makeconfent_c P((struct t_conf *, int));
+_TYPE( struct t_confent * ) t_newconfent P((struct t_conf *));
+_TYPE( int ) t_cmpconfent P((const struct t_confent *, const struct t_confent *));
+_TYPE( int ) t_checkconfent P((const struct t_confent *));
+_TYPE( void ) t_putconfent P((const struct t_confent *, FILE *));
+
+/* libc-style system conf file access */
+_TYPE( struct t_confent *) gettcent();
+_TYPE( struct t_confent *) gettcid P((int));
+_TYPE( void ) settcent();
+_TYPE( void ) endtcent();
+
+#ifdef ENABLE_NSW
+extern struct t_confent * _gettcent();
+extern struct t_confent * _gettcid P((int));
+extern void _settcent();
+extern void _endtcent();
+#endif
+
+/* A hack to support '+'-style entries in the passwd file */
+
+typedef enum fstate {
+ FILE_ONLY, /* Ordinary file, don't consult NIS ever */
+ FILE_NIS, /* Currently accessing file, use NIS if encountered */
+ IN_NIS, /* Currently in a '+' entry; use NIS for getXXent */
+} FILE_STATE;
+
+struct t_pwent { /* A single password file entry */
+ char * name;
+ struct t_num password;
+ struct t_num salt;
+ int index;
+};
+
+struct t_pw { /* An open password file */
+ FILE * instream;
+ char close_on_exit;
+ FILE_STATE state;
+ char userbuf[MAXUSERLEN];
+ cstr * pwbuf;
+ unsigned char saltbuf[SALTLEN];
+ struct t_pwent pebuf;
+};
+
+/*
+ * The password manipulation routines are patterned after the getpw*
+ * standard C library function calls.
+ *
+ * "t_openpw" reads a stream as if it were a password file.
+ * "t_openpwbyname" opens the named file as a password file.
+ * "t_closepw" closes an open password file.
+ * "t_rewindpw" starts the internal file pointer from the beginning
+ * of the password file.
+ * "t_getpwent" retrieves the next sequential password entry.
+ * "t_getpwbyname" looks up the password entry corresponding to the
+ * specified user.
+ * "t_makepwent" constructs a password entry from a username, password,
+ * numeric salt, and configuration entry.
+ * "t_putpwent" writes a password entry to a stream.
+ */
+_TYPE( struct t_pw * ) t_newpw();
+_TYPE( struct t_pw * ) t_openpw P((FILE *));
+_TYPE( struct t_pw * ) t_openpwbyname P((const char *));
+_TYPE( void ) t_closepw P((struct t_pw *));
+_TYPE( void ) t_rewindpw P((struct t_pw *));
+_TYPE( struct t_pwent * ) t_getpwent P((struct t_pw *));
+_TYPE( struct t_pwent * ) t_getpwbyname P((struct t_pw *, const char *));
+_TYPE( struct t_pwent * ) t_makepwent P((struct t_pw *, const char *,
+ const char *, const struct t_num *,
+ const struct t_confent *));
+_TYPE( void ) t_putpwent P((const struct t_pwent *, FILE *));
+
+struct t_passwd {
+ struct t_pwent tp;
+ struct t_confent tc;
+};
+
+/* libc-style system password file access */
+_TYPE( struct t_passwd * ) gettpent();
+_TYPE( struct t_passwd * ) gettpnam P((const char *));
+_TYPE( void ) settpent();
+_TYPE( void ) endtpent();
+
+#ifdef ENABLE_NSW
+extern struct t_passwd * _gettpent();
+extern struct t_passwd * _gettpnam P((const char *));
+extern void _settpent();
+extern void _endtpent();
+#endif
+
+/*
+ * Utility functions
+ *
+ * "t_verifypw" accepts a username and password, and checks against the
+ * system password file to see if the password for that user is correct.
+ * Returns > 0 if it is correct, 0 if not, and -1 if some error occurred
+ * (i.e. the user doesn't exist on the system). This is intended ONLY
+ * for local authentication; for remote authentication, look at the
+ * t_client and t_server source. (That's the whole point of SRP!)
+ * "t_changepw" modifies the specified file, substituting the given password
+ * entry for the one already in the file. If no matching entry is found,
+ * the new entry is simply appended to the file.
+ * "t_deletepw" removes the specified user from the specified file.
+ */
+_TYPE( int ) t_verifypw P((const char *, const char *));
+_TYPE( int ) t_changepw P((const char *, const struct t_pwent *));
+_TYPE( int ) t_deletepw P((const char *, const char *));
+
+/* Conversion utilities */
+
+/*
+ * All these calls accept output as the first parameter. In the case of
+ * t_tohex and t_tob64, the last argument is the length of the byte-string
+ * input.
+ */
+_TYPE( char * ) t_tohex P((char *, const char *, unsigned));
+_TYPE( int ) t_fromhex P((char *, const char *));
+_TYPE( char * ) t_tob64 P((char *, const char *, unsigned));
+_TYPE( int ) t_fromb64 P((char *, const char *));
+
+/* These functions put their output in a cstr object */
+_TYPE( char * ) t_tohexcstr P((cstr *, const char *, unsigned));
+_TYPE( int ) t_cstrfromhex P((cstr *, const char *));
+_TYPE( char * ) t_tob64cstr P((cstr *, const char *, unsigned));
+_TYPE( int ) t_cstrfromb64 P((cstr *, const char *));
+
+/* Miscellaneous utilities (moved to t_defines.h) */
+
+#endif
diff --git a/3rd_party/libsrp6a-sha512/t_sha.c b/3rd_party/libsrp6a-sha512/t_sha.c
new file mode 100644
index 0000000..4029de8
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_sha.c
@@ -0,0 +1,276 @@
+#include "t_defines.h"
+#include "t_sha.h"
+
+#ifdef CRYPTOLIB_SHA
+
+/* A wrapper around CryptoLib's shsFinal that delivers output in octets */
+void
+shsFinalBytes(unsigned char digest[20], SHS_CTX* context)
+{
+ int i;
+ unsigned long r;
+ unsigned char *p = digest;
+
+ shsFinal(context);
+ for(i = 0; i < 5; ++i) {
+ r = context->h[i];
+ *p++ = (unsigned char)((r >> 24) & 0xff);
+ *p++ = (unsigned char)((r >> 16) & 0xff);
+ *p++ = (unsigned char)((r >> 8) & 0xff);
+ *p++ = (unsigned char)(r & 0xff);
+ }
+}
+
+#elif defined(GCRYPT_SHA)
+/* Wrappers for gcrypt's md interface */
+
+void
+SHA1Init_gcry(SHA1_CTX * ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_SHA1, 0);
+}
+
+void
+SHA1Update_gcry(SHA1_CTX * ctx, const void *data, unsigned int len)
+{
+ gcry_md_write(*ctx, data, len);
+}
+
+void
+SHA1Final_gcry(unsigned char digest[20], SHA1_CTX * ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, GCRY_MD_SHA1), 20);
+ gcry_md_close(*ctx);
+}
+
+void
+SHA512Init_gcry(SHA512_CTX * ctx)
+{
+ gcry_md_open(ctx, GCRY_MD_SHA512, 0);
+}
+
+void
+SHA512Update_gcry(SHA512_CTX * ctx, const void *data, unsigned int len)
+{
+ gcry_md_write(*ctx, data, len);
+}
+
+void
+SHA512Final_gcry(unsigned char digest[64], SHA512_CTX * ctx)
+{
+ memcpy(digest, gcry_md_read(*ctx, GCRY_MD_SHA512), 64);
+ gcry_md_close(*ctx);
+}
+
+#elif defined(MBEDTLS_SHA)
+/* Wrappers for mbedtls's md interface */
+
+void
+SHA1Init_mbed(SHA1_CTX * ctx)
+{
+ mbedtls_md_init(ctx);
+ mbedtls_md_setup(ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), 0);
+ mbedtls_md_starts(ctx);
+}
+
+void
+SHA1Update_mbed(SHA1_CTX * ctx, const void *data, unsigned int len)
+{
+ mbedtls_md_update(ctx, data, len);
+}
+
+void
+SHA1Final_mbed(unsigned char digest[20], SHA1_CTX * ctx)
+{
+ mbedtls_md_finish(ctx, digest);
+ mbedtls_md_free(ctx);
+}
+
+void
+SHA512Init_mbed(SHA512_CTX * ctx)
+{
+ mbedtls_md_init(ctx);
+ mbedtls_md_setup(ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), 0);
+ mbedtls_md_starts(ctx);
+}
+
+void
+SHA512Update_mbed(SHA512_CTX * ctx, const void *data, unsigned int len)
+{
+ mbedtls_md_update(ctx, data, len);
+}
+
+void
+SHA512Final_mbed(unsigned char digest[64], SHA512_CTX * ctx)
+{
+ mbedtls_md_finish(ctx, digest);
+ mbedtls_md_free(ctx);
+}
+
+#elif !defined(OPENSSL_SHA) && !defined(TOMCRYPT_SHA)
+/* Use the free SHA1 if the library doesn't have it */
+
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#include <stdio.h>
+#include <string.h>
+
+static void SHA1Transform(uint32 state[5], const unsigned char buffer[64]);
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifndef WORDS_BIGENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+static void SHA1Transform(uint32 state[5], const unsigned char buffer[64])
+{
+uint32 a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ uint32 l[16];
+} CHAR64LONG16;
+CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+static unsigned char workspace[64];
+ block = (CHAR64LONG16*)workspace;
+ memcpy(block, buffer, 64);
+#else
+ block = (CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, unsigned int len)
+{
+unsigned int i, j;
+
+ j = (context->count[0] >> 3) & 63;
+ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+ context->count[1] += (len >> 29);
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+uint32 i, j;
+unsigned char finalcount[8];
+
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+ SHA1Update(context, (unsigned char *)"\200", 1);
+ while ((context->count[0] & 504) != 448) {
+ SHA1Update(context, (unsigned char *)"\0", 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ i = j = 0;
+ memset(context->buffer, 0, 64);
+ memset(context->state, 0, 20);
+ memset(context->count, 0, 8);
+ memset(&finalcount, 0, 8);
+#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
+ SHA1Transform(context->state, context->buffer);
+#endif
+}
+#endif /* OPENSSL */
diff --git a/3rd_party/libsrp6a-sha512/t_sha.h b/3rd_party/libsrp6a-sha512/t_sha.h
new file mode 100644
index 0000000..18deec5
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_sha.h
@@ -0,0 +1,125 @@
+#ifndef T_SHA_H
+#define T_SHA_H
+
+#if !defined(P)
+#ifdef __STDC__
+#define P(x) x
+#else
+#define P(x) ()
+#endif
+#endif
+
+#define SHA_DIGESTSIZE 20
+
+#ifdef OPENSSL
+#define OPENSSL_SHA 1
+#endif
+
+#ifdef TOMCRYPT
+# include <tomcrypt.h>
+# ifdef SHA1
+# define TOMCRYPT_SHA 1
+# endif
+#endif
+
+#ifdef CRYPTOLIB
+/* The SHA (shs) implementation in CryptoLib 1.x breaks when Update
+ * is called multiple times, so we still use our own code.
+ * Uncomment below if you think your copy of CryptoLib is fixed. */
+/*#define CRYPTOLIB_SHA 1*/
+#endif
+
+#ifdef GCRYPT
+# define GCRYPT_SHA 1
+#endif
+
+#ifdef MBEDTLS
+# define MBEDTLS_SHA 1
+#endif
+
+#ifdef OPENSSL_SHA
+#include <openssl/sha.h>
+
+typedef SHA_CTX SHA1_CTX;
+#define SHA1Init SHA1_Init
+#define SHA1Update SHA1_Update
+#define SHA1Final SHA1_Final
+
+#define SHA512Init SHA512_Init
+#define SHA512Update SHA512_Update
+#define SHA512Final SHA512_Final
+
+#elif defined(TOMCRYPT_SHA)
+/* mycrypt.h already included above */
+
+typedef hash_state SHA1_CTX;
+#define SHA1Init sha1_init
+#define SHA1Update sha1_process
+#define SHA1Final(D,C) sha1_done(C,D)
+
+#elif defined(GCRYPT_SHA)
+#include "gcrypt.h"
+
+typedef gcry_md_hd_t SHA1_CTX;
+#define SHA1Init SHA1Init_gcry
+#define SHA1Update SHA1Update_gcry
+#define SHA1Final SHA1Final_gcry
+typedef gcry_md_hd_t SHA512_CTX;
+#define SHA512Init SHA512Init_gcry
+#define SHA512Update SHA512Update_gcry
+#define SHA512Final SHA512Final_gcry
+
+void SHA1Init_gcry(SHA1_CTX * ctx);
+void SHA1Update_gcry(SHA1_CTX * ctx, const void *data, unsigned int len);
+void SHA1Final_gcry(unsigned char digest[20], SHA1_CTX * ctx);
+
+void SHA512Init_gcry(SHA512_CTX * ctx);
+void SHA512Update_gcry(SHA512_CTX * ctx, const void *data, unsigned int len);
+void SHA512Final_gcry(unsigned char digest[64], SHA512_CTX * ctx);
+
+#elif defined(MBEDTLS_SHA)
+#include <mbedtls/md.h>
+
+typedef mbedtls_md_context_t SHA1_CTX;
+#define SHA1Init SHA1Init_mbed
+#define SHA1Update SHA1Update_mbed
+#define SHA1Final SHA1Final_mbed
+
+typedef mbedtls_md_context_t SHA512_CTX;
+#define SHA512Init SHA512Init_mbed
+#define SHA512Update SHA512Update_mbed
+#define SHA512Final SHA512Final_mbed
+
+void SHA1Init_mbed(SHA1_CTX * ctx);
+void SHA1Update_mbed(SHA1_CTX * ctx, const void *data, unsigned int len);
+void SHA1Final_mbed(unsigned char digest[20], SHA1_CTX * ctx);
+
+void SHA512Init_mbed(SHA512_CTX * ctx);
+void SHA512Update_mbed(SHA512_CTX * ctx, const void *data, unsigned int len);
+void SHA512Final_mbed(unsigned char digest[64], SHA512_CTX * ctx);
+
+#elif defined(CRYPTOLIB_SHA)
+#include "libcrypt.h"
+
+typedef SHS_CTX SHA1_CTX;
+#define SHA1Init shsInit
+#define SHA1Update shsUpdate
+#define SHA1Final shsFinalBytes
+
+void shsFinalBytes P((unsigned char digest[20], SHS_CTX* context));
+
+#else
+typedef unsigned int uint32;
+
+typedef struct {
+ uint32 state[5];
+ uint32 count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Init P((SHA1_CTX* context));
+void SHA1Update P((SHA1_CTX* context, const unsigned char* data, unsigned int len));
+void SHA1Final P((unsigned char digest[20], SHA1_CTX* context));
+#endif /* !OPENSSL && !CRYPTOLIB */
+
+#endif /* T_SHA_H */
diff --git a/3rd_party/libsrp6a-sha512/t_truerand.c b/3rd_party/libsrp6a-sha512/t_truerand.c
new file mode 100644
index 0000000..2617b5e
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_truerand.c
@@ -0,0 +1,241 @@
+/*
+ * Physically random numbers (very nearly uniform)
+ * D. P. Mitchell
+ * Modified by Matt Blaze 7/95
+ */
+/*
+ * The authors of this software are Don Mitchell and Matt Blaze.
+ * Copyright (c) 1995 by AT&T.
+ * Permission to use, copy, and modify this software without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software and in all copies of the supporting
+ * documentation for such software.
+ *
+ * This software may be subject to United States export controls.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR AT&T MAKE ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+ * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+ */
+
+/*
+ * WARNING: depending on the particular platform, raw_truerand()
+ * output may be biased or correlated. In general, you can expect
+ * about 16 bits of "pseudo-entropy" out of each 32 bit word returned
+ * by truerand(), but it may not be uniformly diffused. You should
+ * raw_therefore run the output through some post-whitening function
+ * (like MD5 or DES or whatever) before using it to generate key
+ * material. (RSAREF's random package does this for you when you feed
+ * raw_truerand() bits to the seed input function.)
+ *
+ * The application interface, for 8, 16, and 32 bit properly "whitened"
+ * random numbers, can be found in trand8(), trand16(), and trand32().
+ * Use those instead of calling raw_truerand() directly.
+ *
+ * The basic idea here is that between clock "skew" and various
+ * hard-to-predict OS event arrivals, counting a tight loop will yield
+ * a little (maybe a third of a bit or so) of "good" randomness per
+ * interval clock tick. This seems to work well even on unloaded
+ * machines. If there is a human operator at the machine, you should
+ * augment truerand with other measure, like keyboard event timing.
+ * On server machines (e.g., when you need to generate a
+ * Diffie-Hellman secret) truerand alone may be good enough.
+ *
+ * Test these assumptions on your own platform before fielding a
+ * system based on this software or these techniques.
+ *
+ * This software seems to work well (at 10 or so bits per
+ * raw_truerand() call) on a Sun Sparc-20 under SunOS 4.1.3 and on a
+ * P100 under BSDI 2.0. You're on your own elsewhere.
+ *
+ */
+
+#include "t_defines.h"
+
+#ifdef WIN32
+
+# ifdef CRYPTOLIB
+
+/* Cryptolib contains its own truerand() on both UNIX and Windows. */
+/* Only use cryptolib's truerand under Windows */
+
+# include "libcrypt.h"
+
+unsigned long
+raw_truerand()
+{
+ return truerand();
+}
+
+# else /* !CRYPTOLIB && WIN32 */
+
+#include <wtypes.h>
+#include <winbase.h>
+#include <windef.h>
+#include <winnt.h>
+#include <winuser.h>
+#include <process.h>
+
+volatile unsigned long count, ocount, randbuf;
+volatile int dontstop;
+char outbuf[1024], *bufp;
+
+static void counter() {
+ while (dontstop)
+ count++;
+ _endthread();
+}
+
+
+static unsigned long roulette() {
+ unsigned long thread;
+
+ count = 0;
+ dontstop= 1;
+ while ((thread = _beginthread((void *)counter, 1024, NULL)) < 0)
+ ;
+
+ Sleep(16);
+ dontstop = 0;
+ Sleep(1);
+
+ count ^= (count>>3) ^ (count>>6) ^ (ocount);
+ count &= 0x7;
+ ocount = count;
+ randbuf = (randbuf<<3) ^ count;
+ return randbuf;
+}
+
+
+unsigned long
+raw_truerand() {
+
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ roulette();
+ return roulette();
+}
+
+# endif /* CRYPTOLIB */
+
+#else /* !WIN32 */
+
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/time.h>
+#include <math.h>
+#include <stdio.h>
+
+#ifdef OLD_TRUERAND
+static jmp_buf env;
+#endif
+static unsigned volatile count
+#ifndef OLD_TRUERAND
+ , done = 0
+#endif
+;
+
+static unsigned ocount;
+static unsigned buffer;
+
+static void
+tick()
+{
+ struct itimerval it, oit;
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 16665;
+ if (setitimer(ITIMER_REAL, &it, &oit) < 0)
+ perror("tick");
+}
+
+static void
+interrupt()
+{
+ if (count) {
+#ifdef OLD_TRUERAND
+ longjmp(env, 1);
+#else
+ ++done;
+ return;
+#endif
+ }
+
+ (void) signal(SIGALRM, interrupt);
+ tick();
+}
+
+static unsigned long
+roulette()
+{
+#ifdef OLD_TRUERAND
+ if (setjmp(env)) {
+ count ^= (count>>3) ^ (count>>6) ^ ocount;
+ count &= 0x7;
+ ocount=count;
+ buffer = (buffer<<3) ^ count;
+ return buffer;
+ }
+#else
+ done = 0;
+#endif
+ (void) signal(SIGALRM, interrupt);
+ count = 0;
+ tick();
+#ifdef OLD_TRUERAND
+ for (;;)
+#else
+ while(done == 0)
+#endif
+ count++; /* about 1 MHz on VAX 11/780 */
+#ifndef OLD_TRUERAND
+ count ^= (count>>3) ^ (count>>6) ^ ocount;
+ count &= 0x7;
+ ocount=count;
+ buffer = (buffer<<3) ^ count;
+ return buffer;
+#endif
+}
+
+unsigned long
+raw_truerand()
+{
+ count=0;
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ (void) roulette();
+ return roulette();
+}
+
+int
+raw_n_truerand(n)
+int n;
+{
+ int slop, v;
+
+ slop = 0x7FFFFFFF % n;
+ do {
+ v = raw_truerand() >> 1;
+ } while (v <= slop);
+ return v % n;
+}
+
+#endif /* !CRYPTOLIB || !WIN32 */