From e41dbc3ddbe30a414e73fa25d9c7c304ffe6989e Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Wed, 9 Feb 2022 04:04:36 +0100 Subject: Add support for wireless pairing --- 3rd_party/libsrp6a-sha512/LICENSE | 62 ++ 3rd_party/libsrp6a-sha512/Makefile.am | 31 + 3rd_party/libsrp6a-sha512/README.md | 35 + 3rd_party/libsrp6a-sha512/cstr.c | 226 +++++ 3rd_party/libsrp6a-sha512/cstr.h | 94 +++ 3rd_party/libsrp6a-sha512/srp.c | 274 ++++++ 3rd_party/libsrp6a-sha512/srp.h | 372 +++++++++ 3rd_party/libsrp6a-sha512/srp6a_sha512_client.c | 363 ++++++++ 3rd_party/libsrp6a-sha512/srp_aux.h | 146 ++++ 3rd_party/libsrp6a-sha512/t_conv.c | 258 ++++++ 3rd_party/libsrp6a-sha512/t_defines.h | 137 +++ 3rd_party/libsrp6a-sha512/t_math.c | 1008 +++++++++++++++++++++++ 3rd_party/libsrp6a-sha512/t_misc.c | 450 ++++++++++ 3rd_party/libsrp6a-sha512/t_pwd.h | 246 ++++++ 3rd_party/libsrp6a-sha512/t_sha.c | 276 +++++++ 3rd_party/libsrp6a-sha512/t_sha.h | 125 +++ 3rd_party/libsrp6a-sha512/t_truerand.c | 241 ++++++ 17 files changed, 4344 insertions(+) create mode 100644 3rd_party/libsrp6a-sha512/LICENSE create mode 100644 3rd_party/libsrp6a-sha512/Makefile.am create mode 100644 3rd_party/libsrp6a-sha512/README.md create mode 100644 3rd_party/libsrp6a-sha512/cstr.c create mode 100644 3rd_party/libsrp6a-sha512/cstr.h create mode 100644 3rd_party/libsrp6a-sha512/srp.c create mode 100644 3rd_party/libsrp6a-sha512/srp.h create mode 100644 3rd_party/libsrp6a-sha512/srp6a_sha512_client.c create mode 100644 3rd_party/libsrp6a-sha512/srp_aux.h create mode 100644 3rd_party/libsrp6a-sha512/t_conv.c create mode 100644 3rd_party/libsrp6a-sha512/t_defines.h create mode 100644 3rd_party/libsrp6a-sha512/t_math.c create mode 100644 3rd_party/libsrp6a-sha512/t_misc.c create mode 100644 3rd_party/libsrp6a-sha512/t_pwd.h create mode 100644 3rd_party/libsrp6a-sha512/t_sha.c create mode 100644 3rd_party/libsrp6a-sha512/t_sha.h create mode 100644 3rd_party/libsrp6a-sha512/t_truerand.c (limited to '3rd_party/libsrp6a-sha512') 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 +#include + +#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 +#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 +#include +#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 + +#if TIME_WITH_SYS_TIME +#include +#include +#else /* not TIME_WITH_SYS_TIME */ +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif /* not TIME_WITH_SYS_TIME */ + +#if HAVE_TERMIOS_H +#include +#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 +#include +#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 +#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 +#endif + +/* Looking for BigInteger math functions? They've moved to . */ + +#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 +#include + +#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 +# 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 +#include +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 +#endif /* HAVE_UNISTD_H */ + +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#endif + +#include "t_sha.h" + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef OPENSSL +#include +#include +#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 +#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 +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 +#include + +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 +# 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 + +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 + +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 +#include +#include +#include +#include +#include + +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 +#include +#include +#include +#include + +#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 */ -- cgit v1.1-32-gdbae