From daf01977a1677017df4286051279cffd0c5bca8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 6 Jul 2015 12:53:53 -0300 Subject: [PATCH 01/16] adds SRP client and server structures. --- wolfcrypt/src/srp.c | 22 ++++++++++++ wolfssl/wolfcrypt/srp.h | 78 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 wolfcrypt/src/srp.c create mode 100644 wolfssl/wolfcrypt/srp.h diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c new file mode 100644 index 000000000..a0a22cf47 --- /dev/null +++ b/wolfcrypt/src/srp.c @@ -0,0 +1,22 @@ +/* srp.c + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + + diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h new file mode 100644 index 000000000..23bdeb947 --- /dev/null +++ b/wolfssl/wolfcrypt/srp.h @@ -0,0 +1,78 @@ +/* srp.h + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef WOLF_CRYPT_SRP_H +#define WOLF_CRYPT_SRP_H + +#include + +#ifdef HAVE_SRP + +/* Select the largest available hash for the buffer size. */ +#if defined(WOLFSSL_SHA512) + SRP_MAX_DIGEST_SIZE = SHA512_DIGEST_SIZE, +#elif defined(WOLFSSL_SHA384) + SRP_MAX_DIGEST_SIZE = SHA384_DIGEST_SIZE, +#elif !defined(NO_SHA256) + SRP_MAX_DIGEST_SIZE = SHA256_DIGEST_SIZE, +#elif !defined(NO_SHA) + SRP_MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, +#else + #error "You have to have some kind of SHA hash if you want to use SRP." +#endif + +typedef struct { + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ + mp_int g; /**< Generator. A generator modulo N. */ + mp_int a; /**< Private ephemeral value. Random. */ + mp_int A; /**< Public ephemeral value. pow(g, a, N) */ + mp_int B; /**< Server's public ephemeral value. */ + mp_int s; /**< Session key. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ + byte x[SRP_MAX_DIGEST_SIZE]; /**< Priv key. H(salt, H(user, ":", pswd)) */ + byte u[SRP_MAX_DIGEST_SIZE]; /**< Random scrambling parameeter. */ + byte type; /**< Hash type, SHA[1:256:384:512] */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ + byte* pswd; /**< Password. */ + word32 pswdSz; /**< Password length. */ +} SrpClient; + +typedef struct { + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ + mp_int g; /**< Generator. A generator modulo N. */ + mp_int b; /**< Private ephemeral value. */ + mp_int B; /**< Public ephemeral value. */ + mp_int A; /**< Client's public ephemeral value. */ + mp_int s; /**< Session key. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ + mp_int v; /**< Verifier. v = pow(g, x, N) */ + byte u[SRP_MAX_DIGEST_SIZE]; /**< Random scrambling parameeter. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ +} SrpServer; + +#endif /* HAVE_SRP */ +#endif /* WOLF_CRYPT_SRP_H */ From 6d7b5bd2f8020d70f0169b24beb2948d385b59c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 6 Jul 2015 14:10:20 -0300 Subject: [PATCH 02/16] adds srp files to build process. --- configure.ac | 106 ++++++++++++++++++++--------------- src/include.am | 5 +- wolfcrypt/src/srp.c | 6 +- wolfssl/wolfcrypt/include.am | 2 +- wolfssl/wolfcrypt/srp.h | 56 ++++++++++++------ 5 files changed, 109 insertions(+), 66 deletions(-) diff --git a/configure.ac b/configure.ac index bc15219aa..cb3cbaed3 100644 --- a/configure.ac +++ b/configure.ac @@ -85,7 +85,7 @@ AC_CHECK_TYPES(__uint128_t) AC_C_BIGENDIAN # mktime check takes forever on some systems, if time supported it would be # highly unusual for mktime to be missing -#AC_FUNC_MKTIME +#AC_FUNC_MKTIME AC_PROG_CC AC_PROG_CC_C_O @@ -199,7 +199,7 @@ fi AM_CONDITIONAL([BUILD_IPV6], [test "x$ENABLED_IPV6" = "xyes"]) -# Fortress build +# Fortress build AC_ARG_ENABLE([fortress], [ --enable-fortress Enable SSL fortress build (default: disabled)], [ ENABLED_FORTRESS=$enableval ], @@ -217,7 +217,7 @@ then fi -# ssl bump build +# ssl bump build AC_ARG_ENABLE([bump], [ --enable-bump Enable SSL Bump build (default: disabled)], [ ENABLED_BUMP=$enableval ], @@ -231,7 +231,7 @@ fi ENABLED_SLOWMATH="yes" -# lean psk build +# lean psk build AC_ARG_ENABLE([leanpsk], [ --enable-leanpsk Enable Lean PSK build (default: disabled)], [ ENABLED_LEANPSK=$enableval ], @@ -287,7 +287,7 @@ then fi -# Persistent session cache +# Persistent session cache AC_ARG_ENABLE([savesession], [ --enable-savesession Enable persistent session cache (default: disabled)], [ ENABLED_SAVESESSION=$enableval ], @@ -300,7 +300,7 @@ then fi -# Persistent cert cache +# Persistent cert cache AC_ARG_ENABLE([savecert], [ --enable-savecert Enable persistent cert cache (default: disabled)], [ ENABLED_SAVECERT=$enableval ], @@ -313,7 +313,7 @@ then fi -# Atomic User Record Layer +# Atomic User Record Layer AC_ARG_ENABLE([atomicuser], [ --enable-atomicuser Enable Atomic User Record Layer (default: disabled)], [ ENABLED_ATOMICUSER=$enableval ], @@ -326,7 +326,7 @@ then fi -# Public Key Callbacks +# Public Key Callbacks AC_ARG_ENABLE([pkcallbacks], [ --enable-pkcallbacks Enable Public Key Callbacks (default: disabled)], [ ENABLED_PKCALLBACKS=$enableval ], @@ -491,7 +491,7 @@ fi AM_CONDITIONAL([BUILD_MD2], [test "x$ENABLED_MD2" = "xyes"]) -# NULL CIPHER +# NULL CIPHER AC_ARG_ENABLE([nullcipher], [ --enable-nullcipher Enable wolfSSL NULL cipher support (default: disabled)], [ ENABLED_NULL_CIPHER=$enableval ], @@ -650,7 +650,7 @@ then fi -# HKDF +# HKDF AC_ARG_ENABLE([hkdf], [ --enable-hkdf Enable HKDF (HMAC-KDF) support (default: disabled)], [ ENABLED_HKDF=$enableval ], @@ -792,7 +792,7 @@ if test "$ENABLED_FPECC" = "yes" then if test "$ENABLED_ECC" = "no" then - AC_MSG_ERROR([cannot enable fpecc without enabling ecc.]) + AC_MSG_ERROR([cannot enable fpecc without enabling ecc.]) fi AM_CFLAGS="$AM_CFLAGS -DFP_ECC" fi @@ -809,17 +809,17 @@ if test "$ENABLED_ECC_ENCRYPT" = "yes" then if test "$ENABLED_ECC" = "no" then - AC_MSG_ERROR([cannot enable eccencrypt without enabling ecc.]) + AC_MSG_ERROR([cannot enable eccencrypt without enabling ecc.]) fi if test "$ENABLED_HKDF" = "no" then - AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.]) + AC_MSG_ERROR([cannot enable eccencrypt without enabling hkdf.]) fi AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC_ENCRYPT" fi -# PSK +# PSK AC_ARG_ENABLE([psk], [ --enable-psk Enable PSK (default: disabled)], [ ENABLED_PSK=$enableval ], @@ -857,7 +857,7 @@ else fi -# OLD TLS +# OLD TLS AC_ARG_ENABLE([oldtls], [ --enable-oldtls Enable old TLS versions < 1.2 (default: enabled)], [ ENABLED_OLD_TLS=$enableval ], @@ -877,7 +877,7 @@ else fi -# STACK SIZE info for examples +# STACK SIZE info for examples AC_ARG_ENABLE([stacksize], [ --enable-stacksize Enable stack size info on examples (default: disabled)], [ ENABLED_STACKSIZE=$enableval ], @@ -892,7 +892,7 @@ then fi -# MEMORY +# MEMORY AC_ARG_ENABLE([memory], [ --enable-memory Enable memory callbacks (default: enabled)], [ ENABLED_MEMORY=$enableval ], @@ -914,7 +914,7 @@ fi AM_CONDITIONAL([BUILD_MEMORY], [test "x$ENABLED_MEMORY" = "xyes"]) -# RSA +# RSA AC_ARG_ENABLE([rsa], [ --enable-rsa Enable RSA (default: enabled)], [ ENABLED_RSA=$enableval ], @@ -1119,7 +1119,7 @@ fi AM_CONDITIONAL([BUILD_DES3], [test "x$ENABLED_DES3" = "xyes"]) -# ARC4 +# ARC4 AC_ARG_ENABLE([arc4], [ --enable-arc4 Enable ARC4 (default: disabled)], [ ENABLED_ARC4=$enableval ], @@ -1146,7 +1146,7 @@ fi AM_CONDITIONAL([BUILD_RC4], [test "x$ENABLED_ARC4" = "xyes"]) -# MD5 +# MD5 AC_ARG_ENABLE([md5], [ --enable-md5 Enable MD5 (default: enabled)], [ ENABLED_MD5=$enableval ], @@ -1168,7 +1168,7 @@ fi AM_CONDITIONAL([BUILD_MD5], [test "x$ENABLED_MD5" = "xyes"]) -# SHA +# SHA AC_ARG_ENABLE([sha], [ --enable-sha Enable SHA (default: enabled)], [ ENABLED_SHA=$enableval ], @@ -1190,7 +1190,7 @@ fi AM_CONDITIONAL([BUILD_SHA], [test "x$ENABLED_SHA" = "xyes"]) -# Web Server Build +# Web Server Build AC_ARG_ENABLE([webserver], [ --enable-webserver Enable Web Server (default: disabled)], [ ENABLED_WEBSERVER=$enableval ], @@ -1204,7 +1204,7 @@ fi -# HC128 +# HC128 AC_ARG_ENABLE([hc128], [ --enable-hc128 Enable HC-128 (default: disabled)], [ ENABLED_HC128=$enableval ], @@ -1350,7 +1350,7 @@ else fi -# Filesystem Build +# Filesystem Build AC_ARG_ENABLE([filesystem], [ --enable-filesystem Enable Filesystem support (default: enabled)], [ ENABLED_FILESYSTEM=$enableval ], @@ -1370,7 +1370,7 @@ else fi -# inline Build +# inline Build AC_ARG_ENABLE([inline], [ --enable-inline Enable inline functions (default: enabled)], [ ENABLED_INLINE=$enableval ], @@ -1492,7 +1492,7 @@ AM_CONDITIONAL([BUILD_NTRU], [test "x$ENABLED_NTRU" = "xyes"]) if test "$ENABLED_NTRU" = "yes" && test "$ENABLED_SMALL" = "yes" then - AC_MSG_ERROR([cannot enable ntru and small, ntru requires TLS which small turns off.]) + AC_MSG_ERROR([cannot enable ntru and small, ntru requires TLS which small turns off.]) fi # SNI @@ -1648,6 +1648,22 @@ then fi +# Secure Remote Password +AC_ARG_ENABLE([srp], + [ --enable-srp Enable Secure Remote Password (default: disabled)], + [ ENABLED_SRP=$enableval ], + [ ENABLED_SRP=no ] + ) + +if test "x$ENABLED_SRP" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFCRYPT_HAVE_SRP" +fi + +AM_CONDITIONAL([BUILD_SRP], [test "x$ENABLED_SRP" = "xyes"]) + + + # Small Stack AC_ARG_ENABLE([smallstack], [ --enable-smallstack Enable Small Stack Usage (default: disabled)], @@ -1684,7 +1700,7 @@ fi AM_CONDITIONAL([USE_VALGRIND], [test "x$ENABLED_VALGRIND" = "xyes"]) -# Test certs, use internal cert functions for extra testing +# Test certs, use internal cert functions for extra testing AC_ARG_ENABLE([testcert], [ --enable-testcert Enable Test Cert (default: disabled)], [ ENABLED_TESTCERT=$enableval ], @@ -1715,7 +1731,7 @@ then fi -# Certificate Service Support +# Certificate Service Support AC_ARG_ENABLE([certservice], [ --enable-certservice Enable cert service (default: disabled)], [ ENABLED_CERT_SERVICE=$enableval ], @@ -1957,7 +1973,7 @@ AC_ARG_WITH([libz], AM_CONDITIONAL([BUILD_LIBZ], [test "x$ENABLED_LIBZ" = "xyes"]) -# cavium +# cavium trycaviumdir="" AC_ARG_WITH([cavium], [ --with-cavium=PATH PATH to cavium/software dir ], @@ -2183,7 +2199,7 @@ touch ctaocrypt/src/fips.c touch ctaocrypt/src/fips_test.c echo -# generate user options header +# generate user options header echo "---" echo "Generating user options header..." @@ -2193,7 +2209,7 @@ OPTION_FILE="wolfssl/options.h" #fi rm -f $OPTION_FILE -echo "/* wolfssl options.h" > $OPTION_FILE +echo "/* wolfssl options.h" > $OPTION_FILE echo " * generated from configure options" >> $OPTION_FILE echo " *" >> $OPTION_FILE echo " * Copyright (C) 2006-2015 wolfSSL Inc." >> $OPTION_FILE @@ -2202,13 +2218,13 @@ echo " * This file is part of wolfSSL. (formerly known as CyaSSL)" >> $OPTION_FI echo " *" >> $OPTION_FILE echo " */" >> $OPTION_FILE -echo "" >> $OPTION_FILE -echo "#pragma once" >> $OPTION_FILE -echo "" >> $OPTION_FILE -echo "#ifdef __cplusplus" >> $OPTION_FILE -echo "extern \"C\" {" >> $OPTION_FILE -echo "#endif" >> $OPTION_FILE -echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "#pragma once" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "#ifdef __cplusplus" >> $OPTION_FILE +echo "extern \"C\" {" >> $OPTION_FILE +echo "#endif" >> $OPTION_FILE +echo "" >> $OPTION_FILE for option in $OPTION_FLAGS; do defonly=`echo $option | sed 's/-D//'` @@ -2244,11 +2260,11 @@ for option in $OPTION_FLAGS; do fi done -echo "" >> $OPTION_FILE -echo "#ifdef __cplusplus" >> $OPTION_FILE -echo "}" >> $OPTION_FILE -echo "#endif" >> $OPTION_FILE -echo "" >> $OPTION_FILE +echo "" >> $OPTION_FILE +echo "#ifdef __cplusplus" >> $OPTION_FILE +echo "}" >> $OPTION_FILE +echo "#endif" >> $OPTION_FILE +echo "" >> $OPTION_FILE echo #backwards compatability for those who have included options or version @@ -2279,7 +2295,7 @@ echo " * Debug enabled: $ax_enable_debug" echo " * Warnings as failure: $ac_cv_warnings_as_errors" echo " * make -j: $enable_jobserver" echo " * VCS checkout: $ac_cv_vcs_checkout" -echo +echo echo " Features " echo " * Single threaded: $ENABLED_SINGLETHREADED" echo " * Filesystem: $ENABLED_FILESYSTEM" @@ -2351,10 +2367,10 @@ echo " * Session Ticket: $ENABLED_SESSION_TICKET" echo " * All TLS Extensions: $ENABLED_TLSX" echo " * PKCS#7 $ENABLED_PKCS7" echo " * wolfSCEP $ENABLED_WOLFSCEP" +echo " * Secure Remote Password $ENABLED_SRP" echo " * Small Stack: $ENABLED_SMALL_STACK" echo " * valgrind unit tests: $ENABLED_VALGRIND" echo " * LIBZ: $ENABLED_LIBZ" echo " * Examples: $ENABLED_EXAMPLES" echo "" echo "---" - diff --git a/src/include.am b/src/include.am index b4ba39ddd..6c2629bc0 100644 --- a/src/include.am +++ b/src/include.am @@ -201,6 +201,10 @@ if BUILD_PKCS7 src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs7.c endif +if BUILD_SRP +src_libwolfssl_la_SOURCES += wolfcrypt/src/srp.c +endif + # ssl files src_libwolfssl_la_SOURCES += \ src/internal.c \ @@ -220,4 +224,3 @@ endif if BUILD_SNIFFER src_libwolfssl_la_SOURCES += src/sniffer.c endif - diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index a0a22cf47..66a4f00cd 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -19,4 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - +#ifdef WOLFCRYPT_HAVE_SRP + +#include + +#endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 67949fc28..8387ed7df 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -46,6 +46,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/blake2-int.h \ wolfssl/wolfcrypt/blake2-impl.h \ wolfssl/wolfcrypt/tfm.h \ + wolfssl/wolfcrypt/srp.h \ wolfssl/wolfcrypt/types.h \ wolfssl/wolfcrypt/visibility.h \ wolfssl/wolfcrypt/logging.h \ @@ -57,4 +58,3 @@ noinst_HEADERS+= \ wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ wolfssl/wolfcrypt/port/ti/ti-hash.h \ wolfssl/wolfcrypt/port/ti/ti-ccm.h - diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 23bdeb947..f6a3edc10 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -19,12 +19,30 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -#ifndef WOLF_CRYPT_SRP_H -#define WOLF_CRYPT_SRP_H +#ifndef WOLFCRYPT_SRP_H +#define WOLFCRYPT_SRP_H #include +#include +#include +#include +#include -#ifdef HAVE_SRP +#ifdef WOLFCRYPT_HAVE_SRP + +enum { +#ifdef NO_SHA + SRP_SHA = 1, +#endif +#ifdef NO_SHA256 + SRP_SHA256 = 2, +#endif +#ifndef WOLFSSL_SHA384 + SRP_SHA384 = 3, +#endif +#ifndef WOLFSSL_SHA512 + SRP_SHA512 = 4, +#endif /* Select the largest available hash for the buffer size. */ #if defined(WOLFSSL_SHA512) @@ -38,41 +56,43 @@ #else #error "You have to have some kind of SHA hash if you want to use SRP." #endif +}; typedef struct { - mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ - mp_int g; /**< Generator. A generator modulo N. */ mp_int a; /**< Private ephemeral value. Random. */ mp_int A; /**< Public ephemeral value. pow(g, a, N) */ mp_int B; /**< Server's public ephemeral value. */ - mp_int s; /**< Session key. */ - byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ byte x[SRP_MAX_DIGEST_SIZE]; /**< Priv key. H(salt, H(user, ":", pswd)) */ - byte u[SRP_MAX_DIGEST_SIZE]; /**< Random scrambling parameeter. */ - byte type; /**< Hash type, SHA[1:256:384:512] */ - byte* user; /**< Username, login. */ - word32 userSz; /**< Username length. */ - byte* salt; /**< Small salt. */ - word32 saltSz; /**< Salt length. */ byte* pswd; /**< Password. */ word32 pswdSz; /**< Password length. */ } SrpClient; typedef struct { - mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ - mp_int g; /**< Generator. A generator modulo N. */ mp_int b; /**< Private ephemeral value. */ mp_int B; /**< Public ephemeral value. */ mp_int A; /**< Client's public ephemeral value. */ + mp_int v; /**< Verifier. v = pow(g, x, N) */ +} SrpServer; + +typedef struct { + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ + mp_int g; /**< Generator. A generator modulo N. */ mp_int s; /**< Session key. */ byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ - mp_int v; /**< Verifier. v = pow(g, x, N) */ byte u[SRP_MAX_DIGEST_SIZE]; /**< Random scrambling parameeter. */ + byte type; /**< Hash type, SHA[1:256:384:512] */ + byte side; /**< Client or Server side. */ byte* user; /**< Username, login. */ word32 userSz; /**< Username length. */ byte* salt; /**< Small salt. */ word32 saltSz; /**< Salt length. */ -} SrpServer; + union { + SrpClient client; + SrpServer server; + } specific; +} Srp; -#endif /* HAVE_SRP */ +int SrpInit(Srp* srp, byte* N, word32 nSz, byte* g, word32 gSz); + +#endif /* WOLFCRYPT_HAVE_SRP */ #endif /* WOLF_CRYPT_SRP_H */ From dfa956d22772e183c8b0890512162baad9d94e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 7 Jul 2015 12:01:47 -0300 Subject: [PATCH 03/16] adds wc_SrpInit() with unit tests. --- tests/include.am | 1 + tests/srp.c | 91 +++++++++++++++++++++++++++++ tests/unit.c | 5 +- tests/unit.h | 6 +- wolfcrypt/src/hmac.c | 41 +++++++------- wolfcrypt/src/srp.c | 123 ++++++++++++++++++++++++++++++++++++++++ wolfssl/wolfcrypt/srp.h | 49 ++++++++++++---- 7 files changed, 279 insertions(+), 37 deletions(-) create mode 100644 tests/srp.c diff --git a/tests/include.am b/tests/include.am index f276f3af0..802ec5ad1 100644 --- a/tests/include.am +++ b/tests/include.am @@ -11,6 +11,7 @@ tests_unit_test_SOURCES = \ tests/api.c \ tests/suites.c \ tests/hash.c \ + tests/srp.c \ examples/client/client.c \ examples/server/server.c tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) diff --git a/tests/srp.c b/tests/srp.c new file mode 100644 index 000000000..4b8879b43 --- /dev/null +++ b/tests/srp.c @@ -0,0 +1,91 @@ +/* srp.c SRP unit tests + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include +#include + +#ifdef WOLFCRYPT_HAVE_SRP + +static void test_SrpInit(void) +{ + byte N[] = { + 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, + 0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f, + 0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3, + 0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4, + 0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27, + 0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3, + 0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a, + 0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8, + 0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e, + 0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d, + 0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3 + }; + + byte g[] = { + 0x02 + }; + + Srp srp; + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), + g, sizeof(g))); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE, N, sizeof(N), + g, sizeof(g))); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpInit(&srp, SRP_TYPE_SHA, 255, N, sizeof(N), + g, sizeof(g))); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpInit(&srp, SRP_TYPE_SHA, 255, N, sizeof(N), + g, sizeof(g))); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, NULL, sizeof(N), + g, sizeof(g))); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), + NULL, sizeof(g))); + + AssertIntEQ(0, + wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), + g, sizeof(g))); +} + +#endif + +void SrpTest(void) +{ +#ifdef WOLFCRYPT_HAVE_SRP + test_SrpInit(); +#endif +} diff --git a/tests/unit.c b/tests/unit.c index 73ae2bcd7..3a7f2452c 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -77,6 +77,8 @@ int unit_test(int argc, char** argv) } #endif + SrpTest(); + #ifdef HAVE_CAVIUM CspShutdown(CAVIUM_DEV_ID); #endif @@ -92,7 +94,7 @@ void wait_tcp_ready(func_args* args) (void)args; #elif defined(_POSIX_THREADS) && !defined(__MINGW32__) pthread_mutex_lock(&args->signal->mutex); - + if (!args->signal->ready) pthread_cond_wait(&args->signal->cond, &args->signal->mutex); args->signal->ready = 0; /* reset */ @@ -176,4 +178,3 @@ void FreeTcpReady(tcp_ready* ready) (void)ready; #endif } - diff --git a/tests/unit.h b/tests/unit.h index bccd6d2ce..997186291 100644 --- a/tests/unit.h +++ b/tests/unit.h @@ -76,9 +76,9 @@ void ApiTest(void); -int SuiteTest(void); -int HashTest(void); +int SuiteTest(void); +int HashTest(void); +void SrpTest(void); #endif /* CyaSSL_UNIT_H */ - diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 242adfa55..50716f5d9 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -134,31 +134,31 @@ static int InitHmac(Hmac* hmac, int type) ret = wc_InitSha(&hmac->hash.sha); break; #endif - + #ifndef NO_SHA256 case SHA256: ret = wc_InitSha256(&hmac->hash.sha256); break; #endif - + #ifdef WOLFSSL_SHA384 case SHA384: ret = wc_InitSha384(&hmac->hash.sha384); break; #endif - + #ifdef WOLFSSL_SHA512 case SHA512: ret = wc_InitSha512(&hmac->hash.sha512); break; #endif - - #ifdef HAVE_BLAKE2 + + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); break; #endif - + default: return BAD_FUNC_ARG; } @@ -287,7 +287,7 @@ int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) break; #endif - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: { hmac_block_size = BLAKE2B_BLOCKBYTES; @@ -367,7 +367,7 @@ static int HmacKeyInnerHash(Hmac* hmac) break; #endif - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*) hmac->ipad,BLAKE2B_BLOCKBYTES); @@ -438,7 +438,7 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) break; #endif - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); if (ret != 0) @@ -570,7 +570,7 @@ int wc_HmacFinal(Hmac* hmac, byte* hash) break; #endif - #ifdef HAVE_BLAKE2 + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: { ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*) hmac->innerHash, @@ -622,7 +622,7 @@ int wc_HmacInitCavium(Hmac* hmac, int devId) hmac->devId = devId; hmac->magic = WOLFSSL_HMAC_CAVIUM_MAGIC; hmac->data = NULL; /* buffered input data */ - + hmac->innerHashKeyed = 0; return 0; @@ -650,7 +650,7 @@ static void HmacCaviumFinal(Hmac* hmac, byte* hash) (byte*)hmac->ipad, hmac->dataLen, hmac->data, hash, &requestId, hmac->devId) != 0) { WOLFSSL_MSG("Cavium Hmac failed"); - } + } hmac->innerHashKeyed = 0; /* tell update to start over if used again */ } @@ -685,7 +685,7 @@ static void HmacCaviumUpdate(Hmac* hmac, const byte* msg, word32 length) if (hmac->dataLen) XMEMCPY(tmp, hmac->data, hmac->dataLen); XMEMCPY(tmp + hmac->dataLen, msg, add); - + hmac->dataLen += add; XFREE(hmac->data, NULL, DYNAMIC_TYPE_CAVIUM_TMP); hmac->data = tmp; @@ -751,31 +751,31 @@ static INLINE int GetHashSizeByType(int type) return SHA_DIGEST_SIZE; break; #endif - + #ifndef NO_SHA256 case SHA256: return SHA256_DIGEST_SIZE; break; #endif - + #ifdef WOLFSSL_SHA384 case SHA384: return SHA384_DIGEST_SIZE; break; #endif - + #ifdef WOLFSSL_SHA512 case SHA512: return SHA512_DIGEST_SIZE; break; #endif - - #ifdef HAVE_BLAKE2 + + #ifdef HAVE_BLAKE2 case BLAKE2B_ID: return BLAKE2B_OUTBYTES; break; #endif - + default: return BAD_FUNC_ARG; break; @@ -824,7 +824,7 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, localSalt = tmp; saltSz = hashSz; } - + do { ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); if (ret != 0) @@ -876,4 +876,3 @@ int wc_HKDF(int type, const byte* inKey, word32 inKeySz, #endif /* HAVE_FIPS */ #endif /* NO_HMAC */ - diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 66a4f00cd..19862ae66 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -19,8 +19,131 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + #ifdef WOLFCRYPT_HAVE_SRP #include +#include + +static int SrpHashInit(Srp* srp) +{ + switch (srp->type) { + #ifndef NO_SHA + case SRP_TYPE_SHA: + return wc_InitSha(&srp->hash.sha); + #endif + + #ifndef NO_SHA256 + case SRP_TYPE_SHA256: + return wc_InitSha256(&srp->hash.sha256); + #endif + + #ifdef WOLFSSL_SHA384 + case SRP_TYPE_SHA384: + return wc_InitSha384(&srp->hash.sha384); + #endif + + #ifdef WOLFSSL_SHA512 + case SRP_TYPE_SHA512: + return wc_InitSha512(&srp->hash.sha512); + #endif + + default: return BAD_FUNC_ARG; + } +} + +static int SrpHashUpdate(Srp* srp, byte* data, word32 size) +{ + switch (srp->type) { + #ifndef NO_SHA + case SRP_TYPE_SHA: + return wc_ShaUpdate(&srp->hash.sha, data, size); + #endif + + #ifndef NO_SHA256 + case SRP_TYPE_SHA256: + return wc_Sha256Update(&srp->hash.sha256, data, size); + #endif + + #ifdef WOLFSSL_SHA384 + case SRP_TYPE_SHA384: + return wc_Sha384Update(&srp->hash.sha384, data, size); + #endif + + #ifdef WOLFSSL_SHA512 + case SRP_TYPE_SHA512: + return wc_Sha512Update(&srp->hash.sha512, data, size); + #endif + + default: return BAD_FUNC_ARG; + } +} + +static int SrpHashFinal(Srp* srp, byte* digest) +{ + switch (srp->type) { + #ifndef NO_SHA + case SRP_TYPE_SHA: + return wc_ShaFinal(&srp->hash.sha, digest); + #endif + + #ifndef NO_SHA256 + case SRP_TYPE_SHA256: return + wc_Sha256Final(&srp->hash.sha256, digest); + #endif + + #ifdef WOLFSSL_SHA384 + case SRP_TYPE_SHA384: return + wc_Sha384Final(&srp->hash.sha384, digest); + #endif + + #ifdef WOLFSSL_SHA512 + case SRP_TYPE_SHA512: return + wc_Sha512Final(&srp->hash.sha512, digest); + #endif + + default: return BAD_FUNC_ARG; + } +} + +int wc_SrpInit(Srp* srp, byte type, byte side, byte* N, word32 nSz, + byte* g, word32 gSz) +{ + int ret = 0; + + if (!srp || !N || !g) + return BAD_FUNC_ARG; + + if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE) + return BAD_FUNC_ARG; + + srp->side = side; + srp->type = type; /* a valid type is checked inside SrpHashXXX functions. */ + + if (mp_init_multi(&srp->N, &srp->g, &srp->s, 0, 0, 0) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) ret = SrpHashInit(srp); + if (ret == 0) ret = SrpHashUpdate(srp, N, nSz); + if (ret == 0) ret = SrpHashUpdate(srp, g, gSz); + if (ret == 0) ret = SrpHashFinal(srp, srp->k); + + if (ret != 0) { + mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); + } + + return ret; +} #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index f6a3edc10..b4ac77895 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +#ifdef WOLFCRYPT_HAVE_SRP + #ifndef WOLFCRYPT_SRP_H #define WOLFCRYPT_SRP_H @@ -28,20 +30,24 @@ #include #include -#ifdef WOLFCRYPT_HAVE_SRP +#ifdef __cplusplus + extern "C" { +#endif enum { -#ifdef NO_SHA - SRP_SHA = 1, + SRP_CLIENT_SIDE = 0, + SRP_SERVER_SIDE = 1, +#ifndef NO_SHA + SRP_TYPE_SHA = 1, #endif -#ifdef NO_SHA256 - SRP_SHA256 = 2, +#ifndef NO_SHA256 + SRP_TYPE_SHA256 = 2, #endif -#ifndef WOLFSSL_SHA384 - SRP_SHA384 = 3, +#ifdef WOLFSSL_SHA384 + SRP_TYPE_SHA384 = 3, #endif -#ifndef WOLFSSL_SHA512 - SRP_SHA512 = 4, +#ifdef WOLFSSL_SHA512 + SRP_TYPE_SHA512 = 4, #endif /* Select the largest available hash for the buffer size. */ @@ -58,6 +64,21 @@ enum { #endif }; +typedef union { + #ifndef NO_SHA + Sha sha; + #endif + #ifndef NO_SHA256 + Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + Sha512 sha512; + #endif +} SrpHash; + typedef struct { mp_int a; /**< Private ephemeral value. Random. */ mp_int A; /**< Public ephemeral value. pow(g, a, N) */ @@ -90,9 +111,15 @@ typedef struct { SrpClient client; SrpServer server; } specific; + SrpHash hash; /**< Hash object. */ } Srp; -int SrpInit(Srp* srp, byte* N, word32 nSz, byte* g, word32 gSz); +WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side, byte* N, word32 nSz, + byte* g, word32 gSz); +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_SRP_H */ #endif /* WOLFCRYPT_HAVE_SRP */ -#endif /* WOLF_CRYPT_SRP_H */ From 119dd0250e27933d77d005cb8e02b8b8007946b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 13 Jul 2015 16:10:29 -0300 Subject: [PATCH 04/16] fixes field types in SRP structure; adds new memory allocation type (DYNAMIC_TYPE_SRP); improves wc_SrpInit; adds wc_SrpTerm(), wc_SrpSetUsername(), wc_SrpSetParams(), wc_SrpSetPassword(); --- tests/srp.c | 117 ++++++++++++++++++++++----------- wolfcrypt/src/srp.c | 132 +++++++++++++++++++++++++++++++++----- wolfssl/wolfcrypt/srp.h | 27 +++++--- wolfssl/wolfcrypt/types.h | 3 +- 4 files changed, 212 insertions(+), 67 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index 4b8879b43..a2d59c829 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -30,55 +30,92 @@ #ifdef WOLFCRYPT_HAVE_SRP +static char username[] = "username"; + +static byte N[] = { + 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, + 0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f, + 0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3, + 0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4, + 0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27, + 0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3, + 0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a, + 0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8, + 0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e, + 0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d, + 0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3 +}; + +static byte g[] = { + 0x02 +}; + +static byte salt[] = { + 'r', 'a', 'n', 'd', 'o', 'm' +}; + static void test_SrpInit(void) { - byte N[] = { - 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, - 0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f, - 0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3, - 0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4, - 0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27, - 0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3, - 0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a, - 0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8, - 0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e, - 0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d, - 0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3 - }; - - byte g[] = { - 0x02 - }; - Srp srp; - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), - g, sizeof(g))); + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(NULL, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpInit(&srp, SRP_TYPE_SHA, 255 )); - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, 255, SRP_CLIENT_SIDE, N, sizeof(N), - g, sizeof(g))); + /* success */ + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, 255, N, sizeof(N), - g, sizeof(g))); + wc_SrpTerm(&srp); +} - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, 255, N, sizeof(N), - g, sizeof(g))); +static void test_SrpSetUsername(void) +{ + Srp srp; - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, NULL, sizeof(N), - g, sizeof(g))); + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(BAD_FUNC_ARG, - wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), - NULL, sizeof(g))); + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL)); - AssertIntEQ(0, - wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE, N, sizeof(N), - g, sizeof(g))); + /* success */ + AssertIntEQ(0, wc_SrpSetUsername(&srp, username)); + AssertIntEQ((int) XSTRLEN(username), srp.usernameSz); + AssertIntEQ(0, XMEMCMP(srp.username, username, srp.usernameSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpSetParams(void) +{ + Srp srp; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, NULL, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, N, sizeof(N), + NULL, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + NULL, sizeof(salt))); + + /* success */ + AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + AssertIntEQ(sizeof(salt), srp.saltSz); + AssertIntEQ(0, XMEMCMP(srp.salt, salt, srp.saltSz)); + + wc_SrpTerm(&srp); } #endif @@ -87,5 +124,7 @@ void SrpTest(void) { #ifdef WOLFCRYPT_HAVE_SRP test_SrpInit(); + test_SrpSetUsername(); + test_SrpSetParams(); #endif } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 19862ae66..780044017 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -111,39 +111,137 @@ static int SrpHashFinal(Srp* srp, byte* digest) } } -int wc_SrpInit(Srp* srp, byte type, byte side, byte* N, word32 nSz, - byte* g, word32 gSz) +int wc_SrpInit(Srp* srp, byte type, byte side) { int ret = 0; - if (!srp || !N || !g) + if (!srp) return BAD_FUNC_ARG; if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE) return BAD_FUNC_ARG; - srp->side = side; - srp->type = type; /* a valid type is checked inside SrpHashXXX functions. */ + if (type != SRP_TYPE_SHA && type != SRP_TYPE_SHA256 && + type != SRP_TYPE_SHA384 && type != SRP_TYPE_SHA512) + return BAD_FUNC_ARG; - if (mp_init_multi(&srp->N, &srp->g, &srp->s, 0, 0, 0) != MP_OKAY) + srp->side = side; srp->type = type; + srp->salt = NULL; srp->saltSz = 0; + srp->username = NULL; srp->usernameSz = 0; + + if (mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0) != MP_OKAY) return MP_INIT_E; - if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0 && mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) - ret = MP_READ_E; - - if (ret == 0) ret = SrpHashInit(srp); - if (ret == 0) ret = SrpHashUpdate(srp, N, nSz); - if (ret == 0) ret = SrpHashUpdate(srp, g, gSz); - if (ret == 0) ret = SrpHashFinal(srp, srp->k); + if (srp->side == SRP_CLIENT_SIDE) { + if (mp_init_multi(&srp->specific.client.a, + &srp->specific.client.A, + &srp->specific.client.B, + &srp->specific.client.password, 0, 0) != MP_OKAY) + ret = MP_INIT_E; + } + else { + if (mp_init_multi(&srp->specific.server.b, + &srp->specific.server.B, + &srp->specific.server.A, + &srp->specific.server.verifier, 0, 0) != MP_OKAY) + ret = MP_INIT_E; + } if (ret != 0) { - mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); + mp_clear(&srp->N); mp_clear(&srp->g); + mp_clear(&srp->s); mp_clear(&srp->u); } return ret; } +void wc_SrpTerm(Srp* srp) { + if (srp) { + mp_clear(&srp->N); mp_clear(&srp->g); + mp_clear(&srp->s); mp_clear(&srp->u); + + XMEMSET(srp->salt, 0, srp->saltSz); + XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); + XMEMSET(srp->username, 0, srp->usernameSz); + XFREE(srp->username, NULL, DYNAMIC_TYPE_SRP); + + if (srp->side == SRP_CLIENT_SIDE) { + mp_clear(&srp->specific.client.a); + mp_clear(&srp->specific.client.A); + mp_clear(&srp->specific.client.B); + mp_clear(&srp->specific.client.password); + + XMEMSET(srp->specific.client.x, 0, SRP_MAX_DIGEST_SIZE); + } + else { + mp_clear(&srp->specific.server.b); + mp_clear(&srp->specific.server.B); + mp_clear(&srp->specific.server.A); + mp_clear(&srp->specific.server.verifier); + } + } +} + +int wc_SrpSetUsername(Srp* srp, const char* username) { + if (!srp || !username) + return BAD_FUNC_ARG; + + srp->username = (byte*)XMALLOC(XSTRLEN(username), NULL, DYNAMIC_TYPE_SRP); + if (srp->username == NULL) + return MEMORY_E; + + srp->usernameSz = (word32) XSTRLEN(username); + XMEMCPY(srp->username, username, srp->usernameSz); + + return 0; +} + +int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz) +{ + int ret = 0; + + if (!srp || !N || !g || !salt) + return BAD_FUNC_ARG; + + if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) + return MP_READ_E; + + if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) + return MP_READ_E; + + if ((ret = SrpHashInit(srp)) != 0) + return ret; + + if ((ret = SrpHashUpdate(srp, (byte*) N, nSz)) != 0) + return ret; + + if ((ret = SrpHashUpdate(srp, (byte*) g, gSz)) != 0) + return ret; + + if ((ret = SrpHashFinal(srp, srp->k)) != 0) + return ret; + + srp->salt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SRP); + if (srp->salt == NULL) + return MEMORY_E; + + XMEMCPY(srp->salt, salt, saltSz); + srp->saltSz = saltSz; + + return 0; +} + +int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { + if (!srp || !password || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + if (mp_read_unsigned_bin(&srp->specific.client.password, password, size) + != MP_OKAY) + return MP_READ_E; + + return 0; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index b4ac77895..f79042b83 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -84,27 +84,26 @@ typedef struct { mp_int A; /**< Public ephemeral value. pow(g, a, N) */ mp_int B; /**< Server's public ephemeral value. */ byte x[SRP_MAX_DIGEST_SIZE]; /**< Priv key. H(salt, H(user, ":", pswd)) */ - byte* pswd; /**< Password. */ - word32 pswdSz; /**< Password length. */ + mp_int password; /**< Password. */ } SrpClient; typedef struct { mp_int b; /**< Private ephemeral value. */ mp_int B; /**< Public ephemeral value. */ mp_int A; /**< Client's public ephemeral value. */ - mp_int v; /**< Verifier. v = pow(g, x, N) */ + mp_int verifier; /**< Verifier. v = pow(g, x, N) */ } SrpServer; typedef struct { + byte side; /**< Client or Server side. */ + byte type; /**< Hash type, SHA[1:256:384:512] */ mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ mp_int g; /**< Generator. A generator modulo N. */ mp_int s; /**< Session key. */ byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ - byte u[SRP_MAX_DIGEST_SIZE]; /**< Random scrambling parameeter. */ - byte type; /**< Hash type, SHA[1:256:384:512] */ - byte side; /**< Client or Server side. */ - byte* user; /**< Username, login. */ - word32 userSz; /**< Username length. */ + mp_int u; /**< Random scrambling parameeter. */ + byte* username; /**< Username, login. */ + word32 usernameSz; /**< Username length. */ byte* salt; /**< Small salt. */ word32 saltSz; /**< Salt length. */ union { @@ -114,8 +113,16 @@ typedef struct { SrpHash hash; /**< Hash object. */ } Srp; -WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side, byte* N, word32 nSz, - byte* g, word32 gSz); +WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); +WOLFSSL_API void wc_SrpTerm(Srp* srp); + +WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const char* user); + +WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz); + +WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 795d2c9c5..060ed0239 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -271,7 +271,8 @@ DYNAMIC_TYPE_TLSX = 43, DYNAMIC_TYPE_OCSP = 44, DYNAMIC_TYPE_SIGNATURE = 45, - DYNAMIC_TYPE_HASHES = 46 + DYNAMIC_TYPE_HASHES = 46, + DYNAMIC_TYPE_SRP = 47, }; /* max error buffer string size */ From 8b23b86659ca3ef185f67b5ed206d469573445b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Wed, 15 Jul 2015 19:22:47 -0300 Subject: [PATCH 05/16] Adds hash type directly inside SrpHash and removes temp hash from Srp struct. --- wolfcrypt/src/srp.c | 134 ++++++++++++++++++++++++++++------------ wolfssl/wolfcrypt/srp.h | 36 ++++++----- 2 files changed, 113 insertions(+), 57 deletions(-) diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 780044017..555f3172c 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -30,84 +30,117 @@ #include #include -static int SrpHashInit(Srp* srp) +static int SrpHashInit(SrpHash* hash, int type) { - switch (srp->type) { + hash->type = type; + + switch (type) { #ifndef NO_SHA case SRP_TYPE_SHA: - return wc_InitSha(&srp->hash.sha); + return wc_InitSha(&hash->data.sha); #endif #ifndef NO_SHA256 case SRP_TYPE_SHA256: - return wc_InitSha256(&srp->hash.sha256); + return wc_InitSha256(&hash->data.sha256); #endif #ifdef WOLFSSL_SHA384 case SRP_TYPE_SHA384: - return wc_InitSha384(&srp->hash.sha384); + return wc_InitSha384(&hash->data.sha384); #endif #ifdef WOLFSSL_SHA512 case SRP_TYPE_SHA512: - return wc_InitSha512(&srp->hash.sha512); + return wc_InitSha512(&hash->data.sha512); #endif - default: return BAD_FUNC_ARG; + default: + return BAD_FUNC_ARG; } } -static int SrpHashUpdate(Srp* srp, byte* data, word32 size) +static int SrpHashUpdate(SrpHash* hash, byte* data, word32 size) { - switch (srp->type) { + switch (hash->type) { #ifndef NO_SHA case SRP_TYPE_SHA: - return wc_ShaUpdate(&srp->hash.sha, data, size); + return wc_ShaUpdate(&hash->data.sha, data, size); #endif #ifndef NO_SHA256 case SRP_TYPE_SHA256: - return wc_Sha256Update(&srp->hash.sha256, data, size); + return wc_Sha256Update(&hash->data.sha256, data, size); #endif #ifdef WOLFSSL_SHA384 case SRP_TYPE_SHA384: - return wc_Sha384Update(&srp->hash.sha384, data, size); + return wc_Sha384Update(&hash->data.sha384, data, size); #endif #ifdef WOLFSSL_SHA512 case SRP_TYPE_SHA512: - return wc_Sha512Update(&srp->hash.sha512, data, size); + return wc_Sha512Update(&hash->data.sha512, data, size); #endif - default: return BAD_FUNC_ARG; + default: + return BAD_FUNC_ARG; } } -static int SrpHashFinal(Srp* srp, byte* digest) +static int SrpHashFinal(SrpHash* hash, byte* digest) { - switch (srp->type) { + switch (hash->type) { #ifndef NO_SHA case SRP_TYPE_SHA: - return wc_ShaFinal(&srp->hash.sha, digest); + return wc_ShaFinal(&hash->data.sha, digest); #endif #ifndef NO_SHA256 - case SRP_TYPE_SHA256: return - wc_Sha256Final(&srp->hash.sha256, digest); + case SRP_TYPE_SHA256: + return wc_Sha256Final(&hash->data.sha256, digest); #endif #ifdef WOLFSSL_SHA384 - case SRP_TYPE_SHA384: return - wc_Sha384Final(&srp->hash.sha384, digest); + case SRP_TYPE_SHA384: + return wc_Sha384Final(&hash->data.sha384, digest); #endif #ifdef WOLFSSL_SHA512 - case SRP_TYPE_SHA512: return - wc_Sha512Final(&srp->hash.sha512, digest); + case SRP_TYPE_SHA512: + return wc_Sha512Final(&hash->data.sha512, digest); #endif - default: return BAD_FUNC_ARG; + default: + return BAD_FUNC_ARG; + } +} + +static word32 SrpHashSize(byte type) +{ + switch (type) { + #ifndef NO_SHA + case SRP_TYPE_SHA: + return SHA_DIGEST_SIZE; + #endif + + #ifndef NO_SHA256 + case SRP_TYPE_SHA256: + return SHA256_DIGEST_SIZE; + #endif + + #ifdef WOLFSSL_SHA384 + case SRP_TYPE_SHA384: + return SHA384_DIGEST_SIZE; + #endif + + #ifdef WOLFSSL_SHA512 + case SRP_TYPE_SHA512: + return SHA512_DIGEST_SIZE; + #endif + + default: + return 0; } } @@ -115,6 +148,8 @@ int wc_SrpInit(Srp* srp, byte type, byte side) { int ret = 0; + /* validating params */ + if (!srp) return BAD_FUNC_ARG; @@ -125,6 +160,8 @@ int wc_SrpInit(Srp* srp, byte type, byte side) type != SRP_TYPE_SHA384 && type != SRP_TYPE_SHA512) return BAD_FUNC_ARG; + /* initializing common data */ + srp->side = side; srp->type = type; srp->salt = NULL; srp->saltSz = 0; srp->username = NULL; srp->usernameSz = 0; @@ -132,21 +169,31 @@ int wc_SrpInit(Srp* srp, byte type, byte side) if (mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0) != MP_OKAY) return MP_INIT_E; + /* initializing client specific data */ + if (srp->side == SRP_CLIENT_SIDE) { - if (mp_init_multi(&srp->specific.client.a, - &srp->specific.client.A, - &srp->specific.client.B, - &srp->specific.client.password, 0, 0) != MP_OKAY) + ret = SrpHashInit(&srp->specific.client.proof, type); + + if (ret == 0 && mp_init_multi(&srp->specific.client.a, + &srp->specific.client.A, + &srp->specific.client.B, + &srp->specific.client.x, + 0, 0) != MP_OKAY) ret = MP_INIT_E; } - else { + + /* initializing server specific data */ + + if (srp->side == SRP_SERVER_SIDE) { if (mp_init_multi(&srp->specific.server.b, &srp->specific.server.B, &srp->specific.server.A, - &srp->specific.server.verifier, 0, 0) != MP_OKAY) + &srp->specific.server.v, 0, 0) != MP_OKAY) ret = MP_INIT_E; } + /* undo initializations on error */ + if (ret != 0) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); mp_clear(&srp->u); @@ -169,15 +216,16 @@ void wc_SrpTerm(Srp* srp) { mp_clear(&srp->specific.client.a); mp_clear(&srp->specific.client.A); mp_clear(&srp->specific.client.B); - mp_clear(&srp->specific.client.password); + mp_clear(&srp->specific.client.x); - XMEMSET(srp->specific.client.x, 0, SRP_MAX_DIGEST_SIZE); + XMEMSET(&srp->specific.client.proof, 0, sizeof(SrpHash)); } - else { + + if (srp->side == SRP_SERVER_SIDE) { mp_clear(&srp->specific.server.b); mp_clear(&srp->specific.server.B); mp_clear(&srp->specific.server.A); - mp_clear(&srp->specific.server.verifier); + mp_clear(&srp->specific.server.v); } } } @@ -200,6 +248,7 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* g, word32 gSz, const byte* salt, word32 saltSz) { + SrpHash hash; int ret = 0; if (!srp || !N || !g || !salt) @@ -211,16 +260,16 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) return MP_READ_E; - if ((ret = SrpHashInit(srp)) != 0) + if ((ret = SrpHashInit(&hash, srp->type)) != 0) return ret; - if ((ret = SrpHashUpdate(srp, (byte*) N, nSz)) != 0) + if ((ret = SrpHashUpdate(&hash, (byte*) N, nSz)) != 0) return ret; - if ((ret = SrpHashUpdate(srp, (byte*) g, gSz)) != 0) + if ((ret = SrpHashUpdate(&hash, (byte*) g, gSz)) != 0) return ret; - if ((ret = SrpHashFinal(srp, srp->k)) != 0) + if ((ret = SrpHashFinal(&hash, srp->k)) != 0) return ret; srp->salt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SRP); @@ -234,11 +283,16 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, } int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { + byte digest[SRP_MAX_DIGEST_SIZE]; + if (!srp || !password || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; - if (mp_read_unsigned_bin(&srp->specific.client.password, password, size) - != MP_OKAY) + (void) size; + /* TODO: calculate digest. */ + + if (mp_read_unsigned_bin(&srp->specific.client.x, digest, + SrpHashSize(srp->type)) != MP_OKAY) return MP_READ_E; return 0; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index f79042b83..b75ac547a 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -64,34 +64,37 @@ enum { #endif }; -typedef union { - #ifndef NO_SHA - Sha sha; - #endif - #ifndef NO_SHA256 - Sha256 sha256; - #endif - #ifdef WOLFSSL_SHA384 - Sha384 sha384; - #endif - #ifdef WOLFSSL_SHA512 - Sha512 sha512; - #endif +typedef struct { + byte type; + union { + #ifndef NO_SHA + Sha sha; + #endif + #ifndef NO_SHA256 + Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + Sha512 sha512; + #endif + } data; } SrpHash; typedef struct { mp_int a; /**< Private ephemeral value. Random. */ mp_int A; /**< Public ephemeral value. pow(g, a, N) */ mp_int B; /**< Server's public ephemeral value. */ - byte x[SRP_MAX_DIGEST_SIZE]; /**< Priv key. H(salt, H(user, ":", pswd)) */ - mp_int password; /**< Password. */ + mp_int x; /**< Priv key. H(salt, H(user, ":", pswd)) */ + SrpHash proof; /**< Client proof. Sent to Server. */ } SrpClient; typedef struct { mp_int b; /**< Private ephemeral value. */ mp_int B; /**< Public ephemeral value. */ mp_int A; /**< Client's public ephemeral value. */ - mp_int verifier; /**< Verifier. v = pow(g, x, N) */ + mp_int v; /**< Verifier. v = pow(g, x, N) */ } SrpServer; typedef struct { @@ -110,7 +113,6 @@ typedef struct { SrpClient client; SrpServer server; } specific; - SrpHash hash; /**< Hash object. */ } Srp; WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); From 6d5efccc55df7519c4b1b9d83cbef32384627b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Thu, 16 Jul 2015 16:03:18 -0300 Subject: [PATCH 06/16] finishes SrpSetPassword(), SrpSetVerifier(), SrpGetVerifier(); updates client_proof during SrpSetParams(); --- tests/srp.c | 11 +-- wolfcrypt/src/srp.c | 186 +++++++++++++++++++++++++++------------- wolfssl/wolfcrypt/srp.h | 11 ++- 3 files changed, 141 insertions(+), 67 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index a2d59c829..765d8f81f 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -30,7 +30,7 @@ #ifdef WOLFCRYPT_HAVE_SRP -static char username[] = "username"; +static char user[] = "user"; static byte N[] = { 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, @@ -76,13 +76,13 @@ static void test_SrpSetUsername(void) AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); /* invalid params */ - AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, user)); AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL)); /* success */ - AssertIntEQ(0, wc_SrpSetUsername(&srp, username)); - AssertIntEQ((int) XSTRLEN(username), srp.usernameSz); - AssertIntEQ(0, XMEMCMP(srp.username, username, srp.usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, user)); + AssertIntEQ((int) XSTRLEN(user), srp.userSz); + AssertIntEQ(0, XMEMCMP(srp.user, user, srp.userSz)); wc_SrpTerm(&srp); } @@ -92,6 +92,7 @@ static void test_SrpSetParams(void) Srp srp; AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, user)); /* invalid params */ AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, N, sizeof(N), diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 555f3172c..73d79ad4f 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -60,7 +60,7 @@ static int SrpHashInit(SrpHash* hash, int type) } } -static int SrpHashUpdate(SrpHash* hash, byte* data, word32 size) +static int SrpHashUpdate(SrpHash* hash, const byte* data, word32 size) { switch (hash->type) { #ifndef NO_SHA @@ -146,10 +146,9 @@ static word32 SrpHashSize(byte type) int wc_SrpInit(Srp* srp, byte type, byte side) { - int ret = 0; + int r; /* validating params */ - if (!srp) return BAD_FUNC_ARG; @@ -161,64 +160,51 @@ int wc_SrpInit(Srp* srp, byte type, byte side) return BAD_FUNC_ARG; /* initializing common data */ - - srp->side = side; srp->type = type; - srp->salt = NULL; srp->saltSz = 0; - srp->username = NULL; srp->usernameSz = 0; + srp->side = side; srp->type = type; + srp->salt = NULL; srp->saltSz = 0; + srp->user = NULL; srp->userSz = 0; if (mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0) != MP_OKAY) return MP_INIT_E; + r = SrpHashInit(&srp->client_proof, type); + if (!r) r = SrpHashInit(&srp->server_proof, type); + /* initializing client specific data */ - - if (srp->side == SRP_CLIENT_SIDE) { - ret = SrpHashInit(&srp->specific.client.proof, type); - - if (ret == 0 && mp_init_multi(&srp->specific.client.a, - &srp->specific.client.A, - &srp->specific.client.B, - &srp->specific.client.x, - 0, 0) != MP_OKAY) - ret = MP_INIT_E; - } + if (!r && srp->side == SRP_CLIENT_SIDE) + r = mp_init_multi(&srp->specific.client.a, &srp->specific.client.A, + &srp->specific.client.B, &srp->specific.client.x,0,0); /* initializing server specific data */ - - if (srp->side == SRP_SERVER_SIDE) { - if (mp_init_multi(&srp->specific.server.b, - &srp->specific.server.B, - &srp->specific.server.A, - &srp->specific.server.v, 0, 0) != MP_OKAY) - ret = MP_INIT_E; - } + if (!r && srp->side == SRP_SERVER_SIDE) + r = mp_init_multi(&srp->specific.server.b, &srp->specific.server.B, + &srp->specific.server.A, &srp->specific.server.v,0,0); /* undo initializations on error */ - - if (ret != 0) { + if (r != 0) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); mp_clear(&srp->u); } - return ret; + return r; } -void wc_SrpTerm(Srp* srp) { +void wc_SrpTerm(Srp* srp) +{ if (srp) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->s); mp_clear(&srp->u); XMEMSET(srp->salt, 0, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); - XMEMSET(srp->username, 0, srp->usernameSz); - XFREE(srp->username, NULL, DYNAMIC_TYPE_SRP); + XMEMSET(srp->user, 0, srp->userSz); + XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP); if (srp->side == SRP_CLIENT_SIDE) { mp_clear(&srp->specific.client.a); mp_clear(&srp->specific.client.A); mp_clear(&srp->specific.client.B); mp_clear(&srp->specific.client.x); - - XMEMSET(&srp->specific.client.proof, 0, sizeof(SrpHash)); } if (srp->side == SRP_SERVER_SIDE) { @@ -227,19 +213,22 @@ void wc_SrpTerm(Srp* srp) { mp_clear(&srp->specific.server.A); mp_clear(&srp->specific.server.v); } + + XMEMSET(srp, 0, sizeof(Srp)); } } -int wc_SrpSetUsername(Srp* srp, const char* username) { - if (!srp || !username) +int wc_SrpSetUsername(Srp* srp, const char* user) +{ + if (!srp || !user) return BAD_FUNC_ARG; - srp->username = (byte*)XMALLOC(XSTRLEN(username), NULL, DYNAMIC_TYPE_SRP); - if (srp->username == NULL) + srp->user = (byte*)XMALLOC(XSTRLEN(user), NULL, DYNAMIC_TYPE_SRP); + if (srp->user == NULL) return MEMORY_E; - srp->usernameSz = (word32) XSTRLEN(username); - XMEMCPY(srp->username, username, srp->usernameSz); + srp->userSz = (word32) XSTRLEN(user); + XMEMCPY(srp->user, user, srp->userSz); return 0; } @@ -249,28 +238,26 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* salt, word32 saltSz) { SrpHash hash; - int ret = 0; + byte digest1[SRP_MAX_DIGEST_SIZE]; + byte digest2[SRP_MAX_DIGEST_SIZE]; + int i, j, r; - if (!srp || !N || !g || !salt) + if (!srp || !srp->user || !N || !g || !salt) return BAD_FUNC_ARG; + /* Set N */ if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) return MP_READ_E; + /* Set g */ if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) return MP_READ_E; - if ((ret = SrpHashInit(&hash, srp->type)) != 0) - return ret; - - if ((ret = SrpHashUpdate(&hash, (byte*) N, nSz)) != 0) - return ret; - - if ((ret = SrpHashUpdate(&hash, (byte*) g, gSz)) != 0) - return ret; - - if ((ret = SrpHashFinal(&hash, srp->k)) != 0) - return ret; + /* Set salt */ + if (srp->salt) { + XMEMSET(srp->salt, 0, srp->saltSz); + XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); + } srp->salt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SRP); if (srp->salt == NULL) @@ -279,20 +266,101 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, XMEMCPY(srp->salt, salt, saltSz); srp->saltSz = saltSz; - return 0; + /* Set k = H(N, g) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, srp->k); + + /* Update client proof */ + + /* digest1 = H(N) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + if (!r) r = SrpHashFinal(&hash, digest1); + + /* digest2 = H(g) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* digest1 = H(N) ^ H(g) */ + for (i = 0, j = SrpHashSize(srp->type); i < j; i++) + digest1[i] ^= digest2[i]; + + /* digest2 = H(user) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* Client proof = H( H(N) ^ H(g) | H(user) | salt) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); + + return r; } -int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { +int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) +{ + SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; + int r; - if (!srp || !password || srp->side != SRP_CLIENT_SIDE) + if (!srp || !srp->user || !password || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; - (void) size; - /* TODO: calculate digest. */ + /* digest = H(username | ':' | password) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); + if (!r) r = SrpHashUpdate(&hash, password, size); + if (!r) r = SrpHashFinal(&hash, digest); - if (mp_read_unsigned_bin(&srp->specific.client.x, digest, + /* digest = H(salt | H(username | ':' | password)) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); + if (!r) r = SrpHashUpdate(&hash, digest, SrpHashSize(srp->type)); + if (!r) r = SrpHashFinal(&hash, digest); + + /* Set x (private key) */ + if (!r && mp_read_unsigned_bin(&srp->specific.client.x, digest, SrpHashSize(srp->type)) != MP_OKAY) + r = MP_READ_E; + + XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); + + return r; +} + +int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) +{ + mp_int v; + int r; + + if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + r = mp_init(&v); + + /* v = g ^ x % N */ + if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.x, &srp->N, &v); + if (!r) r = (int)*size < mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; + if (!r) r = mp_to_unsigned_bin(&v, verifier); + if (!r) *size = mp_unsigned_bin_size(&srp->specific.server.v); + + mp_clear(&v); + + return r; +} + +int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) +{ + if (!srp || !verifier || srp->side != SRP_SERVER_SIDE) + return BAD_FUNC_ARG; + + if (mp_read_unsigned_bin(&srp->specific.server.v, verifier, size) + != MP_OKAY) return MP_READ_E; return 0; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index b75ac547a..b89733847 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -87,7 +87,6 @@ typedef struct { mp_int A; /**< Public ephemeral value. pow(g, a, N) */ mp_int B; /**< Server's public ephemeral value. */ mp_int x; /**< Priv key. H(salt, H(user, ":", pswd)) */ - SrpHash proof; /**< Client proof. Sent to Server. */ } SrpClient; typedef struct { @@ -105,10 +104,12 @@ typedef struct { mp_int s; /**< Session key. */ byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ mp_int u; /**< Random scrambling parameeter. */ - byte* username; /**< Username, login. */ - word32 usernameSz; /**< Username length. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ byte* salt; /**< Small salt. */ word32 saltSz; /**< Salt length. */ + SrpHash client_proof; /**< Client proof. Sent to Server. */ + SrpHash server_proof; /**< Server proof. Sent to Client. */ union { SrpClient client; SrpServer server; @@ -126,6 +127,10 @@ WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); +WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); + +WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); + #ifdef __cplusplus } /* extern "C" */ #endif From 6ee788277fbe8d9d3ad8ab1e5009560f6d052eb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sat, 25 Jul 2015 21:03:36 -0300 Subject: [PATCH 07/16] adds tests to SrpSetPassword(), SrpSetVerifier(), SrpGetVerifier(); adds SrpGenPublic() and SrpSetPrivate() with unit tests; fixes k with left pad at g; adds new error SRP_CALL_ORDER_E to force the functions to be called in the right order. --- tests/srp.c | 196 ++++++++++++++++++++++++++++---- tests/unit.h | 4 +- wolfcrypt/src/srp.c | 135 ++++++++++++++++++++-- wolfssl/wolfcrypt/error-crypt.h | 4 +- wolfssl/wolfcrypt/srp.h | 20 ++-- 5 files changed, 318 insertions(+), 41 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index 765d8f81f..7ec4a25c8 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -30,20 +30,19 @@ #ifdef WOLFCRYPT_HAVE_SRP -static char user[] = "user"; +static byte username[] = "user"; +static word32 usernameSz = 4; + +static byte password[] = "password"; +static word32 passwordSz = 8; static byte N[] = { - 0x00, 0xc0, 0x37, 0xc3, 0x75, 0x88, 0xb4, 0x32, 0x98, 0x87, 0xe6, 0x1c, - 0x2d, 0xa3, 0x32, 0x4b, 0x1b, 0xa4, 0xb8, 0x1a, 0x63, 0xf9, 0x74, 0x8f, - 0xed, 0x2d, 0x8a, 0x41, 0x0c, 0x2f, 0xc2, 0x1b, 0x12, 0x32, 0xf0, 0xd3, - 0xbf, 0xa0, 0x24, 0x27, 0x6c, 0xfd, 0x88, 0x44, 0x81, 0x97, 0xaa, 0xe4, - 0x86, 0xa6, 0x3b, 0xfc, 0xa7, 0xb8, 0xbf, 0x77, 0x54, 0xdf, 0xb3, 0x27, - 0xc7, 0x20, 0x1f, 0x6f, 0xd1, 0x7f, 0xd7, 0xfd, 0x74, 0x15, 0x8b, 0xd3, - 0x1c, 0xe7, 0x72, 0xc9, 0xf5, 0xf8, 0xab, 0x58, 0x45, 0x48, 0xa9, 0x9a, - 0x75, 0x9b, 0x5a, 0x2c, 0x05, 0x32, 0x16, 0x2b, 0x7b, 0x62, 0x18, 0xe8, - 0xf1, 0x42, 0xbc, 0xe2, 0xc3, 0x0d, 0x77, 0x84, 0x68, 0x9a, 0x48, 0x3e, - 0x09, 0x5e, 0x70, 0x16, 0x18, 0x43, 0x79, 0x13, 0xa8, 0xc3, 0x9c, 0x3d, - 0xd0, 0xd4, 0xca, 0x3c, 0x50, 0x0b, 0x88, 0x5f, 0xe3 + 0xD4, 0xC7, 0xF8, 0xA2, 0xB3, 0x2C, 0x11, 0xB8, 0xFB, 0xA9, 0x58, 0x1E, + 0xC4, 0xBA, 0x4F, 0x1B, 0x04, 0x21, 0x56, 0x42, 0xEF, 0x73, 0x55, 0xE3, + 0x7C, 0x0F, 0xC0, 0x44, 0x3E, 0xF7, 0x56, 0xEA, 0x2C, 0x6B, 0x8E, 0xEB, + 0x75, 0x5A, 0x1C, 0x72, 0x30, 0x27, 0x66, 0x3C, 0xAA, 0x26, 0x5E, 0xF7, + 0x85, 0xB8, 0xFF, 0x6A, 0x9B, 0x35, 0x22, 0x7A, 0x52, 0xD8, 0x66, 0x33, + 0xDB, 0xDF, 0xCA, 0x43 }; static byte g[] = { @@ -51,7 +50,46 @@ static byte g[] = { }; static byte salt[] = { - 'r', 'a', 'n', 'd', 'o', 'm' + 0x80, 0x66, 0x61, 0x5B, 0x7D, 0x33, 0xA2, 0x2E, 0x79, 0x18 +}; + +static byte verifier[] = { + 0x24, 0x5F, 0xA5, 0x1B, 0x2A, 0x28, 0xF8, 0xFF, 0xE2, 0xA0, 0xF8, 0x61, + 0x7B, 0x0F, 0x3C, 0x05, 0xD6, 0x4A, 0x55, 0xDF, 0x74, 0x31, 0x54, 0x47, + 0xA1, 0xFA, 0x9D, 0x25, 0x7B, 0x02, 0x88, 0x0A, 0xE8, 0x5A, 0xBA, 0x8B, + 0xA2, 0xD3, 0x8A, 0x62, 0x46, 0x8C, 0xEC, 0x52, 0xBE, 0xDE, 0xFC, 0x75, + 0xF5, 0xDB, 0x9C, 0x8C, 0x9B, 0x34, 0x7A, 0xE7, 0x4A, 0x5F, 0xBB, 0x96, + 0x38, 0x19, 0xAB, 0x24 +}; + +static byte a[] = { + 0x37, 0x95, 0xF2, 0xA6, 0xF1, 0x6F, 0x0D, 0x58, 0xBF, 0xED, 0x44, 0x87, + 0xE0, 0xB6, 0xCC, 0x1C, 0xA0, 0x50, 0xC6, 0x61, 0xBB, 0x36, 0xE0, 0x9A, + 0xF3, 0xF7, 0x1E, 0x7A, 0x61, 0x86, 0x5A, 0xF5 +}; + +static byte A[] = { + 0x8D, 0x28, 0xC5, 0x6A, 0x46, 0x5C, 0x82, 0xDB, 0xC7, 0xF6, 0x8B, 0x62, + 0x1A, 0xAD, 0xA1, 0x76, 0x1B, 0x55, 0xFF, 0xAB, 0x10, 0x2F, 0xFF, 0x4A, + 0xAA, 0x46, 0xAD, 0x33, 0x64, 0xDE, 0x28, 0x2E, 0x82, 0x7A, 0xBE, 0xEA, + 0x32, 0xFC, 0xD6, 0x14, 0x01, 0x71, 0xE6, 0xC8, 0xC9, 0x53, 0x69, 0x55, + 0xE1, 0xF8, 0x3D, 0xDD, 0xC7, 0xD5, 0x21, 0xCE, 0xFF, 0x17, 0xFC, 0x23, + 0xBF, 0xCF, 0x2D, 0xB0 +}; + +static byte b[] = { + 0x2B, 0xDD, 0x30, 0x30, 0x53, 0xAF, 0xD8, 0x3A, 0xE7, 0xE0, 0x17, 0x82, + 0x39, 0x44, 0x2C, 0xDB, 0x30, 0x88, 0x0F, 0xC8, 0x88, 0xC2, 0xB2, 0xC1, + 0x78, 0x43, 0x2F, 0xD5, 0x60, 0xD4, 0xDA, 0x43 +}; + +static byte B[] = { + 0xB5, 0x80, 0x36, 0x7F, 0x50, 0x89, 0xC1, 0x04, 0x42, 0x98, 0xD7, 0x6A, + 0x37, 0x8E, 0xF1, 0x81, 0x52, 0xC5, 0x7A, 0xA1, 0xD5, 0xB7, 0x66, 0x84, + 0xA1, 0x3E, 0x32, 0x82, 0x2B, 0x3A, 0xB5, 0xD7, 0x3D, 0x50, 0xF1, 0x58, + 0xBD, 0x89, 0x75, 0xC7, 0x51, 0xCF, 0x6C, 0x03, 0xD4, 0xCA, 0xD5, 0x6E, + 0x97, 0x4D, 0xA3, 0x1E, 0x19, 0x0B, 0xF0, 0xAA, 0x7D, 0x14, 0x90, 0x80, + 0x0E, 0xC7, 0x92, 0xAD }; static void test_SrpInit(void) @@ -76,13 +114,13 @@ static void test_SrpSetUsername(void) AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); /* invalid params */ - AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, user)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(NULL, username, usernameSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetUsername(&srp, NULL, usernameSz)); /* success */ - AssertIntEQ(0, wc_SrpSetUsername(&srp, user)); - AssertIntEQ((int) XSTRLEN(user), srp.userSz); - AssertIntEQ(0, XMEMCMP(srp.user, user, srp.userSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + AssertIntEQ((int) usernameSz, srp.userSz); + AssertIntEQ(0, XMEMCMP(srp.user, username, usernameSz)); wc_SrpTerm(&srp); } @@ -92,7 +130,14 @@ static void test_SrpSetParams(void) Srp srp; AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - AssertIntEQ(0, wc_SrpSetUsername(&srp, user)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); /* invalid params */ AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetParams(NULL, N, sizeof(N), @@ -119,6 +164,117 @@ static void test_SrpSetParams(void) wc_SrpTerm(&srp); } +static void test_SrpSetPassword(void) +{ + Srp srp; + byte v[64]; + word32 vSz = 0; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, + wc_SrpSetPassword(&srp, password, passwordSz)); + AssertIntEQ(SRP_CALL_ORDER_E, + wc_SrpGetVerifier(&srp, v, &vSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetPassword(NULL, password, passwordSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetPassword(&srp, NULL, passwordSz)); + + /* success */ + AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetVerifier(NULL, v, &vSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetVerifier(&srp, NULL, &vSz)); + AssertIntEQ(BUFFER_E, wc_SrpGetVerifier(&srp, v, &vSz)); + + /* success */ + vSz = sizeof(v); + AssertIntEQ(0, wc_SrpGetVerifier(&srp, v, &vSz)); + AssertIntEQ(vSz, sizeof(verifier)); + AssertIntEQ(0, XMEMCMP(verifier, v, vSz)); + + /* invalid params - client side srp */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(&srp, v, vSz)); + + wc_SrpTerm(&srp); + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(NULL, v, vSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpSetVerifier(&srp, NULL, vSz)); + + /* success */ + AssertIntEQ(0, wc_SrpSetVerifier(&srp, v, vSz)); + + wc_SrpTerm(&srp); +} + +static void test_SrpGenPublic(void) +{ + Srp srp; + byte public[64]; + word32 publicSz = 0; + + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGenPublic(&srp, public, &publicSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(NULL, public, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(&srp, NULL, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(&srp, public, NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGenPublic(&srp, public, &publicSz)); + + /* success */ + publicSz = sizeof(public); + AssertIntEQ(0, wc_SrpGenPublic(&srp, NULL, NULL)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srp, a, sizeof(a))); + AssertIntEQ(0, wc_SrpGenPublic(&srp, public, &publicSz)); + AssertIntEQ(publicSz, sizeof(A)); + AssertIntEQ(0, XMEMCMP(public, A, publicSz)); + + wc_SrpTerm(&srp); + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGenPublic(&srp, public, &publicSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetVerifier(&srp, verifier, sizeof(verifier))); + + /* success */ + AssertIntEQ(0, wc_SrpGenPublic(&srp, NULL, NULL)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srp, b, sizeof(b))); + AssertIntEQ(0, wc_SrpGenPublic(&srp, public, &publicSz)); + AssertIntEQ(publicSz, sizeof(B)); + AssertIntEQ(0, XMEMCMP(public, B, publicSz)); + + wc_SrpTerm(&srp); +} + #endif void SrpTest(void) @@ -127,5 +283,7 @@ void SrpTest(void) test_SrpInit(); test_SrpSetUsername(); test_SrpSetParams(); + test_SrpSetPassword(); + test_SrpGenPublic(); #endif } diff --git a/tests/unit.h b/tests/unit.h index 997186291..1a038a21f 100644 --- a/tests/unit.h +++ b/tests/unit.h @@ -27,8 +27,8 @@ #define Fail(description, result) do { \ printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \ - printf("\n\n test: "); printf description; \ - printf("\n\n result: "); printf result; \ + printf("\n expected: "); printf description; \ + printf("\n result: "); printf result; printf("\n\n"); \ abort(); \ } while(0) diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 73d79ad4f..48219d49b 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -28,6 +28,7 @@ #ifdef WOLFCRYPT_HAVE_SRP #include +#include #include static int SrpHashInit(SrpHash* hash, int type) @@ -218,21 +219,20 @@ void wc_SrpTerm(Srp* srp) } } -int wc_SrpSetUsername(Srp* srp, const char* user) +int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size) { - if (!srp || !user) + if (!srp || !username) return BAD_FUNC_ARG; - srp->user = (byte*)XMALLOC(XSTRLEN(user), NULL, DYNAMIC_TYPE_SRP); + srp->user = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_SRP); if (srp->user == NULL) return MEMORY_E; - srp->userSz = (word32) XSTRLEN(user); - XMEMCPY(srp->user, user, srp->userSz); + srp->userSz = size; + XMEMCPY(srp->user, username, srp->userSz); return 0; } - int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* g, word32 gSz, const byte* salt, word32 saltSz) @@ -240,11 +240,15 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, SrpHash hash; byte digest1[SRP_MAX_DIGEST_SIZE]; byte digest2[SRP_MAX_DIGEST_SIZE]; + byte pad = 0; int i, j, r; - if (!srp || !srp->user || !N || !g || !salt) + if (!srp || !N || !g || !salt || nSz < gSz) return BAD_FUNC_ARG; + if (!srp->user) + return SRP_CALL_ORDER_E; + /* Set N */ if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) return MP_READ_E; @@ -269,6 +273,8 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, /* Set k = H(N, g) */ r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + for (i = 0; (word32)i < nSz - gSz; i++) + SrpHashUpdate(&hash, &pad, 1); if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); if (!r) r = SrpHashFinal(&hash, srp->k); @@ -307,9 +313,12 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) byte digest[SRP_MAX_DIGEST_SIZE]; int r; - if (!srp || !srp->user || !password || srp->side != SRP_CLIENT_SIDE) + if (!srp || !password || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; + if (!srp->salt) + return SRP_CALL_ORDER_E; + /* digest = H(username | ':' | password) */ r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); @@ -341,13 +350,16 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; + if (mp_iszero(&srp->specific.client.x)) + return SRP_CALL_ORDER_E; + r = mp_init(&v); /* v = g ^ x % N */ if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.x, &srp->N, &v); - if (!r) r = (int)*size < mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; + if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; if (!r) r = mp_to_unsigned_bin(&v, verifier); - if (!r) *size = mp_unsigned_bin_size(&srp->specific.server.v); + if (!r) *size = mp_unsigned_bin_size(&v); mp_clear(&v); @@ -366,4 +378,107 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) return 0; } +int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) { + if (!srp || !private || !size) + return BAD_FUNC_ARG; + + return mp_read_unsigned_bin(srp->type == SRP_CLIENT_SIDE + ? &srp->specific.client.a + : &srp->specific.server.b, private, size); +} + +static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) { + RNG rng; + int r = wc_InitRng(&rng); + + if (!r) r = wc_RNG_GenerateBlock(&rng, private, size); + if (!r) r = wc_SrpSetPrivate(srp, private, size); + if (!r) wc_FreeRng(&rng); + + return r; +} + +int wc_SrpGenPublic(Srp* srp, byte* public, word32* size) +{ + byte* buf; + word32 len; + int r = 0; + + if (!srp || (!public && size) || (public && !size)) + return BAD_FUNC_ARG; + + if (srp->side == SRP_CLIENT_SIDE && mp_iszero(&srp->N)) + return SRP_CALL_ORDER_E; + + if (srp->side == SRP_SERVER_SIDE && (mp_iszero(&srp->N) || + mp_iszero(&srp->specific.server.v))) + return SRP_CALL_ORDER_E; + + len = mp_unsigned_bin_size(&srp->N); + if (size && *size < len) + return BUFFER_E; + + buf = public ? public : (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_SRP); + if (!buf) + return MEMORY_E; + + if (srp->side == SRP_CLIENT_SIDE) { + /* a = random() */ + if (mp_iszero(&srp->specific.client.a)) + r = wc_SrpGenPrivate(srp, buf, len); + + /* A = g ^ a % N */ + if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.a, + &srp->N, &srp->specific.client.A); + + /* extract public key to buffer */ + XMEMSET(buf, 0, len); + if (!r) r = mp_to_unsigned_bin(&srp->specific.client.A, buf); + if (!r) len = mp_unsigned_bin_size(&srp->specific.client.A); + + /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len); + + /* Server proof = H(A) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len); + + } else { + mp_int i, j; + + if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { + /* b = random() */ + if (mp_iszero(&srp->specific.server.b)) + r = wc_SrpGenPrivate(srp, buf, len); + + /* B = (k * v + (g ^ b % N)) % N */ + if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); + if (!r) r = mp_exptmod(&srp->g, &srp->specific.server.b, + &srp->N, &srp->specific.server.B); + if (!r) r = mp_mul(&i, &srp->specific.server.v, &j); + if (!r) r = mp_add(&j, &srp->specific.server.B, &i); + if (!r) r = mp_mod(&i, &srp->N, &srp->specific.server.B); + + /* extract public key to buffer */ + XMEMSET(buf, 0, len); + if (!r) r = mp_to_unsigned_bin(&srp->specific.server.B, buf); + if (!r) len = mp_unsigned_bin_size(&srp->specific.server.B); + + /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len); + + /* Server proof = H(A) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len); + + mp_clear(&i); mp_clear(&j); + } + } + + if (public) + *size = len; + else + XFREE(buf, NULL, DYNAMIC_TYPE_SRP); + + return r; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 79991fdf4..31847de9c 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -151,6 +151,8 @@ enum { ECC_INF_E = -215, /* ECC point infinity error */ ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ + SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ + MIN_CODE_E = -300 /* errors -101 - -299 */ }; @@ -163,5 +165,3 @@ WOLFSSL_API const char* wc_GetErrorString(int error); } /* extern "C" */ #endif #endif /* WOLF_CRYPT_ERROR_H */ - - diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index b89733847..8f6f9c081 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -116,20 +116,24 @@ typedef struct { } specific; } Srp; -WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); +WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); WOLFSSL_API void wc_SrpTerm(Srp* srp); -WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const char* user); +WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size); -WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, - const byte* g, word32 gSz, - const byte* salt, word32 saltSz); +WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz); -WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); +WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); -WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); +WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); -WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); +WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); + +WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size); + +WOLFSSL_API int wc_SrpGenPublic(Srp* srp, byte* public, word32* size); #ifdef __cplusplus } /* extern "C" */ From ba0c75011b519011f09a834bbc67ebb85efe97ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 28 Jul 2015 14:55:46 -0300 Subject: [PATCH 08/16] adds secret computation. --- wolfcrypt/src/srp.c | 278 ++++++++++++++++++++++++++-------------- wolfssl/wolfcrypt/srp.h | 39 ++---- 2 files changed, 193 insertions(+), 124 deletions(-) diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 48219d49b..03345ac21 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -150,6 +150,7 @@ int wc_SrpInit(Srp* srp, byte type, byte side) int r; /* validating params */ + if (!srp) return BAD_FUNC_ARG; @@ -160,61 +161,46 @@ int wc_SrpInit(Srp* srp, byte type, byte side) type != SRP_TYPE_SHA384 && type != SRP_TYPE_SHA512) return BAD_FUNC_ARG; - /* initializing common data */ + /* initializing variables */ + + if ((r = SrpHashInit(&srp->client_proof, type)) != 0) + return r; + + if ((r = SrpHashInit(&srp->server_proof, type)) != 0) + return r; + + if ((r = mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0)) != 0) + return r; + + if ((r = mp_init_multi(&srp->auth, &srp->peer, &srp->priv, &srp->pub, + 0, 0)) != 0) { + /* undo previous initializations on error */ + mp_clear(&srp->N); mp_clear(&srp->g); + mp_clear(&srp->s); mp_clear(&srp->u); + + return r; + } + srp->side = side; srp->type = type; srp->salt = NULL; srp->saltSz = 0; srp->user = NULL; srp->userSz = 0; - if (mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0) != MP_OKAY) - return MP_INIT_E; - - r = SrpHashInit(&srp->client_proof, type); - if (!r) r = SrpHashInit(&srp->server_proof, type); - - /* initializing client specific data */ - if (!r && srp->side == SRP_CLIENT_SIDE) - r = mp_init_multi(&srp->specific.client.a, &srp->specific.client.A, - &srp->specific.client.B, &srp->specific.client.x,0,0); - - /* initializing server specific data */ - if (!r && srp->side == SRP_SERVER_SIDE) - r = mp_init_multi(&srp->specific.server.b, &srp->specific.server.B, - &srp->specific.server.A, &srp->specific.server.v,0,0); - - /* undo initializations on error */ - if (r != 0) { - mp_clear(&srp->N); mp_clear(&srp->g); - mp_clear(&srp->s); mp_clear(&srp->u); - } - - return r; + return 0; } void wc_SrpTerm(Srp* srp) { if (srp) { - mp_clear(&srp->N); mp_clear(&srp->g); - mp_clear(&srp->s); mp_clear(&srp->u); + mp_clear(&srp->N); mp_clear(&srp->g); + mp_clear(&srp->s); mp_clear(&srp->u); + mp_clear(&srp->auth); mp_clear(&srp->peer); + mp_clear(&srp->priv); mp_clear(&srp->pub); XMEMSET(srp->salt, 0, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); XMEMSET(srp->user, 0, srp->userSz); XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP); - if (srp->side == SRP_CLIENT_SIDE) { - mp_clear(&srp->specific.client.a); - mp_clear(&srp->specific.client.A); - mp_clear(&srp->specific.client.B); - mp_clear(&srp->specific.client.x); - } - - if (srp->side == SRP_SERVER_SIDE) { - mp_clear(&srp->specific.server.b); - mp_clear(&srp->specific.server.B); - mp_clear(&srp->specific.server.A); - mp_clear(&srp->specific.server.v); - } - XMEMSET(srp, 0, sizeof(Srp)); } } @@ -233,6 +219,7 @@ int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size) return 0; } + int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* g, word32 gSz, const byte* salt, word32 saltSz) @@ -311,6 +298,7 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) { SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; + word32 digestSz; int r; if (!srp || !password || srp->side != SRP_CLIENT_SIDE) @@ -319,6 +307,8 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) if (!srp->salt) return SRP_CALL_ORDER_E; + digestSz = SrpHashSize(srp->type); + /* digest = H(username | ':' | password) */ r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); @@ -329,13 +319,11 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) /* digest = H(salt | H(username | ':' | password)) */ if (!r) r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); - if (!r) r = SrpHashUpdate(&hash, digest, SrpHashSize(srp->type)); + if (!r) r = SrpHashUpdate(&hash, digest, digestSz); if (!r) r = SrpHashFinal(&hash, digest); /* Set x (private key) */ - if (!r && mp_read_unsigned_bin(&srp->specific.client.x, digest, - SrpHashSize(srp->type)) != MP_OKAY) - r = MP_READ_E; + if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); @@ -350,13 +338,13 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; - if (mp_iszero(&srp->specific.client.x)) + if (mp_iszero(&srp->auth)) return SRP_CALL_ORDER_E; r = mp_init(&v); /* v = g ^ x % N */ - if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.x, &srp->N, &v); + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; if (!r) r = mp_to_unsigned_bin(&v, verifier); if (!r) *size = mp_unsigned_bin_size(&v); @@ -371,23 +359,19 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) if (!srp || !verifier || srp->side != SRP_SERVER_SIDE) return BAD_FUNC_ARG; - if (mp_read_unsigned_bin(&srp->specific.server.v, verifier, size) - != MP_OKAY) - return MP_READ_E; - - return 0; + return mp_read_unsigned_bin(&srp->auth, verifier, size); } -int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) { +int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) +{ if (!srp || !private || !size) return BAD_FUNC_ARG; - return mp_read_unsigned_bin(srp->type == SRP_CLIENT_SIDE - ? &srp->specific.client.a - : &srp->specific.server.b, private, size); + return mp_read_unsigned_bin(&srp->priv, private, size); } -static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) { +static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) +{ RNG rng; int r = wc_InitRng(&rng); @@ -407,11 +391,10 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size) if (!srp || (!public && size) || (public && !size)) return BAD_FUNC_ARG; - if (srp->side == SRP_CLIENT_SIDE && mp_iszero(&srp->N)) + if (mp_iszero(&srp->N)) return SRP_CALL_ORDER_E; - if (srp->side == SRP_SERVER_SIDE && (mp_iszero(&srp->N) || - mp_iszero(&srp->specific.server.v))) + if (srp->side == SRP_SERVER_SIDE && mp_iszero(&srp->auth)) return SRP_CALL_ORDER_E; len = mp_unsigned_bin_size(&srp->N); @@ -422,55 +405,44 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size) if (!buf) return MEMORY_E; + /* priv = random() */ + if (mp_iszero(&srp->priv)) + r = wc_SrpGenPrivate(srp, buf, len); + + /* client side: A = g ^ a % N */ if (srp->side == SRP_CLIENT_SIDE) { - /* a = random() */ - if (mp_iszero(&srp->specific.client.a)) - r = wc_SrpGenPrivate(srp, buf, len); - /* A = g ^ a % N */ - if (!r) r = mp_exptmod(&srp->g, &srp->specific.client.a, - &srp->N, &srp->specific.client.A); + if (!r) r = mp_exptmod(&srp->g, &srp->priv, + &srp->N, &srp->pub); - /* extract public key to buffer */ - XMEMSET(buf, 0, len); - if (!r) r = mp_to_unsigned_bin(&srp->specific.client.A, buf); - if (!r) len = mp_unsigned_bin_size(&srp->specific.client.A); + /* server side: B = (k * v + (g ^ b % N)) % N */ + } else { + mp_int i, j; + if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { + if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); + if (!r) r = mp_exptmod(&srp->g, &srp->priv, + &srp->N, &srp->pub); + if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); + if (!r) r = mp_add(&j, &srp->pub, &i); + if (!r) r = mp_mod(&i, &srp->N, &srp->pub); + + mp_clear(&i); mp_clear(&j); + } + } + + /* extract public key to buffer */ + XMEMSET(buf, 0, len); + if (!r) r = mp_to_unsigned_bin(&srp->pub, buf); + if (!r) len = mp_unsigned_bin_size(&srp->pub); + + /* update proofs */ + if (srp->side == SRP_CLIENT_SIDE) { /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */ if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len); /* Server proof = H(A) */ if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len); - - } else { - mp_int i, j; - - if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { - /* b = random() */ - if (mp_iszero(&srp->specific.server.b)) - r = wc_SrpGenPrivate(srp, buf, len); - - /* B = (k * v + (g ^ b % N)) % N */ - if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); - if (!r) r = mp_exptmod(&srp->g, &srp->specific.server.b, - &srp->N, &srp->specific.server.B); - if (!r) r = mp_mul(&i, &srp->specific.server.v, &j); - if (!r) r = mp_add(&j, &srp->specific.server.B, &i); - if (!r) r = mp_mod(&i, &srp->N, &srp->specific.server.B); - - /* extract public key to buffer */ - XMEMSET(buf, 0, len); - if (!r) r = mp_to_unsigned_bin(&srp->specific.server.B, buf); - if (!r) len = mp_unsigned_bin_size(&srp->specific.server.B); - - /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len); - - /* Server proof = H(A) */ - if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len); - - mp_clear(&i); mp_clear(&j); - } } if (public) @@ -481,4 +453,112 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size) return r; } +static int wc_SrpSetU(Srp* srp, byte* peersKey, word32 peersKeySz) +{ + SrpHash hash; + byte digest[SRP_MAX_DIGEST_SIZE]; + byte* public = NULL; + word32 publicSz = 0; + word32 modulusSz = mp_unsigned_bin_size(&srp->N); + byte pad = 0; + word32 i; + int r = SrpHashInit(&hash, srp->type); + + if (!r && srp->side == SRP_CLIENT_SIDE) { + publicSz = mp_unsigned_bin_size(&srp->pub); + public = (byte*)XMALLOC(publicSz, NULL, DYNAMIC_TYPE_SRP); + + if (public == NULL) + r = MEMORY_E; + + /* H(A) */ + if (!r) r = mp_to_unsigned_bin(&srp->pub, public); + for (i = 0; i < modulusSz - publicSz; i++) + SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, public, publicSz); + + /* H(A | B) */ + if (!r) r = mp_read_unsigned_bin(&srp->peer, + peersKey, peersKeySz); + for (i = 0; i < modulusSz - peersKeySz; i++) + SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, peersKey, peersKeySz); + + /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A | B) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, peersKey, peersKeySz); + + } else if (!r && srp->side == SRP_SERVER_SIDE) { + publicSz = mp_unsigned_bin_size(&srp->pub); + public = (byte*)XMALLOC(publicSz, NULL, DYNAMIC_TYPE_SRP); + + if (public == NULL) + r = MEMORY_E; + + /* H(A) */ + if (!r) r = mp_read_unsigned_bin(&srp->peer, + peersKey, peersKeySz); + for (i = 0; i < modulusSz - peersKeySz; i++) + SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, peersKey, peersKeySz); + + /* H(A | B) */ + if (!r) r = mp_to_unsigned_bin(&srp->pub, public); + for (i = 0; i < modulusSz - publicSz; i++) + SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, public, publicSz); + } + + if (!r) r = SrpHashFinal(&hash, digest); + if (!r) r = mp_read_unsigned_bin(&srp->u, digest, SrpHashSize(srp->type)); + + XFREE(public, NULL, DYNAMIC_TYPE_SRP); + + return r; +} + +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* peersKey, word32 peersKeySz) +{ + mp_int i, j; + int r; + + if (!srp || !peersKey || peersKeySz == 0) + return BAD_FUNC_ARG; + + if ((r = mp_init_multi(&i, &j, 0, 0, 0, 0)) != MP_OKAY) + return r; + + r = wc_SrpSetU(srp, peersKey, peersKeySz); + + if (!r && srp->side == SRP_CLIENT_SIDE) { + r = mp_read_unsigned_bin(&i, srp->k, SrpHashSize(srp->type)); + + /* i = B - k * v */ + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &j); + if (!r) r = mp_mulmod(&i, &j, &srp->N, &srp->s); + if (!r) r = mp_sub(&srp->peer, &srp->s, &i); + + /* j = a + u * x */ + if (!r) r = mp_mulmod(&srp->u, &srp->auth, &srp->N, &srp->s); + if (!r) r = mp_add(&srp->priv, &srp->s, &j); + + /* s = i ^ j % N */ + if (!r) r = mp_exptmod(&i, &j, &srp->N, &srp->s); + + } else if (!r && srp->side == SRP_SERVER_SIDE) { + /* i = v ^ u % N */ + if (!r) r = mp_exptmod(&srp->auth, &srp->u, &srp->N, &i); + + /* j = A * i % N */ + if (!r) r = mp_mulmod(&srp->peer, &i, &srp->N, &j); + + /* s = j * b % N */ + if (!r) r = mp_exptmod(&j, &srp->priv, &srp->N, &srp->s); + } + + mp_clear(&i); + mp_clear(&j); + + return r; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 8f6f9c081..7b19a4025 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -83,40 +83,27 @@ typedef struct { } SrpHash; typedef struct { - mp_int a; /**< Private ephemeral value. Random. */ - mp_int A; /**< Public ephemeral value. pow(g, a, N) */ - mp_int B; /**< Server's public ephemeral value. */ - mp_int x; /**< Priv key. H(salt, H(user, ":", pswd)) */ -} SrpClient; - -typedef struct { - mp_int b; /**< Private ephemeral value. */ - mp_int B; /**< Public ephemeral value. */ - mp_int A; /**< Client's public ephemeral value. */ - mp_int v; /**< Verifier. v = pow(g, x, N) */ -} SrpServer; - -typedef struct { - byte side; /**< Client or Server side. */ - byte type; /**< Hash type, SHA[1:256:384:512] */ - mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ - mp_int g; /**< Generator. A generator modulo N. */ - mp_int s; /**< Session key. */ - byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ - mp_int u; /**< Random scrambling parameeter. */ + byte side; /**< SRP_CLIENT_SIDE or SRP_SERVER_SIDE */ + byte type; /**< Hash type, one of SRP_TYPE_SHA[|256|384|512] */ byte* user; /**< Username, login. */ word32 userSz; /**< Username length. */ byte* salt; /**< Small salt. */ word32 saltSz; /**< Salt length. */ + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ + mp_int g; /**< Generator. A generator modulo N. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ + mp_int auth; /**< Priv key. H(salt, H(user, ":", pswd)) */ + mp_int priv; /**< Private ephemeral value. */ + mp_int pub; /**< Public ephemeral value. */ + mp_int peer; /**< Peer's public ephemeral value. */ + mp_int u; /**< Random scrambling parameeter. */ SrpHash client_proof; /**< Client proof. Sent to Server. */ SrpHash server_proof; /**< Server proof. Sent to Client. */ - union { - SrpClient client; - SrpServer server; - } specific; + mp_int s; /**< Session key. */ } Srp; WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); + WOLFSSL_API void wc_SrpTerm(Srp* srp); WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size); @@ -135,6 +122,8 @@ WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size); WOLFSSL_API int wc_SrpGenPublic(Srp* srp, byte* public, word32* size); +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* peersKey, word32 peersKeySz); + #ifdef __cplusplus } /* extern "C" */ #endif From 490d063deca5c9103172a6fb6cfd5be72562c88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 28 Jul 2015 18:59:15 -0300 Subject: [PATCH 09/16] adds key computation. removes unnecessary fields from the srp struct. --- tests/srp.c | 115 +++++++++++++++---- wolfcrypt/src/srp.c | 239 ++++++++++++++++++++-------------------- wolfssl/wolfcrypt/srp.h | 37 +++---- 3 files changed, 233 insertions(+), 158 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index 7ec4a25c8..02e97d0f4 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -5,16 +5,16 @@ * This file is part of wolfSSL. (formerly known as CyaSSL) * * wolfSSL is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * it under the terms of the GNU Geteral Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Geteral Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Geteral Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ @@ -92,6 +92,13 @@ static byte B[] = { 0x0E, 0xC7, 0x92, 0xAD }; +static byte key[] = { + 0x66, 0x00, 0x9D, 0x58, 0xB3, 0xD2, 0x0D, 0x4B, 0x69, 0x7F, 0xCF, 0x48, + 0xFF, 0x8F, 0x15, 0x81, 0x4C, 0x4B, 0xFE, 0x9D, 0x85, 0x77, 0x88, 0x60, + 0x1D, 0x1E, 0x51, 0xCF, 0x75, 0xCC, 0x58, 0x00, 0xE7, 0x8D, 0x22, 0x87, + 0x13, 0x6C, 0x88, 0x55 +}; + static void test_SrpInit(void) { Srp srp; @@ -218,63 +225,126 @@ static void test_SrpSetPassword(void) wc_SrpTerm(&srp); } -static void test_SrpGenPublic(void) +static void test_SrpGetPublic(void) { Srp srp; byte public[64]; word32 publicSz = 0; AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); - - /* invalid call order */ - AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGenPublic(&srp, public, &publicSz)); - - /* fix call order */ AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), g, sizeof(g), salt, sizeof(salt))); + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, public, &publicSz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetPassword(&srp, password, passwordSz)); + /* invalid params */ - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(NULL, public, &publicSz)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(&srp, NULL, &publicSz)); - AssertIntEQ(BAD_FUNC_ARG, wc_SrpGenPublic(&srp, public, NULL)); - AssertIntEQ(BUFFER_E, wc_SrpGenPublic(&srp, public, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(NULL, public, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, NULL, &publicSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetPublic(&srp, public, NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetPublic(&srp, public, &publicSz)); /* success */ publicSz = sizeof(public); - AssertIntEQ(0, wc_SrpGenPublic(&srp, NULL, NULL)); - AssertIntEQ(0, wc_SrpSetPrivate(&srp, a, sizeof(a))); - AssertIntEQ(0, wc_SrpGenPublic(&srp, public, &publicSz)); + AssertIntEQ(0, wc_SrpGetPublic(&srp, public, &publicSz)); AssertIntEQ(publicSz, sizeof(A)); AssertIntEQ(0, XMEMCMP(public, A, publicSz)); wc_SrpTerm(&srp); - AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srp, SRP_TYPE_SHA, SRP_SERVER_SIDE)); AssertIntEQ(0, wc_SrpSetUsername(&srp, username, usernameSz)); AssertIntEQ(0, wc_SrpSetParams(&srp, N, sizeof(N), g, sizeof(g), salt, sizeof(salt))); /* invalid call order */ - AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGenPublic(&srp, public, &publicSz)); + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpGetPublic(&srp, public, &publicSz)); /* fix call order */ AssertIntEQ(0, wc_SrpSetVerifier(&srp, verifier, sizeof(verifier))); /* success */ - AssertIntEQ(0, wc_SrpGenPublic(&srp, NULL, NULL)); - AssertIntEQ(0, wc_SrpSetPrivate(&srp, b, sizeof(b))); - AssertIntEQ(0, wc_SrpGenPublic(&srp, public, &publicSz)); + AssertIntEQ(0, wc_SrpGetPublic(&srp, public, &publicSz)); AssertIntEQ(publicSz, sizeof(B)); AssertIntEQ(0, XMEMCMP(public, B, publicSz)); wc_SrpTerm(&srp); } +static void test_SrpComputeKey(void) +{ + Srp cli, srv; + byte clientPubKey[64]; + byte serverPubKey[64]; + word32 clientPubKeySz = 64; + word32 serverPubKeySz = 64; + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + /* invalid call order */ + AssertIntEQ(SRP_CALL_ORDER_E, wc_SrpComputeKey(&cli, + clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + + /* fix call order */ + AssertIntEQ(0, wc_SrpSetUsername(&cli, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username, usernameSz)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(0, wc_SrpSetParams(&srv, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password, passwordSz)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, verifier, sizeof(verifier))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, a, sizeof(a))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, A, clientPubKeySz)); + AssertIntEQ(0, wc_SrpSetPrivate(&srv, b, sizeof(b))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, B, serverPubKeySz)); + + /* invalid params */ + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(NULL, + clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + NULL, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + clientPubKey, 0, + serverPubKey, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + clientPubKey, clientPubKeySz, + NULL, serverPubKeySz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpComputeKey(&cli, + clientPubKey, clientPubKeySz, + serverPubKey, 0)); + + /* success */ + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, key, sizeof(key))); + AssertIntEQ(0, XMEMCMP(srv.key, key, sizeof(key))); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + #endif void SrpTest(void) @@ -284,6 +354,7 @@ void SrpTest(void) test_SrpSetUsername(); test_SrpSetParams(); test_SrpSetPassword(); - test_SrpGenPublic(); + test_SrpGetPublic(); + test_SrpComputeKey(); #endif } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 03345ac21..a41c43109 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -169,18 +169,10 @@ int wc_SrpInit(Srp* srp, byte type, byte side) if ((r = SrpHashInit(&srp->server_proof, type)) != 0) return r; - if ((r = mp_init_multi(&srp->N, &srp->g, &srp->s, &srp->u, 0, 0)) != 0) + if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth, + &srp->priv, &srp->u, 0)) != 0) return r; - if ((r = mp_init_multi(&srp->auth, &srp->peer, &srp->priv, &srp->pub, - 0, 0)) != 0) { - /* undo previous initializations on error */ - mp_clear(&srp->N); mp_clear(&srp->g); - mp_clear(&srp->s); mp_clear(&srp->u); - - return r; - } - srp->side = side; srp->type = type; srp->salt = NULL; srp->saltSz = 0; srp->user = NULL; srp->userSz = 0; @@ -192,9 +184,8 @@ void wc_SrpTerm(Srp* srp) { if (srp) { mp_clear(&srp->N); mp_clear(&srp->g); - mp_clear(&srp->s); mp_clear(&srp->u); - mp_clear(&srp->auth); mp_clear(&srp->peer); - mp_clear(&srp->priv); mp_clear(&srp->pub); + mp_clear(&srp->auth); mp_clear(&srp->priv); + mp_clear(&srp->u); XMEMSET(srp->salt, 0, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); @@ -367,6 +358,9 @@ int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) if (!srp || !private || !size) return BAD_FUNC_ARG; + if (mp_iszero(&srp->auth)) + return SRP_CALL_ORDER_E; + return mp_read_unsigned_bin(&srp->priv, private, size); } @@ -382,38 +376,32 @@ static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) return r; } -int wc_SrpGenPublic(Srp* srp, byte* public, word32* size) +int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) { - byte* buf; - word32 len; - int r = 0; + mp_int pubkey; + word32 modulusSz; + int r = mp_init(&pubkey); - if (!srp || (!public && size) || (public && !size)) + if (r != 0) + return r; + + if (!srp || !public || !size) return BAD_FUNC_ARG; - if (mp_iszero(&srp->N)) + if (mp_iszero(&srp->auth)) return SRP_CALL_ORDER_E; - if (srp->side == SRP_SERVER_SIDE && mp_iszero(&srp->auth)) - return SRP_CALL_ORDER_E; - - len = mp_unsigned_bin_size(&srp->N); - if (size && *size < len) + modulusSz = mp_unsigned_bin_size(&srp->N); + if (*size < modulusSz) return BUFFER_E; - buf = public ? public : (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_SRP); - if (!buf) - return MEMORY_E; - /* priv = random() */ if (mp_iszero(&srp->priv)) - r = wc_SrpGenPrivate(srp, buf, len); + r = wc_SrpGenPrivate(srp, public, modulusSz); /* client side: A = g ^ a % N */ if (srp->side == SRP_CLIENT_SIDE) { - - if (!r) r = mp_exptmod(&srp->g, &srp->priv, - &srp->N, &srp->pub); + if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); /* server side: B = (k * v + (g ^ b % N)) % N */ } else { @@ -421,142 +409,159 @@ int wc_SrpGenPublic(Srp* srp, byte* public, word32* size) if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); - if (!r) r = mp_exptmod(&srp->g, &srp->priv, - &srp->N, &srp->pub); + if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); - if (!r) r = mp_add(&j, &srp->pub, &i); - if (!r) r = mp_mod(&i, &srp->N, &srp->pub); + if (!r) r = mp_add(&j, &pubkey, &i); + if (!r) r = mp_mod(&i, &srp->N, &pubkey); mp_clear(&i); mp_clear(&j); } } /* extract public key to buffer */ - XMEMSET(buf, 0, len); - if (!r) r = mp_to_unsigned_bin(&srp->pub, buf); - if (!r) len = mp_unsigned_bin_size(&srp->pub); - - /* update proofs */ - if (srp->side == SRP_CLIENT_SIDE) { - /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, buf, len); - - /* Server proof = H(A) */ - if (!r) r = SrpHashUpdate(&srp->server_proof, buf, len); - } - - if (public) - *size = len; - else - XFREE(buf, NULL, DYNAMIC_TYPE_SRP); + XMEMSET(public, 0, modulusSz); + if (!r) r = mp_to_unsigned_bin(&pubkey, public); + if (!r) *size = mp_unsigned_bin_size(&pubkey); + mp_clear(&pubkey); return r; } -static int wc_SrpSetU(Srp* srp, byte* peersKey, word32 peersKeySz) +static int wc_SrpSetU(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz) { SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; - byte* public = NULL; - word32 publicSz = 0; word32 modulusSz = mp_unsigned_bin_size(&srp->N); byte pad = 0; word32 i; int r = SrpHashInit(&hash, srp->type); - if (!r && srp->side == SRP_CLIENT_SIDE) { - publicSz = mp_unsigned_bin_size(&srp->pub); - public = (byte*)XMALLOC(publicSz, NULL, DYNAMIC_TYPE_SRP); + /* H(A) */ + for (i = 0; !r && i < modulusSz - clientPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); - if (public == NULL) - r = MEMORY_E; + /* H(A | B) */ + for (i = 0; !r && i < modulusSz - serverPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); - /* H(A) */ - if (!r) r = mp_to_unsigned_bin(&srp->pub, public); - for (i = 0; i < modulusSz - publicSz; i++) - SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, public, publicSz); + /* client proof = H( H(N) ^ H(g) | H(user) | salt | A | B) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); - /* H(A | B) */ - if (!r) r = mp_read_unsigned_bin(&srp->peer, - peersKey, peersKeySz); - for (i = 0; i < modulusSz - peersKeySz; i++) - SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, peersKey, peersKeySz); - - /* Client proof = H( H(N) ^ H(g) | H(user) | salt | A | B) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, peersKey, peersKeySz); - - } else if (!r && srp->side == SRP_SERVER_SIDE) { - publicSz = mp_unsigned_bin_size(&srp->pub); - public = (byte*)XMALLOC(publicSz, NULL, DYNAMIC_TYPE_SRP); - - if (public == NULL) - r = MEMORY_E; - - /* H(A) */ - if (!r) r = mp_read_unsigned_bin(&srp->peer, - peersKey, peersKeySz); - for (i = 0; i < modulusSz - peersKeySz; i++) - SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, peersKey, peersKeySz); - - /* H(A | B) */ - if (!r) r = mp_to_unsigned_bin(&srp->pub, public); - for (i = 0; i < modulusSz - publicSz; i++) - SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, public, publicSz); - } + /* server proof = H(A) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); + /* set u */ if (!r) r = SrpHashFinal(&hash, digest); if (!r) r = mp_read_unsigned_bin(&srp->u, digest, SrpHashSize(srp->type)); - XFREE(public, NULL, DYNAMIC_TYPE_SRP); - return r; } -WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* peersKey, word32 peersKeySz) +static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) { - mp_int i, j; + SrpHash hash; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 digestSz = SrpHashSize(srp->type); + int r; + word32 i = 0; + word32 pos = 0; + byte cnt[4]; + + for (i = 0; pos < digestSz * 2; i++) { + cnt[0] = (i >> 24) & 0xFF; + cnt[1] = (i >> 16) & 0xFF; + cnt[2] = (i >> 8) & 0xFF; + cnt[3] = i & 0xFF; + + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, secret, size); + if (!r) r = SrpHashUpdate(&hash, cnt, 4); + + if(pos + digestSz > digestSz * 2) { + if (!r) r = SrpHashFinal(&hash, digest); + XMEMCPY(srp->key + pos, digest, digestSz * 2 - pos); + pos = digestSz * 2; + } + else { + if (!r) r = SrpHashFinal(&hash, srp->key + pos); + pos += digestSz; + } + } + + XMEMSET(digest, 0, sizeof(digest)); + XMEMSET(&hash, 0, sizeof(SrpHash)); + + return r; +} + +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, + byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz) +{ + byte* secret; + word32 secretSz; + mp_int i, j, s; int r; - if (!srp || !peersKey || peersKeySz == 0) + if (!srp || !clientPubKey || clientPubKeySz == 0 + || !serverPubKey || serverPubKeySz == 0) return BAD_FUNC_ARG; - if ((r = mp_init_multi(&i, &j, 0, 0, 0, 0)) != MP_OKAY) + if (mp_iszero(&srp->priv)) + return SRP_CALL_ORDER_E; + + if ((r = mp_init_multi(&i, &j, &s, 0, 0, 0)) != MP_OKAY) return r; - r = wc_SrpSetU(srp, peersKey, peersKeySz); + secretSz = mp_unsigned_bin_size(&srp->N); + secret = (byte*)XMALLOC(secretSz, NULL, DYNAMIC_TYPE_SRP); + if (secret == NULL) { + mp_clear(&i); mp_clear(&j); mp_clear(&s); + return MEMORY_E; + } + + r = wc_SrpSetU(srp, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz); if (!r && srp->side == SRP_CLIENT_SIDE) { - r = mp_read_unsigned_bin(&i, srp->k, SrpHashSize(srp->type)); - /* i = B - k * v */ + r = mp_read_unsigned_bin(&i, srp->k, SrpHashSize(srp->type)); if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &j); - if (!r) r = mp_mulmod(&i, &j, &srp->N, &srp->s); - if (!r) r = mp_sub(&srp->peer, &srp->s, &i); + if (!r) r = mp_mulmod(&i, &j, &srp->N, &s); + if (!r) r = mp_read_unsigned_bin(&j, serverPubKey, serverPubKeySz); + if (!r) r = mp_sub(&j, &s, &i); /* j = a + u * x */ - if (!r) r = mp_mulmod(&srp->u, &srp->auth, &srp->N, &srp->s); - if (!r) r = mp_add(&srp->priv, &srp->s, &j); + if (!r) r = mp_mulmod(&srp->u, &srp->auth, &srp->N, &s); + if (!r) r = mp_add(&srp->priv, &s, &j); - /* s = i ^ j % N */ - if (!r) r = mp_exptmod(&i, &j, &srp->N, &srp->s); + /* secret = i ^ j % N */ + if (!r) r = mp_exptmod(&i, &j, &srp->N, &s); } else if (!r && srp->side == SRP_SERVER_SIDE) { /* i = v ^ u % N */ - if (!r) r = mp_exptmod(&srp->auth, &srp->u, &srp->N, &i); + r = mp_exptmod(&srp->auth, &srp->u, &srp->N, &i); /* j = A * i % N */ - if (!r) r = mp_mulmod(&srp->peer, &i, &srp->N, &j); + if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); + if (!r) r = mp_mulmod(&s, &i, &srp->N, &j); - /* s = j * b % N */ - if (!r) r = mp_exptmod(&j, &srp->priv, &srp->N, &srp->s); + /* secret = j * b % N */ + if (!r) r = mp_exptmod(&j, &srp->priv, &srp->N, &s); } - mp_clear(&i); - mp_clear(&j); + if (!r) r = mp_to_unsigned_bin(&s, secret); + if (!r) r = wc_SrpSetK(srp, secret, mp_unsigned_bin_size(&s)); + + /* client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, sizeof(srp->key)); + + XFREE(secret, NULL, DYNAMIC_TYPE_SRP); + mp_clear(&i); mp_clear(&j); mp_clear(&s); return r; } diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 7b19a4025..9b76de8b4 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -83,23 +83,21 @@ typedef struct { } SrpHash; typedef struct { - byte side; /**< SRP_CLIENT_SIDE or SRP_SERVER_SIDE */ - byte type; /**< Hash type, one of SRP_TYPE_SHA[|256|384|512] */ - byte* user; /**< Username, login. */ - word32 userSz; /**< Username length. */ - byte* salt; /**< Small salt. */ - word32 saltSz; /**< Salt length. */ - mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ - mp_int g; /**< Generator. A generator modulo N. */ - byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ - mp_int auth; /**< Priv key. H(salt, H(user, ":", pswd)) */ - mp_int priv; /**< Private ephemeral value. */ - mp_int pub; /**< Public ephemeral value. */ - mp_int peer; /**< Peer's public ephemeral value. */ - mp_int u; /**< Random scrambling parameeter. */ - SrpHash client_proof; /**< Client proof. Sent to Server. */ - SrpHash server_proof; /**< Server proof. Sent to Client. */ - mp_int s; /**< Session key. */ + byte side; /**< SRP_CLIENT_SIDE or SRP_SERVER_SIDE */ + byte type; /**< Hash type, one of SRP_TYPE_SHA[|256|384|512] */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ + mp_int g; /**< Generator. A generator modulo N. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ + mp_int auth; /**< client: x = H(salt, H(user, ":", pswd)) */ + mp_int priv; /**< Private ephemeral value. */ + mp_int u; /**< Random scrambling parameeter. */ + SrpHash client_proof; /**< Client proof. Sent to Server. */ + SrpHash server_proof; /**< Server proof. Sent to Client. */ + byte key[2 * SRP_MAX_DIGEST_SIZE]; /**< Session key. */ } Srp; WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); @@ -120,9 +118,10 @@ WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size); -WOLFSSL_API int wc_SrpGenPublic(Srp* srp, byte* public, word32* size); +WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* public, word32* size); -WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* peersKey, word32 peersKeySz); +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz); #ifdef __cplusplus } /* extern "C" */ From 53224281d2091f2555a4eadbfba545f7ec26e536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Thu, 30 Jul 2015 16:27:12 -0300 Subject: [PATCH 10/16] adds proof getter and verifier for both sides. --- tests/srp.c | 82 +++++++++++++++++++++++++++++++++ wolfcrypt/src/srp.c | 66 ++++++++++++++++++++++++-- wolfssl/wolfcrypt/error-crypt.h | 1 + wolfssl/wolfcrypt/srp.h | 4 ++ 4 files changed, 148 insertions(+), 5 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index 02e97d0f4..0e3af9c4a 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -99,6 +99,16 @@ static byte key[] = { 0x13, 0x6C, 0x88, 0x55 }; +static byte client_proof[] = { + 0x0D, 0x49, 0xE1, 0x9C, 0x3A, 0x88, 0x43, 0x15, 0x45, 0xA8, 0xAC, 0xAB, + 0xEA, 0x15, 0x1A, 0xEE, 0xF9, 0x38, 0x4D, 0x21 +}; + +static byte server_proof[] = { + 0xBD, 0xB1, 0x20, 0x70, 0x46, 0xC9, 0xD6, 0xCC, 0xE2, 0x1D, 0x75, 0xA2, + 0xD0, 0xAF, 0xC5, 0xBC, 0xAE, 0x12, 0xFC, 0x75 +}; + static void test_SrpInit(void) { Srp srp; @@ -345,6 +355,77 @@ static void test_SrpComputeKey(void) wc_SrpTerm(&srv); } +static void test_SrpGetProofAndVerify(void) +{ + Srp cli, srv; + byte clientPubKey[64]; + byte serverPubKey[64]; + word32 clientPubKeySz = 64; + word32 serverPubKeySz = 64; + byte clientProof[SRP_MAX_DIGEST_SIZE]; + byte serverProof[SRP_MAX_DIGEST_SIZE]; + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE)); + + AssertIntEQ(0, wc_SrpSetUsername(&cli, username, usernameSz)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username, usernameSz)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + AssertIntEQ(0, wc_SrpSetParams(&srv, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password, passwordSz)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, verifier, sizeof(verifier))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, a, sizeof(a))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, A, clientPubKeySz)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srv, b, sizeof(b))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, B, serverPubKeySz)); + + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, key, sizeof(key))); + + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(srv.key, key, sizeof(key))); + + /* invalid params */ + serverProofSz = 0; + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(NULL, clientProof,&clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(&cli, NULL, &clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, wc_SrpGetProof(&cli, clientProof,NULL)); + AssertIntEQ(BUFFER_E, wc_SrpGetProof(&srv, serverProof,&serverProofSz)); + + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpVerifyPeersProof(NULL, clientProof, clientProofSz)); + AssertIntEQ(BAD_FUNC_ARG, + wc_SrpVerifyPeersProof(&cli, NULL, clientProofSz)); + AssertIntEQ(BUFFER_E, + wc_SrpVerifyPeersProof(&srv, serverProof, serverProofSz)); + serverProofSz = SRP_MAX_DIGEST_SIZE; + + /* success */ + AssertIntEQ(0, wc_SrpGetProof(&cli, clientProof, &clientProofSz)); + AssertIntEQ(0, XMEMCMP(clientProof, client_proof, sizeof(client_proof))); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz)); + AssertIntEQ(0, wc_SrpGetProof(&srv, serverProof, &serverProofSz)); + AssertIntEQ(0, XMEMCMP(serverProof, server_proof, sizeof(server_proof))); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz)); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + #endif void SrpTest(void) @@ -356,5 +437,6 @@ void SrpTest(void) test_SrpSetPassword(); test_SrpGetPublic(); test_SrpComputeKey(); + test_SrpGetProofAndVerify(); #endif } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index a41c43109..95881b9c9 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -163,6 +163,8 @@ int wc_SrpInit(Srp* srp, byte type, byte side) /* initializing variables */ + XMEMSET(srp, 0, sizeof(Srp)); + if ((r = SrpHashInit(&srp->client_proof, type)) != 0) return r; @@ -498,11 +500,11 @@ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) return r; } -WOLFSSL_API int wc_SrpComputeKey(Srp* srp, - byte* clientPubKey, word32 clientPubKeySz, - byte* serverPubKey, word32 serverPubKeySz) +int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz) { byte* secret; + word32 digestSz; word32 secretSz; mp_int i, j, s; int r; @@ -524,12 +526,14 @@ WOLFSSL_API int wc_SrpComputeKey(Srp* srp, return MEMORY_E; } + digestSz = SrpHashSize(srp->type); + r = wc_SrpSetU(srp, clientPubKey, clientPubKeySz, serverPubKey, serverPubKeySz); if (!r && srp->side == SRP_CLIENT_SIDE) { /* i = B - k * v */ - r = mp_read_unsigned_bin(&i, srp->k, SrpHashSize(srp->type)); + r = mp_read_unsigned_bin(&i, srp->k, digestSz); if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &j); if (!r) r = mp_mulmod(&i, &j, &srp->N, &s); if (!r) r = mp_read_unsigned_bin(&j, serverPubKey, serverPubKeySz); @@ -558,7 +562,7 @@ WOLFSSL_API int wc_SrpComputeKey(Srp* srp, if (!r) r = wc_SrpSetK(srp, secret, mp_unsigned_bin_size(&s)); /* client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, sizeof(srp->key)); + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, digestSz * 2); XFREE(secret, NULL, DYNAMIC_TYPE_SRP); mp_clear(&i); mp_clear(&j); mp_clear(&s); @@ -566,4 +570,56 @@ WOLFSSL_API int wc_SrpComputeKey(Srp* srp, return r; } +int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) +{ + int r; + + if (!srp || !proof || !size) + return BAD_FUNC_ARG; + + if (*size < SrpHashSize(srp->type)) + return BUFFER_E; + + if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE + ? &srp->client_proof + : &srp->server_proof, proof)) != 0) + return r; + + *size = SrpHashSize(srp->type); + + if (srp->side == SRP_CLIENT_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, (*size) * 2); + } + + return r; +} + +int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) +{ + byte digest[SRP_MAX_DIGEST_SIZE]; + int r; + + if (!srp || !proof) + return BAD_FUNC_ARG; + + if (size != SrpHashSize(srp->type)) + return BUFFER_E; + + r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof + : &srp->client_proof, digest); + + if (srp->side == SRP_SERVER_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, size * 2); + } + + if (!r && XMEMCMP(proof, digest, size) != 0) + r = SRP_VERIFY_E; + + return r; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 31847de9c..84714e462 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -152,6 +152,7 @@ enum { ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -218, /* SRP proof verification failed. */ MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 9b76de8b4..56cf41329 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -123,6 +123,10 @@ WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* public, word32* size); WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, byte* serverPubKey, word32 serverPubKeySz); +WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); + +WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); + #ifdef __cplusplus } /* extern "C" */ #endif From 1d99bd333903c3bfd28dc2f633cf282ca7191d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 3 Aug 2015 12:30:56 -0300 Subject: [PATCH 11/16] removes u from srp struct. --- wolfcrypt/src/srp.c | 179 +++++++++++++++++++++------------------- wolfssl/wolfcrypt/srp.h | 3 +- 2 files changed, 97 insertions(+), 85 deletions(-) diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 95881b9c9..96dda59a3 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -172,7 +172,7 @@ int wc_SrpInit(Srp* srp, byte type, byte side) return r; if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth, - &srp->priv, &srp->u, 0)) != 0) + &srp->priv, 0, 0)) != 0) return r; srp->side = side; srp->type = type; @@ -187,7 +187,6 @@ void wc_SrpTerm(Srp* srp) if (srp) { mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->auth); mp_clear(&srp->priv); - mp_clear(&srp->u); XMEMSET(srp->salt, 0, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); @@ -429,68 +428,32 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) return r; } -static int wc_SrpSetU(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, - byte* serverPubKey, word32 serverPubKeySz) -{ - SrpHash hash; - byte digest[SRP_MAX_DIGEST_SIZE]; - word32 modulusSz = mp_unsigned_bin_size(&srp->N); - byte pad = 0; - word32 i; - int r = SrpHashInit(&hash, srp->type); - - /* H(A) */ - for (i = 0; !r && i < modulusSz - clientPubKeySz; i++) - r = SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); - - /* H(A | B) */ - for (i = 0; !r && i < modulusSz - serverPubKeySz; i++) - r = SrpHashUpdate(&hash, &pad, 1); - if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); - - /* client proof = H( H(N) ^ H(g) | H(user) | salt | A | B) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); - if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); - - /* server proof = H(A) */ - if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); - - /* set u */ - if (!r) r = SrpHashFinal(&hash, digest); - if (!r) r = mp_read_unsigned_bin(&srp->u, digest, SrpHashSize(srp->type)); - - return r; -} - static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) { SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; - word32 digestSz = SrpHashSize(srp->type); + word32 i, j, digestSz = SrpHashSize(srp->type); + byte counter[4]; int r; - word32 i = 0; - word32 pos = 0; - byte cnt[4]; - for (i = 0; pos < digestSz * 2; i++) { - cnt[0] = (i >> 24) & 0xFF; - cnt[1] = (i >> 16) & 0xFF; - cnt[2] = (i >> 8) & 0xFF; - cnt[3] = i & 0xFF; + for (i = j = 0; j < 2 * digestSz; i++) { + counter[0] = (i >> 24) & 0xFF; + counter[1] = (i >> 16) & 0xFF; + counter[2] = (i >> 8) & 0xFF; + counter[3] = i & 0xFF; r = SrpHashInit(&hash, srp->type); if (!r) r = SrpHashUpdate(&hash, secret, size); - if (!r) r = SrpHashUpdate(&hash, cnt, 4); + if (!r) r = SrpHashUpdate(&hash, counter, 4); - if(pos + digestSz > digestSz * 2) { + if(j + digestSz > 2 * digestSz) { if (!r) r = SrpHashFinal(&hash, digest); - XMEMCPY(srp->key + pos, digest, digestSz * 2 - pos); - pos = digestSz * 2; + XMEMCPY(srp->key + j, digest, 2 * digestSz - j); + j = 2 * digestSz; } else { - if (!r) r = SrpHashFinal(&hash, srp->key + pos); - pos += digestSz; + if (!r) r = SrpHashFinal(&hash, srp->key + j); + j += digestSz; } } @@ -503,12 +466,16 @@ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, byte* serverPubKey, word32 serverPubKeySz) { - byte* secret; - word32 digestSz; - word32 secretSz; - mp_int i, j, s; + SrpHash hash; + byte *secret; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 i, secretSz, digestSz; + mp_int u, s, temp1, temp2; + byte pad = 0; int r; + /* validating params */ + if (!srp || !clientPubKey || clientPubKeySz == 0 || !serverPubKey || serverPubKeySz == 0) return BAD_FUNC_ARG; @@ -516,56 +483,84 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, if (mp_iszero(&srp->priv)) return SRP_CALL_ORDER_E; - if ((r = mp_init_multi(&i, &j, &s, 0, 0, 0)) != MP_OKAY) + /* initializing variables */ + + if ((r = SrpHashInit(&hash, srp->type)) != 0) return r; + digestSz = SrpHashSize(srp->type); secretSz = mp_unsigned_bin_size(&srp->N); - secret = (byte*)XMALLOC(secretSz, NULL, DYNAMIC_TYPE_SRP); - if (secret == NULL) { - mp_clear(&i); mp_clear(&j); mp_clear(&s); + + if ((secret = (byte*)XMALLOC(secretSz, NULL, DYNAMIC_TYPE_SRP)) == NULL) return MEMORY_E; + + if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) { + XFREE(secret, NULL, DYNAMIC_TYPE_SRP); + return r; } - digestSz = SrpHashSize(srp->type); + /* building u (random scrambling parameeter) */ - r = wc_SrpSetU(srp, clientPubKey, clientPubKeySz, - serverPubKey, serverPubKeySz); + /* H(A) */ + for (i = 0; !r && i < secretSz - clientPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); + + /* H(A | B) */ + for (i = 0; !r && i < secretSz - serverPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); + + /* set u */ + if (!r) r = SrpHashFinal(&hash, digest); + if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type)); + + /* building s (secret) */ if (!r && srp->side == SRP_CLIENT_SIDE) { - /* i = B - k * v */ - r = mp_read_unsigned_bin(&i, srp->k, digestSz); - if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &j); - if (!r) r = mp_mulmod(&i, &j, &srp->N, &s); - if (!r) r = mp_read_unsigned_bin(&j, serverPubKey, serverPubKeySz); - if (!r) r = mp_sub(&j, &s, &i); + /* temp1 = B - k * v */ + r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); + if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); + if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); + if (!r) r = mp_sub(&temp2, &s, &temp1); - /* j = a + u * x */ - if (!r) r = mp_mulmod(&srp->u, &srp->auth, &srp->N, &s); - if (!r) r = mp_add(&srp->priv, &s, &j); + /* temp2 = a + u * x */ + if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s); + if (!r) r = mp_add(&srp->priv, &s, &temp2); - /* secret = i ^ j % N */ - if (!r) r = mp_exptmod(&i, &j, &srp->N, &s); + /* secret = temp1 ^ temp2 % N */ + if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s); } else if (!r && srp->side == SRP_SERVER_SIDE) { - /* i = v ^ u % N */ - r = mp_exptmod(&srp->auth, &srp->u, &srp->N, &i); + /* temp1 = v ^ u % N */ + r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); - /* j = A * i % N */ + /* temp2 = A * temp1 % N */ if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); - if (!r) r = mp_mulmod(&s, &i, &srp->N, &j); + if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); - /* secret = j * b % N */ - if (!r) r = mp_exptmod(&j, &srp->priv, &srp->N, &s); + /* secret = temp2 * b % N */ + if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); } + /* building session key from secret */ + if (!r) r = mp_to_unsigned_bin(&s, secret); if (!r) r = wc_SrpSetK(srp, secret, mp_unsigned_bin_size(&s)); - /* client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ - if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, digestSz * 2); + /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ + + if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, 2 * digestSz); + + /* updating server proof = H(A) */ + + if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); XFREE(secret, NULL, DYNAMIC_TYPE_SRP); - mp_clear(&i); mp_clear(&j); mp_clear(&s); + mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2); return r; } @@ -590,7 +585,7 @@ int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) if (srp->side == SRP_CLIENT_SIDE) { /* server proof = H( A | client proof | K) */ if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); - if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, (*size) * 2); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, 2 * (*size)); } return r; @@ -613,7 +608,7 @@ int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) if (srp->side == SRP_SERVER_SIDE) { /* server proof = H( A | client proof | K) */ if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); - if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, size * 2); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, 2 * size); } if (!r && XMEMCMP(proof, digest, size) != 0) @@ -622,4 +617,20 @@ int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) return r; } +int wc_SrpGetSessionKey(Srp* srp, byte* key, word32* size) +{ + word32 sz; + + if (!srp || !key || !size) + return BAD_FUNC_ARG; + + if (*size < (sz = SrpHashSize(srp->type))) + return BUFFER_E; + + XMEMCPY(key, srp->key, sz); + *size = sz; + + return 0; +} + #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 56cf41329..7dd4808e2 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -94,7 +94,6 @@ typedef struct { byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ mp_int auth; /**< client: x = H(salt, H(user, ":", pswd)) */ mp_int priv; /**< Private ephemeral value. */ - mp_int u; /**< Random scrambling parameeter. */ SrpHash client_proof; /**< Client proof. Sent to Server. */ SrpHash server_proof; /**< Server proof. Sent to Client. */ byte key[2 * SRP_MAX_DIGEST_SIZE]; /**< Session key. */ @@ -127,6 +126,8 @@ WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); +WOLFSSL_API int wc_SrpGetSessionKey(Srp* srp, byte* key, word32* size); + #ifdef __cplusplus } /* extern "C" */ #endif From f31c32bea24e011e9d01559d6dce494e11f0e2f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 3 Aug 2015 17:47:19 -0300 Subject: [PATCH 12/16] adds docs using doxygen style. --- wolfcrypt/src/srp.c | 12 +- wolfssl/wolfcrypt/srp.h | 252 ++++++++++++++++++++++++++++++++++------ 2 files changed, 221 insertions(+), 43 deletions(-) diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 96dda59a3..be3a39c3b 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -31,7 +31,7 @@ #include #include -static int SrpHashInit(SrpHash* hash, int type) +static int SrpHashInit(SrpHash* hash, SrpType type) { hash->type = type; @@ -117,7 +117,7 @@ static int SrpHashFinal(SrpHash* hash, byte* digest) } } -static word32 SrpHashSize(byte type) +static word32 SrpHashSize(SrpType type) { switch (type) { #ifndef NO_SHA @@ -145,7 +145,7 @@ static word32 SrpHashSize(byte type) } } -int wc_SrpInit(Srp* srp, byte type, byte side) +int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) { int r; @@ -257,7 +257,7 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); if (!r) r = SrpHashFinal(&hash, srp->k); - /* Update client proof */ + /* update client proof */ /* digest1 = H(N) */ if (!r) r = SrpHashInit(&hash, srp->type); @@ -278,7 +278,7 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); if (!r) r = SrpHashFinal(&hash, digest2); - /* Client proof = H( H(N) ^ H(g) | H(user) | salt) */ + /* client proof = H( H(N) ^ H(g) | H(user) | salt) */ if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); @@ -365,6 +365,7 @@ int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) return mp_read_unsigned_bin(&srp->priv, private, size); } +/** Generates random data using wolfcrypt RNG. */ static int wc_SrpGenPrivate(Srp* srp, byte* private, word32 size) { RNG rng; @@ -428,6 +429,7 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) return r; } +/** Computes the session key using the interleaved hash. */ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) { SrpHash hash; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 7dd4808e2..639468cf7 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -34,36 +34,48 @@ extern "C" { #endif -enum { - SRP_CLIENT_SIDE = 0, - SRP_SERVER_SIDE = 1, -#ifndef NO_SHA - SRP_TYPE_SHA = 1, -#endif -#ifndef NO_SHA256 - SRP_TYPE_SHA256 = 2, -#endif -#ifdef WOLFSSL_SHA384 - SRP_TYPE_SHA384 = 3, -#endif -#ifdef WOLFSSL_SHA512 - SRP_TYPE_SHA512 = 4, -#endif - /* Select the largest available hash for the buffer size. */ #if defined(WOLFSSL_SHA512) - SRP_MAX_DIGEST_SIZE = SHA512_DIGEST_SIZE, + #define SRP_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE #elif defined(WOLFSSL_SHA384) - SRP_MAX_DIGEST_SIZE = SHA384_DIGEST_SIZE, + #define SRP_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE #elif !defined(NO_SHA256) - SRP_MAX_DIGEST_SIZE = SHA256_DIGEST_SIZE, + #define SRP_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE #elif !defined(NO_SHA) - SRP_MAX_DIGEST_SIZE = SHA_DIGEST_SIZE, + #define SRP_MAX_DIGEST_SIZE SHA_DIGEST_SIZE #else #error "You have to have some kind of SHA hash if you want to use SRP." #endif -}; +/** + * SRP side, client or server. + */ +typedef enum { + SRP_CLIENT_SIDE = 0, + SRP_SERVER_SIDE = 1, +} SrpSide; + +/** + * SRP hash type, SHA[1|256|384|512]. + */ +typedef enum { + #ifndef NO_SHA + SRP_TYPE_SHA = 1, + #endif + #ifndef NO_SHA256 + SRP_TYPE_SHA256 = 2, + #endif + #ifdef WOLFSSL_SHA384 + SRP_TYPE_SHA384 = 3, + #endif + #ifdef WOLFSSL_SHA512 + SRP_TYPE_SHA512 = 4, + #endif +} SrpType; + +/** + * SRP hash struct. + */ typedef struct { byte type; union { @@ -83,49 +95,213 @@ typedef struct { } SrpHash; typedef struct { - byte side; /**< SRP_CLIENT_SIDE or SRP_SERVER_SIDE */ - byte type; /**< Hash type, one of SRP_TYPE_SHA[|256|384|512] */ - byte* user; /**< Username, login. */ - word32 userSz; /**< Username length. */ - byte* salt; /**< Small salt. */ - word32 saltSz; /**< Salt length. */ - mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes. */ - mp_int g; /**< Generator. A generator modulo N. */ - byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ - mp_int auth; /**< client: x = H(salt, H(user, ":", pswd)) */ - mp_int priv; /**< Private ephemeral value. */ - SrpHash client_proof; /**< Client proof. Sent to Server. */ - SrpHash server_proof; /**< Server proof. Sent to Client. */ - byte key[2 * SRP_MAX_DIGEST_SIZE]; /**< Session key. */ + SrpSide side; /**< Client or Server, @see SrpSide.*/ + SrpType type; /**< Hash type, @see SrpType. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ + mp_int N; /**< N = 2q+1, [q, N] are primes. */ + /**< a.k.a. modulus. */ + mp_int g; /**< Generator modulo N. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ + mp_int auth; /**< x = H(salt + H(user:pswd)) */ + /**< v = g ^ x % N */ + mp_int priv; /**< Private ephemeral value. */ + SrpHash client_proof; /**< Client proof. Sent to Server. */ + SrpHash server_proof; /**< Server proof. Sent to Client. */ + byte key[2 * SRP_MAX_DIGEST_SIZE]; /**< Session key. */ } Srp; -WOLFSSL_API int wc_SrpInit(Srp* srp, byte type, byte side); +/** + * Initializes the Srp struct for usage. + * + * @param[out] srp the Srp structure to be initialized. + * @param[in] type the hash type to be used. + * @param[in] side the side of the communication. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpInit(Srp* srp, SrpType type, SrpSide side); +/** + * Releases the Srp struct resources after usage. + * + * @param[in,out] srp the Srp structure to be terminated. + */ WOLFSSL_API void wc_SrpTerm(Srp* srp); +/** + * Sets the username. + * + * This function MUST be called after wc_SrpInit. + * + * @param[in,out] srp the Srp structure. + * @param[in] username the buffer containing the username. + * @param[in] size the username size in bytes + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size); + +/** + * Sets the srp parameeters based on the username. + * + * This function MUST be called after wc_SrpSetUsername. + * + * @param[in,out] srp the Srp structure. + * @param[in] N the Modulus. N = 2q+1, [q, N] are primes. + * @param[in] nSz the N size in bytes. + * @param[in] g the Generator modulo N. + * @param[in] gSz the g size in bytes + * @param[in] salt a small random salt. Specific for each username. + * @param[in] saltSz the salt size in bytes + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, const byte* g, word32 gSz, const byte* salt, word32 saltSz); +/** + * Sets the password. + * + * Setting the password does not persists the clear password data in the + * srp structure. The client calculates x = H(salt + H(user:pswd)) and stores + * it in the auth field. + * + * This function MUST be called after wc_SrpSetParams and is CLIENT SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[in] password the buffer containing the password. + * @param[in] size the password size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); +/** + * Sets the password. + * + * This function MUST be called after wc_SrpSetParams and is SERVER SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[in] verifier the buffer containing the verifier. + * @param[in] size the verifier size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); +/** + * Gets the verifier. + * + * The client calculates the verifier with v = g ^ x % N. + * This function MAY be called after wc_SrpSetPassword and is SERVER SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[out] verifier the buffer to write the verifier. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * verifier size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); +/** + * Sets the private ephemeral value. + * + * The private ephemeral value is known as: + * a at the client side. a = random() + * b at the server side. b = random() + * This function is handy for unit test cases or if the developer wants to use + * an external random source to set the ephemeral value. + * This function MAY be called before wc_SrpGetPublic. + * + * @param[in,out] srp the Srp structure. + * @param[in] private the ephemeral value. + * @param[in] size the private size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size); +/** + * Gets the public ephemeral value. + * + * The public ephemeral value is known as: + * A at the client side. A = g ^ a % N + * B at the server side. B = (k * v + (g ˆ b % N)) % N + * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier. + * + * @param[in,out] srp the Srp structure. + * @param[out] public the buffer to write the public ephemeral value. + * @param[in,out] size the the buffer size in bytes. Will be updated with + * the ephemeral value size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* public, word32* size); -WOLFSSL_API int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, - byte* serverPubKey, word32 serverPubKeySz); +/** + * Computes the session key. + * + * This function is handy for unit test cases or if the developer wants to use + * an external random source to set the ephemeral value. + * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier. + * + * @param[in,out] srp the Srp structure. + * @param[out] public the buffer to write the public ephemeral value. + * @param[in,out] size the the buffer size in bytes. Will be updated with + the ephemeral value size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, + byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz); + +/** + * Gets the proof. + * + * This function MUST be called after wc_SrpComputeKey. + * + * @param[in,out] srp the Srp structure. + * @param[out] proof the buffer to write the proof. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * proof size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); +/** + * Verifies the peers proof. + * + * This function MUST be called before wc_SrpGetSessionKey. + * + * @param[in,out] srp the Srp structure. + * @param[in] proof the peers proof. + * @param[in] size the proof size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); +/** + * Gets the session key. + * + * This function MUST be called after wc_SrpVerifyPeersProof. + * + * @param[in,out] srp the Srp structure. + * @param[out] key the buffer to write the key. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * key size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ WOLFSSL_API int wc_SrpGetSessionKey(Srp* srp, byte* key, word32* size); #ifdef __cplusplus From 12b84451531fcda54ae8eca9c8927609f4902df0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 4 Aug 2015 13:36:58 -0300 Subject: [PATCH 13/16] adds key generation function callback option. --- tests/srp.c | 254 ++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/srp.c | 82 +++++++++---- wolfssl/wolfcrypt/srp.h | 55 ++++----- 3 files changed, 335 insertions(+), 56 deletions(-) diff --git a/tests/srp.c b/tests/srp.c index 0e3af9c4a..691bbdabe 100644 --- a/tests/srp.c +++ b/tests/srp.c @@ -26,6 +26,7 @@ #include #include +#include #include #ifdef WOLFCRYPT_HAVE_SRP @@ -426,6 +427,258 @@ static void test_SrpGetProofAndVerify(void) wc_SrpTerm(&srv); } +static int sha512_key_gen(Srp* srp, byte* secret, word32 size) +{ + Sha512 hash; + int r; + + srp->key = (byte*)XMALLOC(SHA512_DIGEST_SIZE, NULL, DYNAMIC_TYPE_SRP); + if (srp->key == NULL) + return MEMORY_E; + + srp->keySz = SHA512_DIGEST_SIZE; + + r = wc_InitSha512(&hash); + if (!r) r = wc_Sha512Update(&hash, secret, size); + if (!r) r = wc_Sha512Final(&hash, srp->key); + + XMEMSET(&hash, 0, sizeof(Sha512)); + + return r; +} + +static void test_SrpKeyGenFunc_cb(void) +{ + Srp cli, srv; + byte clientPubKey[1024]; + byte serverPubKey[1024]; + word32 clientPubKeySz = 1024; + word32 serverPubKeySz = 1024; + byte clientProof[SRP_MAX_DIGEST_SIZE]; + byte serverProof[SRP_MAX_DIGEST_SIZE]; + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + byte username_[] = "alice"; + word32 usernameSz_ = 5; + + byte password_[] = "password123"; + word32 passwordSz_ = 11; + + byte N_[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, + 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, + 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, + 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, + 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, + 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, + 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, + 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, + 0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2, + 0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C, + 0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D, + 0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57, + 0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0, + 0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73, + 0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0, + 0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20, + 0xA9, 0x3A, 0xD2, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + + byte g_[] = { + 0x05 + }; + + byte salt_[] = { + 0xBE, 0xB2, 0x53, 0x79, 0xD1, 0xA8, 0x58, 0x1E, 0xB5, 0xA7, 0x27, 0x67, + 0x3A, 0x24, 0x41, 0xEE + }; + + byte verifier_[] = { + 0x9B, 0x5E, 0x06, 0x17, 0x01, 0xEA, 0x7A, 0xEB, 0x39, 0xCF, 0x6E, 0x35, + 0x19, 0x65, 0x5A, 0x85, 0x3C, 0xF9, 0x4C, 0x75, 0xCA, 0xF2, 0x55, 0x5E, + 0xF1, 0xFA, 0xF7, 0x59, 0xBB, 0x79, 0xCB, 0x47, 0x70, 0x14, 0xE0, 0x4A, + 0x88, 0xD6, 0x8F, 0xFC, 0x05, 0x32, 0x38, 0x91, 0xD4, 0xC2, 0x05, 0xB8, + 0xDE, 0x81, 0xC2, 0xF2, 0x03, 0xD8, 0xFA, 0xD1, 0xB2, 0x4D, 0x2C, 0x10, + 0x97, 0x37, 0xF1, 0xBE, 0xBB, 0xD7, 0x1F, 0x91, 0x24, 0x47, 0xC4, 0xA0, + 0x3C, 0x26, 0xB9, 0xFA, 0xD8, 0xED, 0xB3, 0xE7, 0x80, 0x77, 0x8E, 0x30, + 0x25, 0x29, 0xED, 0x1E, 0xE1, 0x38, 0xCC, 0xFC, 0x36, 0xD4, 0xBA, 0x31, + 0x3C, 0xC4, 0x8B, 0x14, 0xEA, 0x8C, 0x22, 0xA0, 0x18, 0x6B, 0x22, 0x2E, + 0x65, 0x5F, 0x2D, 0xF5, 0x60, 0x3F, 0xD7, 0x5D, 0xF7, 0x6B, 0x3B, 0x08, + 0xFF, 0x89, 0x50, 0x06, 0x9A, 0xDD, 0x03, 0xA7, 0x54, 0xEE, 0x4A, 0xE8, + 0x85, 0x87, 0xCC, 0xE1, 0xBF, 0xDE, 0x36, 0x79, 0x4D, 0xBA, 0xE4, 0x59, + 0x2B, 0x7B, 0x90, 0x4F, 0x44, 0x2B, 0x04, 0x1C, 0xB1, 0x7A, 0xEB, 0xAD, + 0x1E, 0x3A, 0xEB, 0xE3, 0xCB, 0xE9, 0x9D, 0xE6, 0x5F, 0x4B, 0xB1, 0xFA, + 0x00, 0xB0, 0xE7, 0xAF, 0x06, 0x86, 0x3D, 0xB5, 0x3B, 0x02, 0x25, 0x4E, + 0xC6, 0x6E, 0x78, 0x1E, 0x3B, 0x62, 0xA8, 0x21, 0x2C, 0x86, 0xBE, 0xB0, + 0xD5, 0x0B, 0x5B, 0xA6, 0xD0, 0xB4, 0x78, 0xD8, 0xC4, 0xE9, 0xBB, 0xCE, + 0xC2, 0x17, 0x65, 0x32, 0x6F, 0xBD, 0x14, 0x05, 0x8D, 0x2B, 0xBD, 0xE2, + 0xC3, 0x30, 0x45, 0xF0, 0x38, 0x73, 0xE5, 0x39, 0x48, 0xD7, 0x8B, 0x79, + 0x4F, 0x07, 0x90, 0xE4, 0x8C, 0x36, 0xAE, 0xD6, 0xE8, 0x80, 0xF5, 0x57, + 0x42, 0x7B, 0x2F, 0xC0, 0x6D, 0xB5, 0xE1, 0xE2, 0xE1, 0xD7, 0xE6, 0x61, + 0xAC, 0x48, 0x2D, 0x18, 0xE5, 0x28, 0xD7, 0x29, 0x5E, 0xF7, 0x43, 0x72, + 0x95, 0xFF, 0x1A, 0x72, 0xD4, 0x02, 0x77, 0x17, 0x13, 0xF1, 0x68, 0x76, + 0xDD, 0x05, 0x0A, 0xE5, 0xB7, 0xAD, 0x53, 0xCC, 0xB9, 0x08, 0x55, 0xC9, + 0x39, 0x56, 0x64, 0x83, 0x58, 0xAD, 0xFD, 0x96, 0x64, 0x22, 0xF5, 0x24, + 0x98, 0x73, 0x2D, 0x68, 0xD1, 0xD7, 0xFB, 0xEF, 0x10, 0xD7, 0x80, 0x34, + 0xAB, 0x8D, 0xCB, 0x6F, 0x0F, 0xCF, 0x88, 0x5C, 0xC2, 0xB2, 0xEA, 0x2C, + 0x3E, 0x6A, 0xC8, 0x66, 0x09, 0xEA, 0x05, 0x8A, 0x9D, 0xA8, 0xCC, 0x63, + 0x53, 0x1D, 0xC9, 0x15, 0x41, 0x4D, 0xF5, 0x68, 0xB0, 0x94, 0x82, 0xDD, + 0xAC, 0x19, 0x54, 0xDE, 0xC7, 0xEB, 0x71, 0x4F, 0x6F, 0xF7, 0xD4, 0x4C, + 0xD5, 0xB8, 0x6F, 0x6B, 0xD1, 0x15, 0x81, 0x09, 0x30, 0x63, 0x7C, 0x01, + 0xD0, 0xF6, 0x01, 0x3B, 0xC9, 0x74, 0x0F, 0xA2, 0xC6, 0x33, 0xBA, 0x89 + }; + + byte a_[] = { + 0x60, 0x97, 0x55, 0x27, 0x03, 0x5C, 0xF2, 0xAD, 0x19, 0x89, 0x80, 0x6F, + 0x04, 0x07, 0x21, 0x0B, 0xC8, 0x1E, 0xDC, 0x04, 0xE2, 0x76, 0x2A, 0x56, + 0xAF, 0xD5, 0x29, 0xDD, 0xDA, 0x2D, 0x43, 0x93 + }; + + byte A_[] = { + 0xFA, 0xB6, 0xF5, 0xD2, 0x61, 0x5D, 0x1E, 0x32, 0x35, 0x12, 0xE7, 0x99, + 0x1C, 0xC3, 0x74, 0x43, 0xF4, 0x87, 0xDA, 0x60, 0x4C, 0xA8, 0xC9, 0x23, + 0x0F, 0xCB, 0x04, 0xE5, 0x41, 0xDC, 0xE6, 0x28, 0x0B, 0x27, 0xCA, 0x46, + 0x80, 0xB0, 0x37, 0x4F, 0x17, 0x9D, 0xC3, 0xBD, 0xC7, 0x55, 0x3F, 0xE6, + 0x24, 0x59, 0x79, 0x8C, 0x70, 0x1A, 0xD8, 0x64, 0xA9, 0x13, 0x90, 0xA2, + 0x8C, 0x93, 0xB6, 0x44, 0xAD, 0xBF, 0x9C, 0x00, 0x74, 0x5B, 0x94, 0x2B, + 0x79, 0xF9, 0x01, 0x2A, 0x21, 0xB9, 0xB7, 0x87, 0x82, 0x31, 0x9D, 0x83, + 0xA1, 0xF8, 0x36, 0x28, 0x66, 0xFB, 0xD6, 0xF4, 0x6B, 0xFC, 0x0D, 0xDB, + 0x2E, 0x1A, 0xB6, 0xE4, 0xB4, 0x5A, 0x99, 0x06, 0xB8, 0x2E, 0x37, 0xF0, + 0x5D, 0x6F, 0x97, 0xF6, 0xA3, 0xEB, 0x6E, 0x18, 0x20, 0x79, 0x75, 0x9C, + 0x4F, 0x68, 0x47, 0x83, 0x7B, 0x62, 0x32, 0x1A, 0xC1, 0xB4, 0xFA, 0x68, + 0x64, 0x1F, 0xCB, 0x4B, 0xB9, 0x8D, 0xD6, 0x97, 0xA0, 0xC7, 0x36, 0x41, + 0x38, 0x5F, 0x4B, 0xAB, 0x25, 0xB7, 0x93, 0x58, 0x4C, 0xC3, 0x9F, 0xC8, + 0xD4, 0x8D, 0x4B, 0xD8, 0x67, 0xA9, 0xA3, 0xC1, 0x0F, 0x8E, 0xA1, 0x21, + 0x70, 0x26, 0x8E, 0x34, 0xFE, 0x3B, 0xBE, 0x6F, 0xF8, 0x99, 0x98, 0xD6, + 0x0D, 0xA2, 0xF3, 0xE4, 0x28, 0x3C, 0xBE, 0xC1, 0x39, 0x3D, 0x52, 0xAF, + 0x72, 0x4A, 0x57, 0x23, 0x0C, 0x60, 0x4E, 0x9F, 0xBC, 0xE5, 0x83, 0xD7, + 0x61, 0x3E, 0x6B, 0xFF, 0xD6, 0x75, 0x96, 0xAD, 0x12, 0x1A, 0x87, 0x07, + 0xEE, 0xC4, 0x69, 0x44, 0x95, 0x70, 0x33, 0x68, 0x6A, 0x15, 0x5F, 0x64, + 0x4D, 0x5C, 0x58, 0x63, 0xB4, 0x8F, 0x61, 0xBD, 0xBF, 0x19, 0xA5, 0x3E, + 0xAB, 0x6D, 0xAD, 0x0A, 0x18, 0x6B, 0x8C, 0x15, 0x2E, 0x5F, 0x5D, 0x8C, + 0xAD, 0x4B, 0x0E, 0xF8, 0xAA, 0x4E, 0xA5, 0x00, 0x88, 0x34, 0xC3, 0xCD, + 0x34, 0x2E, 0x5E, 0x0F, 0x16, 0x7A, 0xD0, 0x45, 0x92, 0xCD, 0x8B, 0xD2, + 0x79, 0x63, 0x93, 0x98, 0xEF, 0x9E, 0x11, 0x4D, 0xFA, 0xAA, 0xB9, 0x19, + 0xE1, 0x4E, 0x85, 0x09, 0x89, 0x22, 0x4D, 0xDD, 0x98, 0x57, 0x6D, 0x79, + 0x38, 0x5D, 0x22, 0x10, 0x90, 0x2E, 0x9F, 0x9B, 0x1F, 0x2D, 0x86, 0xCF, + 0xA4, 0x7E, 0xE2, 0x44, 0x63, 0x54, 0x65, 0xF7, 0x10, 0x58, 0x42, 0x1A, + 0x01, 0x84, 0xBE, 0x51, 0xDD, 0x10, 0xCC, 0x9D, 0x07, 0x9E, 0x6F, 0x16, + 0x04, 0xE7, 0xAA, 0x9B, 0x7C, 0xF7, 0x88, 0x3C, 0x7D, 0x4C, 0xE1, 0x2B, + 0x06, 0xEB, 0xE1, 0x60, 0x81, 0xE2, 0x3F, 0x27, 0xA2, 0x31, 0xD1, 0x84, + 0x32, 0xD7, 0xD1, 0xBB, 0x55, 0xC2, 0x8A, 0xE2, 0x1F, 0xFC, 0xF0, 0x05, + 0xF5, 0x75, 0x28, 0xD1, 0x5A, 0x88, 0x88, 0x1B, 0xB3, 0xBB, 0xB7, 0xFE + }; + + byte b_[] = { + 0xE4, 0x87, 0xCB, 0x59, 0xD3, 0x1A, 0xC5, 0x50, 0x47, 0x1E, 0x81, 0xF0, + 0x0F, 0x69, 0x28, 0xE0, 0x1D, 0xDA, 0x08, 0xE9, 0x74, 0xA0, 0x04, 0xF4, + 0x9E, 0x61, 0xF5, 0xD1, 0x05, 0x28, 0x4D, 0x20 + }; + + byte B_[] = { + 0x40, 0xF5, 0x70, 0x88, 0xA4, 0x82, 0xD4, 0xC7, 0x73, 0x33, 0x84, 0xFE, + 0x0D, 0x30, 0x1F, 0xDD, 0xCA, 0x90, 0x80, 0xAD, 0x7D, 0x4F, 0x6F, 0xDF, + 0x09, 0xA0, 0x10, 0x06, 0xC3, 0xCB, 0x6D, 0x56, 0x2E, 0x41, 0x63, 0x9A, + 0xE8, 0xFA, 0x21, 0xDE, 0x3B, 0x5D, 0xBA, 0x75, 0x85, 0xB2, 0x75, 0x58, + 0x9B, 0xDB, 0x27, 0x98, 0x63, 0xC5, 0x62, 0x80, 0x7B, 0x2B, 0x99, 0x08, + 0x3C, 0xD1, 0x42, 0x9C, 0xDB, 0xE8, 0x9E, 0x25, 0xBF, 0xBD, 0x7E, 0x3C, + 0xAD, 0x31, 0x73, 0xB2, 0xE3, 0xC5, 0xA0, 0xB1, 0x74, 0xDA, 0x6D, 0x53, + 0x91, 0xE6, 0xA0, 0x6E, 0x46, 0x5F, 0x03, 0x7A, 0x40, 0x06, 0x25, 0x48, + 0x39, 0xA5, 0x6B, 0xF7, 0x6D, 0xA8, 0x4B, 0x1C, 0x94, 0xE0, 0xAE, 0x20, + 0x85, 0x76, 0x15, 0x6F, 0xE5, 0xC1, 0x40, 0xA4, 0xBA, 0x4F, 0xFC, 0x9E, + 0x38, 0xC3, 0xB0, 0x7B, 0x88, 0x84, 0x5F, 0xC6, 0xF7, 0xDD, 0xDA, 0x93, + 0x38, 0x1F, 0xE0, 0xCA, 0x60, 0x84, 0xC4, 0xCD, 0x2D, 0x33, 0x6E, 0x54, + 0x51, 0xC4, 0x64, 0xCC, 0xB6, 0xEC, 0x65, 0xE7, 0xD1, 0x6E, 0x54, 0x8A, + 0x27, 0x3E, 0x82, 0x62, 0x84, 0xAF, 0x25, 0x59, 0xB6, 0x26, 0x42, 0x74, + 0x21, 0x59, 0x60, 0xFF, 0xF4, 0x7B, 0xDD, 0x63, 0xD3, 0xAF, 0xF0, 0x64, + 0xD6, 0x13, 0x7A, 0xF7, 0x69, 0x66, 0x1C, 0x9D, 0x4F, 0xEE, 0x47, 0x38, + 0x26, 0x03, 0xC8, 0x8E, 0xAA, 0x09, 0x80, 0x58, 0x1D, 0x07, 0x75, 0x84, + 0x61, 0xB7, 0x77, 0xE4, 0x35, 0x6D, 0xDA, 0x58, 0x35, 0x19, 0x8B, 0x51, + 0xFE, 0xEA, 0x30, 0x8D, 0x70, 0xF7, 0x54, 0x50, 0xB7, 0x16, 0x75, 0xC0, + 0x8C, 0x7D, 0x83, 0x02, 0xFD, 0x75, 0x39, 0xDD, 0x1F, 0xF2, 0xA1, 0x1C, + 0xB4, 0x25, 0x8A, 0xA7, 0x0D, 0x23, 0x44, 0x36, 0xAA, 0x42, 0xB6, 0xA0, + 0x61, 0x5F, 0x3F, 0x91, 0x5D, 0x55, 0xCC, 0x3B, 0x96, 0x6B, 0x27, 0x16, + 0xB3, 0x6E, 0x4D, 0x1A, 0x06, 0xCE, 0x5E, 0x5D, 0x2E, 0xA3, 0xBE, 0xE5, + 0xA1, 0x27, 0x0E, 0x87, 0x51, 0xDA, 0x45, 0xB6, 0x0B, 0x99, 0x7B, 0x0F, + 0xFD, 0xB0, 0xF9, 0x96, 0x2F, 0xEE, 0x4F, 0x03, 0xBE, 0xE7, 0x80, 0xBA, + 0x0A, 0x84, 0x5B, 0x1D, 0x92, 0x71, 0x42, 0x17, 0x83, 0xAE, 0x66, 0x01, + 0xA6, 0x1E, 0xA2, 0xE3, 0x42, 0xE4, 0xF2, 0xE8, 0xBC, 0x93, 0x5A, 0x40, + 0x9E, 0xAD, 0x19, 0xF2, 0x21, 0xBD, 0x1B, 0x74, 0xE2, 0x96, 0x4D, 0xD1, + 0x9F, 0xC8, 0x45, 0xF6, 0x0E, 0xFC, 0x09, 0x33, 0x8B, 0x60, 0xB6, 0xB2, + 0x56, 0xD8, 0xCA, 0xC8, 0x89, 0xCC, 0xA3, 0x06, 0xCC, 0x37, 0x0A, 0x0B, + 0x18, 0xC8, 0xB8, 0x86, 0xE9, 0x5D, 0xA0, 0xAF, 0x52, 0x35, 0xFE, 0xF4, + 0x39, 0x30, 0x20, 0xD2, 0xB7, 0xF3, 0x05, 0x69, 0x04, 0x75, 0x90, 0x42 + }; + + byte key_[] = { + 0x5C, 0xBC, 0x21, 0x9D, 0xB0, 0x52, 0x13, 0x8E, 0xE1, 0x14, 0x8C, 0x71, + 0xCD, 0x44, 0x98, 0x96, 0x3D, 0x68, 0x25, 0x49, 0xCE, 0x91, 0xCA, 0x24, + 0xF0, 0x98, 0x46, 0x8F, 0x06, 0x01, 0x5B, 0xEB, 0x6A, 0xF2, 0x45, 0xC2, + 0x09, 0x3F, 0x98, 0xC3, 0x65, 0x1B, 0xCA, 0x83, 0xAB, 0x8C, 0xAB, 0x2B, + 0x58, 0x0B, 0xBF, 0x02, 0x18, 0x4F, 0xEF, 0xDF, 0x26, 0x14, 0x2F, 0x73, + 0xDF, 0x95, 0xAC, 0x50 + }; + + AssertIntEQ(0, wc_SrpInit(&cli, SRP_TYPE_SHA512, SRP_CLIENT_SIDE)); + AssertIntEQ(0, wc_SrpInit(&srv, SRP_TYPE_SHA512, SRP_SERVER_SIDE)); + + AssertIntEQ(0, wc_SrpSetUsername(&cli, username_, usernameSz_)); + AssertIntEQ(0, wc_SrpSetUsername(&srv, username_, usernameSz_)); + + AssertIntEQ(0, wc_SrpSetParams(&cli, N_, sizeof(N_), + g_, sizeof(g_), + salt_, sizeof(salt_))); + AssertIntEQ(0, wc_SrpSetParams(&srv, N_, sizeof(N_), + g_, sizeof(g_), + salt_, sizeof(salt_))); + + AssertIntEQ(0, wc_SrpSetPassword(&cli, password_, passwordSz_)); + AssertIntEQ(0, wc_SrpSetVerifier(&srv, verifier_, sizeof(verifier_))); + + AssertIntEQ(0, wc_SrpSetPrivate(&cli, a_, sizeof(a_))); + AssertIntEQ(0, wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz)); + AssertIntEQ(0, XMEMCMP(clientPubKey, A_, clientPubKeySz)); + + AssertIntEQ(0, wc_SrpSetPrivate(&srv, b_, sizeof(b_))); + AssertIntEQ(0, wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(serverPubKey, B_, serverPubKeySz)); + + cli.keyGenFunc_cb = sha512_key_gen; + AssertIntEQ(0, wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(cli.key, key_, sizeof(key_))); + + srv.keyGenFunc_cb = sha512_key_gen; + AssertIntEQ(0, wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz)); + AssertIntEQ(0, XMEMCMP(srv.key, key_, sizeof(key_))); + + AssertIntEQ(0, wc_SrpGetProof(&cli, clientProof, &clientProofSz)); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz)); + + AssertIntEQ(0, wc_SrpGetProof(&srv, serverProof, &serverProofSz)); + AssertIntEQ(0, wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz)); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); +} + #endif void SrpTest(void) @@ -438,5 +691,6 @@ void SrpTest(void) test_SrpGetPublic(); test_SrpComputeKey(); test_SrpGetProofAndVerify(); + test_SrpKeyGenFunc_cb(); #endif } diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index be3a39c3b..66e7e7fda 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -31,6 +31,42 @@ #include #include +/** Computes the session key using the Mask Generation Function 1. */ +static int wc_SrpSetK(Srp* srp, byte* secret, word32 size); + +#include +static inline void LogHex(byte* data, word32 length) +{ + #define LINE_LEN 16 + + word32 i; + + printf("\t"); + + if (!data) { + printf("NULL\n"); + return; + } + + for (i = 0; i < LINE_LEN; i++) { + if (i < length) + printf("%02x ", data[i]); + else + printf(" "); + } + + printf("| "); + + for (i = 0; i < LINE_LEN; i++) + if (i < length) + printf("%c", 31 < data[i] && data[i] < 127 ? data[i] : '.'); + + printf("\n"); + + if (length > LINE_LEN) + LogHex(data + LINE_LEN, length - LINE_LEN); +} + static int SrpHashInit(SrpHash* hash, SrpType type) { hash->type = type; @@ -178,6 +214,9 @@ int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) srp->side = side; srp->type = type; srp->salt = NULL; srp->saltSz = 0; srp->user = NULL; srp->userSz = 0; + srp->key = NULL; srp->keySz = 0; + + srp->keyGenFunc_cb = wc_SrpSetK; return 0; } @@ -192,6 +231,8 @@ void wc_SrpTerm(Srp* srp) XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); XMEMSET(srp->user, 0, srp->userSz); XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP); + XMEMSET(srp->key, 0, srp->keySz); + XFREE(srp->key, NULL, DYNAMIC_TYPE_SRP); XMEMSET(srp, 0, sizeof(Srp)); } @@ -429,7 +470,6 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) return r; } -/** Computes the session key using the interleaved hash. */ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) { SrpHash hash; @@ -438,7 +478,13 @@ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) byte counter[4]; int r; - for (i = j = 0; j < 2 * digestSz; i++) { + srp->key = (byte*)XMALLOC(2 * digestSz, NULL, DYNAMIC_TYPE_SRP); + if (srp->key == NULL) + return MEMORY_E; + + srp->keySz = 2 * digestSz; + + for (i = j = 0; j < srp->keySz; i++) { counter[0] = (i >> 24) & 0xFF; counter[1] = (i >> 16) & 0xFF; counter[2] = (i >> 8) & 0xFF; @@ -448,10 +494,10 @@ static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) if (!r) r = SrpHashUpdate(&hash, secret, size); if (!r) r = SrpHashUpdate(&hash, counter, 4); - if(j + digestSz > 2 * digestSz) { + if(j + digestSz > srp->keySz) { if (!r) r = SrpHashFinal(&hash, digest); - XMEMCPY(srp->key + j, digest, 2 * digestSz - j); - j = 2 * digestSz; + XMEMCPY(srp->key + j, digest, srp->keySz - j); + j = srp->keySz; } else { if (!r) r = SrpHashFinal(&hash, srp->key + j); @@ -549,13 +595,15 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* building session key from secret */ if (!r) r = mp_to_unsigned_bin(&s, secret); - if (!r) r = wc_SrpSetK(srp, secret, mp_unsigned_bin_size(&s)); + if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); + printf("key\n"); + LogHex(srp->key, srp->keySz); /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); - if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, 2 * digestSz); + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz); /* updating server proof = H(A) */ @@ -587,7 +635,7 @@ int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) if (srp->side == SRP_CLIENT_SIDE) { /* server proof = H( A | client proof | K) */ if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); - if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, 2 * (*size)); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); } return r; @@ -610,7 +658,7 @@ int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) if (srp->side == SRP_SERVER_SIDE) { /* server proof = H( A | client proof | K) */ if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); - if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, 2 * size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); } if (!r && XMEMCMP(proof, digest, size) != 0) @@ -619,20 +667,4 @@ int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) return r; } -int wc_SrpGetSessionKey(Srp* srp, byte* key, word32* size) -{ - word32 sz; - - if (!srp || !key || !size) - return BAD_FUNC_ARG; - - if (*size < (sz = SrpHashSize(srp->type))) - return BUFFER_E; - - XMEMCPY(key, srp->key, sz); - *size = sz; - - return 0; -} - #endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index 639468cf7..ba917d2ad 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -94,23 +94,30 @@ typedef struct { } data; } SrpHash; -typedef struct { - SrpSide side; /**< Client or Server, @see SrpSide.*/ - SrpType type; /**< Hash type, @see SrpType. */ - byte* user; /**< Username, login. */ - word32 userSz; /**< Username length. */ - byte* salt; /**< Small salt. */ - word32 saltSz; /**< Salt length. */ - mp_int N; /**< N = 2q+1, [q, N] are primes. */ - /**< a.k.a. modulus. */ - mp_int g; /**< Generator modulo N. */ - byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. H(N, g) */ - mp_int auth; /**< x = H(salt + H(user:pswd)) */ - /**< v = g ^ x % N */ - mp_int priv; /**< Private ephemeral value. */ - SrpHash client_proof; /**< Client proof. Sent to Server. */ - SrpHash server_proof; /**< Server proof. Sent to Client. */ - byte key[2 * SRP_MAX_DIGEST_SIZE]; /**< Session key. */ +typedef struct Srp { + SrpSide side; /**< Client or Server, @see SrpSide. */ + SrpType type; /**< Hash type, @see SrpType. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes.*/ + mp_int g; /**< Generator. A generator modulo N. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameeter. k = H(N, g) */ + mp_int auth; /**< Client: x = H(salt + H(user:pswd)) */ + /**< Server: v = g ^ x % N */ + mp_int priv; /**< Private ephemeral value. */ + SrpHash client_proof; /**< Client proof. Sent to the Server. */ + SrpHash server_proof; /**< Server proof. Sent to the Client. */ + byte* key; /**< Session key. */ + word32 keySz; /**< Session key length. */ + int (*keyGenFunc_cb) (struct Srp* srp, byte* secret, word32 size); + /**< Function responsible for generating the session key. */ + /**< It MUST use XMALLOC with type DYNAMIC_TYPE_SRP to allocate the */ + /**< key buffer for this structure and set keySz to the buffer size. */ + /**< The default function used by this implementation is a modified */ + /**< version of t_mgf1 that uses the proper hash function according */ + /**< to srp->type. */ } Srp; /** @@ -290,20 +297,6 @@ WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); */ WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); -/** - * Gets the session key. - * - * This function MUST be called after wc_SrpVerifyPeersProof. - * - * @param[in,out] srp the Srp structure. - * @param[out] key the buffer to write the key. - * @param[in,out] size the buffer size in bytes. Will be updated with the - * key size. - * - * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h - */ -WOLFSSL_API int wc_SrpGetSessionKey(Srp* srp, byte* key, word32* size); - #ifdef __cplusplus } /* extern "C" */ #endif From 690cb147465532a0d45df40b5b6bb28cbf5401bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 4 Aug 2015 14:48:17 -0300 Subject: [PATCH 14/16] makes sure random values are safe. --- wolfcrypt/src/error.c | 9 ++++ wolfcrypt/src/srp.c | 76 +++++++++++++++------------------ wolfssl/wolfcrypt/error-crypt.h | 1 + wolfssl/wolfcrypt/srp.h | 3 ++ 4 files changed, 48 insertions(+), 41 deletions(-) diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 7d1d5ebe7..37b78422a 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -328,6 +328,15 @@ const char* wc_GetErrorString(int error) case ECC_PRIV_KEY_E: return " ECC private key is not valid error"; + case SRP_CALL_ORDER_E: + return "SRP function called in the wrong order error"; + + case SRP_VERIFY_E: + return "SRP proof verification error"; + + case SRP_BAD_KEY_E: + return "SRP bad key values error"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 66e7e7fda..6e8b22d2f 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -32,40 +32,7 @@ #include /** Computes the session key using the Mask Generation Function 1. */ -static int wc_SrpSetK(Srp* srp, byte* secret, word32 size); - -#include -static inline void LogHex(byte* data, word32 length) -{ - #define LINE_LEN 16 - - word32 i; - - printf("\t"); - - if (!data) { - printf("NULL\n"); - return; - } - - for (i = 0; i < LINE_LEN; i++) { - if (i < length) - printf("%02x ", data[i]); - else - printf(" "); - } - - printf("| "); - - for (i = 0; i < LINE_LEN; i++) - if (i < length) - printf("%c", 31 < data[i] && data[i] < 127 ? data[i] : '.'); - - printf("\n"); - - if (length > LINE_LEN) - LogHex(data + LINE_LEN, length - LINE_LEN); -} +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size); static int SrpHashInit(SrpHash* hash, SrpType type) { @@ -216,7 +183,7 @@ int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) srp->user = NULL; srp->userSz = 0; srp->key = NULL; srp->keySz = 0; - srp->keyGenFunc_cb = wc_SrpSetK; + srp->keyGenFunc_cb = wc_SrpSetKey; return 0; } @@ -273,10 +240,16 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) return MP_READ_E; + if (mp_count_bits(&srp->N) < SRP_DEFAULT_MIN_BITS) + return BAD_FUNC_ARG; + /* Set g */ if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) return MP_READ_E; + if (mp_cmp(&srp->N, &srp->g) != MP_GT) + return BAD_FUNC_ARG; + /* Set salt */ if (srp->salt) { XMEMSET(srp->salt, 0, srp->saltSz); @@ -397,13 +370,23 @@ int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) { + mp_int p; + int r; + if (!srp || !private || !size) return BAD_FUNC_ARG; if (mp_iszero(&srp->auth)) return SRP_CALL_ORDER_E; - return mp_read_unsigned_bin(&srp->priv, private, size); + r = mp_init(&p); + if (!r) r = mp_read_unsigned_bin(&p, private, size); + if (!r) r = mp_mod(&p, &srp->N, &srp->priv); + if (!r) r = mp_iszero(&srp->priv) ? SRP_BAD_KEY_E : 0; + + mp_clear(&p); + + return r; } /** Generates random data using wolfcrypt RNG. */ @@ -452,6 +435,7 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); + if (!r) r = mp_iszero(&i) ? SRP_BAD_KEY_E : 0; if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); if (!r) r = mp_add(&j, &pubkey, &i); @@ -470,7 +454,7 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) return r; } -static int wc_SrpSetK(Srp* srp, byte* secret, word32 size) +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) { SrpHash hash; byte digest[SRP_MAX_DIGEST_SIZE]; @@ -566,11 +550,15 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* building s (secret) */ if (!r && srp->side == SRP_CLIENT_SIDE) { - /* temp1 = B - k * v */ + + /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); + if (!r) r = mp_iszero(&temp1) ? SRP_BAD_KEY_E : 0; if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); + if (!r) r = mp_iszero(&temp2) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; if (!r) r = mp_sub(&temp2, &s, &temp1); /* temp2 = a + u * x */ @@ -584,10 +572,18 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* temp1 = v ^ u % N */ r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); - /* temp2 = A * temp1 % N */ + /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); + if (!r) r = mp_iszero(&s) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); + /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ + if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); + if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_sub(&srp->N, &temp1, &s); + if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; + /* secret = temp2 * b % N */ if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); } @@ -596,8 +592,6 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, if (!r) r = mp_to_unsigned_bin(&s, secret); if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); - printf("key\n"); - LogHex(srp->key, srp->keySz); /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 84714e462..340d1db75 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -153,6 +153,7 @@ enum { SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ SRP_VERIFY_E = -218, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */ MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/srp.h b/wolfssl/wolfcrypt/srp.h index ba917d2ad..3992a07ea 100644 --- a/wolfssl/wolfcrypt/srp.h +++ b/wolfssl/wolfcrypt/srp.h @@ -47,6 +47,9 @@ #error "You have to have some kind of SHA hash if you want to use SRP." #endif +/* Set the minimum number of bits acceptable in an SRP modulus */ +#define SRP_DEFAULT_MIN_BITS 512 + /** * SRP side, client or server. */ From 114e3edc279d99ef01f1e804d1f49acf9c5f517f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 4 Aug 2015 16:02:44 -0300 Subject: [PATCH 15/16] add srp example to test.c --- wolfcrypt/test/test.c | 104 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f85ee6373..b7888b0c2 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -179,6 +180,7 @@ int camellia_test(void); int rsa_test(void); int dh_test(void); int dsa_test(void); +int srp_test(void); int random_test(void); int pwdbased_test(void); int ripemd_test(void); @@ -500,6 +502,13 @@ int wolfcrypt_test(void* args) printf( "DSA test passed!\n"); #endif +#ifdef WOLFCRYPT_HAVE_SRP + if ( (ret = srp_test()) != 0) + return err_sys("SRP test failed!\n", ret); + else + printf( "SRP test passed!\n"); +#endif + #ifndef NO_PWDBASED if ( (ret = pwdbased_test()) != 0) return err_sys("PWDBASED test failed!\n", ret); @@ -4541,6 +4550,101 @@ int dsa_test(void) #endif /* NO_DSA */ +#ifdef WOLFCRYPT_HAVE_SRP + +int srp_test(void) +{ + Srp cli, srv; + int r; + + byte clientPubKey[80]; /* A */ + byte serverPubKey[80]; /* B */ + word32 clientPubKeySz = 80; + word32 serverPubKeySz = 80; + byte clientProof[SRP_MAX_DIGEST_SIZE]; /* M1 */ + byte serverProof[SRP_MAX_DIGEST_SIZE]; /* M2 */ + word32 clientProofSz = SRP_MAX_DIGEST_SIZE; + word32 serverProofSz = SRP_MAX_DIGEST_SIZE; + + byte username[] = "user"; + word32 usernameSz = 4; + + byte password[] = "password"; + word32 passwordSz = 8; + + byte N[] = { + 0xC9, 0x4D, 0x67, 0xEB, 0x5B, 0x1A, 0x23, 0x46, 0xE8, 0xAB, 0x42, 0x2F, + 0xC6, 0xA0, 0xED, 0xAE, 0xDA, 0x8C, 0x7F, 0x89, 0x4C, 0x9E, 0xEE, 0xC4, + 0x2F, 0x9E, 0xD2, 0x50, 0xFD, 0x7F, 0x00, 0x46, 0xE5, 0xAF, 0x2C, 0xF7, + 0x3D, 0x6B, 0x2F, 0xA2, 0x6B, 0xB0, 0x80, 0x33, 0xDA, 0x4D, 0xE3, 0x22, + 0xE1, 0x44, 0xE7, 0xA8, 0xE9, 0xB1, 0x2A, 0x0E, 0x46, 0x37, 0xF6, 0x37, + 0x1F, 0x34, 0xA2, 0x07, 0x1C, 0x4B, 0x38, 0x36, 0xCB, 0xEE, 0xAB, 0x15, + 0x03, 0x44, 0x60, 0xFA, 0xA7, 0xAD, 0xF4, 0x83 + }; + + byte g[] = { + 0x02 + }; + + byte salt[] = { + 0xB2, 0xE5, 0x8E, 0xCC, 0xD0, 0xCF, 0x9D, 0x10, 0x3A, 0x56 + }; + + byte verifier[] = { + 0x7C, 0xAB, 0x17, 0xFE, 0x54, 0x3E, 0x8C, 0x13, 0xF2, 0x3D, 0x21, 0xE7, + 0xD2, 0xAF, 0xAF, 0xDB, 0xA1, 0x52, 0x69, 0x9D, 0x49, 0x01, 0x79, 0x91, + 0xCF, 0xD1, 0x3F, 0xE5, 0x28, 0x72, 0xCA, 0xBE, 0x13, 0xD1, 0xC2, 0xDA, + 0x65, 0x34, 0x55, 0x8F, 0x34, 0x0E, 0x05, 0xB8, 0xB4, 0x0F, 0x7F, 0x6B, + 0xBB, 0xB0, 0x6B, 0x50, 0xD8, 0xB1, 0xCC, 0xB7, 0x81, 0xFE, 0xD4, 0x42, + 0xF5, 0x11, 0xBC, 0x8A, 0x28, 0xEB, 0x50, 0xB3, 0x46, 0x08, 0xBA, 0x24, + 0xA2, 0xFB, 0x7F, 0x2E, 0x0A, 0xA5, 0x33, 0xCC + }; + + /* client knows username and password. */ + /* server knows N, g, salt and verifier. */ + + r = wc_SrpInit(&cli, SRP_TYPE_SHA, SRP_CLIENT_SIDE); + if (!r) r = wc_SrpSetUsername(&cli, username, usernameSz); + + /* client sends username to server */ + + if (!r) r = wc_SrpInit(&srv, SRP_TYPE_SHA, SRP_SERVER_SIDE); + if (!r) r = wc_SrpSetUsername(&srv, username, usernameSz); + if (!r) r = wc_SrpSetParams(&srv, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt)); + if (!r) r = wc_SrpSetVerifier(&srv, verifier, sizeof(verifier)); + if (!r) r = wc_SrpGetPublic(&srv, serverPubKey, &serverPubKeySz); + + /* server sends N, g, salt and B to client */ + + if (!r) r = wc_SrpSetParams(&cli, N, sizeof(N), + g, sizeof(g), + salt, sizeof(salt)); + if (!r) r = wc_SrpSetPassword(&cli, password, passwordSz); + if (!r) r = wc_SrpGetPublic(&cli, clientPubKey, &clientPubKeySz); + if (!r) r = wc_SrpComputeKey(&cli, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz); + if (!r) r = wc_SrpGetProof(&cli, clientProof, &clientProofSz); + + /* client sends A and M1 to server */ + + if (!r) r = wc_SrpComputeKey(&srv, clientPubKey, clientPubKeySz, + serverPubKey, serverPubKeySz); + if (!r) r = wc_SrpVerifyPeersProof(&srv, clientProof, clientProofSz); + if (!r) r = wc_SrpGetProof(&srv, serverProof, &serverProofSz); + + /* server sends M2 to client */ + + if (!r) r = wc_SrpVerifyPeersProof(&cli, serverProof, serverProofSz); + + wc_SrpTerm(&cli); + wc_SrpTerm(&srv); + + return r; +} + +#endif /* WOLFCRYPT_HAVE_SRP */ #ifdef OPENSSL_EXTRA From 0a037d39fff06f26a7dd4b624e4f0aa332dfa8ff Mon Sep 17 00:00:00 2001 From: toddouska Date: Fri, 7 Aug 2015 09:37:22 -0700 Subject: [PATCH 16/16] fix srp request; forcezero, check mp_init(), no leaks --- wolfcrypt/src/srp.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 6e8b22d2f..7d9560911 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -31,6 +31,12 @@ #include #include +#ifdef NO_INLINE + #include +#else + #include +#endif + /** Computes the session key using the Mask Generation Function 1. */ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size); @@ -194,14 +200,14 @@ void wc_SrpTerm(Srp* srp) mp_clear(&srp->N); mp_clear(&srp->g); mp_clear(&srp->auth); mp_clear(&srp->priv); - XMEMSET(srp->salt, 0, srp->saltSz); + ForceZero(srp->salt, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); - XMEMSET(srp->user, 0, srp->userSz); + ForceZero(srp->user, srp->userSz); XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP); - XMEMSET(srp->key, 0, srp->keySz); + ForceZero(srp->key, srp->keySz); XFREE(srp->key, NULL, DYNAMIC_TYPE_SRP); - XMEMSET(srp, 0, sizeof(Srp)); + ForceZero(srp, sizeof(Srp)); } } @@ -252,7 +258,7 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, /* Set salt */ if (srp->salt) { - XMEMSET(srp->salt, 0, srp->saltSz); + ForceZero(srp->salt, srp->saltSz); XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); } @@ -284,8 +290,10 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, if (!r) r = SrpHashFinal(&hash, digest2); /* digest1 = H(N) ^ H(g) */ - for (i = 0, j = SrpHashSize(srp->type); i < j; i++) - digest1[i] ^= digest2[i]; + if (r == 0) { + for (i = 0, j = SrpHashSize(srp->type); i < j; i++) + digest1[i] ^= digest2[i]; + } /* digest2 = H(user) */ if (!r) r = SrpHashInit(&hash, srp->type); @@ -331,7 +339,7 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) /* Set x (private key) */ if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); - XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); + ForceZero(digest, SRP_MAX_DIGEST_SIZE); return r; } @@ -348,6 +356,8 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) return SRP_CALL_ORDER_E; r = mp_init(&v); + if (r != MP_OKAY) + return MP_INIT_E; /* v = g ^ x % N */ if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); @@ -380,6 +390,8 @@ int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) return SRP_CALL_ORDER_E; r = mp_init(&p); + if (r != MP_OKAY) + return MP_INIT_E; if (!r) r = mp_read_unsigned_bin(&p, private, size); if (!r) r = mp_mod(&p, &srp->N, &srp->priv); if (!r) r = mp_iszero(&srp->priv) ? SRP_BAD_KEY_E : 0; @@ -406,10 +418,7 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) { mp_int pubkey; word32 modulusSz; - int r = mp_init(&pubkey); - - if (r != 0) - return r; + int r; if (!srp || !public || !size) return BAD_FUNC_ARG; @@ -421,6 +430,10 @@ int wc_SrpGetPublic(Srp* srp, byte* public, word32* size) if (*size < modulusSz) return BUFFER_E; + r = mp_init(&pubkey); + if (r != MP_OKAY) + return MP_INIT_E; + /* priv = random() */ if (mp_iszero(&srp->priv)) r = wc_SrpGenPrivate(srp, public, modulusSz); @@ -460,7 +473,7 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) byte digest[SRP_MAX_DIGEST_SIZE]; word32 i, j, digestSz = SrpHashSize(srp->type); byte counter[4]; - int r; + int r = BAD_FUNC_ARG; srp->key = (byte*)XMALLOC(2 * digestSz, NULL, DYNAMIC_TYPE_SRP); if (srp->key == NULL) @@ -489,8 +502,8 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) } } - XMEMSET(digest, 0, sizeof(digest)); - XMEMSET(&hash, 0, sizeof(SrpHash)); + ForceZero(digest, sizeof(digest)); + ForceZero(&hash, sizeof(SrpHash)); return r; }