summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES3
-rwxr-xr-xConfigure6
-rw-r--r--Makefile.org2
-rw-r--r--apps/Makefile6
-rw-r--r--apps/demoSRP/srp_verifier.txt6
-rw-r--r--apps/demoSRP/srp_verifier.txt.attr1
-rw-r--r--apps/progs.h4
-rw-r--r--apps/s_client.c180
-rw-r--r--apps/s_server.c81
-rw-r--r--apps/srp.c759
-rw-r--r--crypto/srp/.cvsignore1
-rw-r--r--crypto/srp/Makefile91
-rw-r--r--crypto/srp/srp.h172
-rw-r--r--crypto/srp/srp_grps.h517
-rw-r--r--crypto/srp/srp_lcl.h83
-rw-r--r--crypto/srp/srp_lib.c357
-rw-r--r--crypto/srp/srp_vfy.c657
-rw-r--r--crypto/srp/srptest.c162
-rw-r--r--crypto/stack/safestack.h60
-rw-r--r--ssl/Makefile4
-rw-r--r--ssl/s3_clnt.c138
-rw-r--r--ssl/s3_lib.c213
-rw-r--r--ssl/s3_pkt.c4
-rw-r--r--ssl/s3_srvr.c140
-rw-r--r--ssl/ssl.h96
-rw-r--r--ssl/ssl3.h2
-rw-r--r--ssl/ssl_asn1.c37
-rw-r--r--ssl/ssl_ciph.c8
-rw-r--r--ssl/ssl_err.c11
-rw-r--r--ssl/ssl_lib.c6
-rw-r--r--ssl/ssl_locl.h1
-rw-r--r--ssl/ssl_sess.c7
-rw-r--r--ssl/ssl_stat.c8
-rw-r--r--ssl/ssl_txt.c4
-rw-r--r--ssl/ssltest.c99
-rw-r--r--ssl/t1_enc.c3
-rw-r--r--ssl/t1_lib.c37
-rw-r--r--ssl/tls1.h26
-rw-r--r--ssl/tls_srp.c527
-rw-r--r--test/Makefile14
-rw-r--r--test/testssl10
-rwxr-xr-xutil/libeay.num16
-rwxr-xr-xutil/mk1mf.pl7
-rwxr-xr-xutil/mkdef.pl7
-rwxr-xr-xutil/mkfiles.pl1
-rwxr-xr-xutil/ssleay.num14
46 files changed, 4571 insertions, 17 deletions
diff --git a/CHANGES b/CHANGES
index 5d0cc3f4bc..42b4c89c36 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,9 @@
Changes between 1.0.0d and 1.0.1 [xx XXX xxxx]
+ *) Add SRP support.
+ [Tom Wu <tjw@cs.stanford.edu> and Ben Laurie]
+
*) Add functions to copy EVP_PKEY_METHOD and retrieve flags and id.
[Steve Henson]
diff --git a/Configure b/Configure
index 429ab2e5eb..9397ca1c4a 100755
--- a/Configure
+++ b/Configure
@@ -946,6 +946,12 @@ if (defined($disabled{"ec"}) || defined($disabled{"dsa"})
$disabled{"gost"} = "forced";
}
+# SRP requires TLSEXT
+if (defined($disabled{"tlsext"}))
+ {
+ $disabled{"srp"} = "forced";
+ }
+
if ($target eq "TABLE") {
foreach $target (sort keys %table) {
print_table_entry($target);
diff --git a/Makefile.org b/Makefile.org
index fb0af7ecc2..c8869d14df 100644
--- a/Makefile.org
+++ b/Makefile.org
@@ -121,7 +121,7 @@ SDIRS= \
bn ec rsa dsa ecdsa dh ecdh dso engine \
buffer bio stack lhash rand err \
evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 \
- cms pqueue ts jpake store
+ cms pqueue ts jpake srp store
# keep in mind that the above list is adjusted by ./Configure
# according to no-xxx arguments...
diff --git a/apps/Makefile b/apps/Makefile
index fa32d2d7e7..61c80da0fb 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -39,7 +39,7 @@ E_EXE= verify asn1pars req dgst dh dhparam enc passwd gendh errstr \
ca crl rsa rsautl dsa dsaparam ec ecparam \
x509 genrsa gendsa genpkey s_server s_client speed \
s_time version pkcs7 cms crl2pkcs7 sess_id ciphers nseq pkcs12 \
- pkcs8 pkey pkeyparam pkeyutl spkac smime rand engine ocsp prime ts
+ pkcs8 pkey pkeyparam pkeyutl spkac smime rand engine ocsp prime ts srp
PROGS= $(PROGRAM).c
@@ -56,7 +56,7 @@ E_OBJ= verify.o asn1pars.o req.o dgst.o dh.o dhparam.o enc.o passwd.o gendh.o er
x509.o genrsa.o gendsa.o genpkey.o s_server.o s_client.o speed.o \
s_time.o $(A_OBJ) $(S_OBJ) $(RAND_OBJ) version.o sess_id.o \
ciphers.o nseq.o pkcs12.o pkcs8.o pkey.o pkeyparam.o pkeyutl.o \
- spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o
+ spkac.o smime.o cms.o rand.o engine.o ocsp.o prime.o ts.o srp.o
E_SRC= verify.c asn1pars.c req.c dgst.c dh.c enc.c passwd.c gendh.c errstr.c ca.c \
pkcs7.c crl2p7.c crl.c \
@@ -64,7 +64,7 @@ E_SRC= verify.c asn1pars.c req.c dgst.c dh.c enc.c passwd.c gendh.c errstr.c ca.
x509.c genrsa.c gendsa.c genpkey.c s_server.c s_client.c speed.c \
s_time.c $(A_SRC) $(S_SRC) $(RAND_SRC) version.c sess_id.c \
ciphers.c nseq.c pkcs12.c pkcs8.c pkey.c pkeyparam.c pkeyutl.c \
- spkac.c smime.c cms.c rand.c engine.c ocsp.c prime.c ts.c
+ spkac.c smime.c cms.c rand.c engine.c ocsp.c prime.c ts.c srp.c
SRC=$(E_SRC)
diff --git a/apps/demoSRP/srp_verifier.txt b/apps/demoSRP/srp_verifier.txt
new file mode 100644
index 0000000000..ccae629247
--- /dev/null
+++ b/apps/demoSRP/srp_verifier.txt
@@ -0,0 +1,6 @@
+# This is a file that will be filled by the openssl srp routine.
+# You can initialize the file with additional groups, these are
+# records starting with a I followed by the g and N values and the id.
+# The exact values ... you have to dig this out from the source of srp.c
+# or srp_vfy.c
+# The last value of an I is used as the default group for new users.
diff --git a/apps/demoSRP/srp_verifier.txt.attr b/apps/demoSRP/srp_verifier.txt.attr
new file mode 100644
index 0000000000..8f7e63a347
--- /dev/null
+++ b/apps/demoSRP/srp_verifier.txt.attr
@@ -0,0 +1 @@
+unique_subject = yes
diff --git a/apps/progs.h b/apps/progs.h
index 79e479a337..e91b884a9c 100644
--- a/apps/progs.h
+++ b/apps/progs.h
@@ -44,6 +44,7 @@ extern int smime_main(int argc,char *argv[]);
extern int rand_main(int argc,char *argv[]);
extern int engine_main(int argc,char *argv[]);
extern int ocsp_main(int argc,char *argv[]);
+extern int srp_main(int argc,char *argv[]);
extern int prime_main(int argc,char *argv[]);
extern int ts_main(int argc,char *argv[]);
@@ -145,6 +146,9 @@ FUNCTION functions[] = {
#ifndef OPENSSL_NO_OCSP
{FUNC_TYPE_GENERAL,"ocsp",ocsp_main},
#endif
+#ifndef OPENSSL_NO_SRP
+ {FUNC_TYPE_GENERAL,"srp",srp_main},
+#endif
{FUNC_TYPE_GENERAL,"prime",prime_main},
{FUNC_TYPE_GENERAL,"ts",ts_main},
#ifndef OPENSSL_NO_MD2
diff --git a/apps/s_client.c b/apps/s_client.c
index 484d009987..81c7e85fdb 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -163,6 +163,9 @@ typedef unsigned int u_int;
#include <openssl/rand.h>
#include <openssl/ocsp.h>
#include <openssl/bn.h>
+#ifndef OPENSSL_NO_SRP
+#include <openssl/srp.h>
+#endif
#include "s_apps.h"
#include "timeouts.h"
@@ -316,6 +319,13 @@ static void sc_usage(void)
BIO_printf(bio_err," -jpake arg - JPAKE secret to use\n");
# endif
#endif
+#ifndef OPENSSL_NO_SRP
+ BIO_printf(bio_err," -srpuser user - SRP authentification for 'user'\n");
+ BIO_printf(bio_err," -srppass arg - password for 'user'\n");
+ BIO_printf(bio_err," -srp_lateuser - SRP username into second ClientHello message\n");
+ BIO_printf(bio_err," -srp_moregroups - Tolerate other than the known g N values.\n");
+ BIO_printf(bio_err," -srp_strength int - minimal mength in bits for N (default %d).\n",SRP_MINIMAL_N);
+#endif
BIO_printf(bio_err," -ssl2 - just use SSLv2\n");
BIO_printf(bio_err," -ssl3 - just use SSLv3\n");
BIO_printf(bio_err," -tls1_1 - just use TLSv1.1\n");
@@ -367,6 +377,112 @@ static int MS_CALLBACK ssl_servername_cb(SSL *s, int *ad, void *arg)
return SSL_TLSEXT_ERR_OK;
}
+
+#ifndef OPENSSL_NO_SRP
+
+/* This is a context that we pass to all callbacks */
+typedef struct srp_arg_st
+ {
+ char *srppassin;
+ char *srplogin;
+ int msg; /* copy from c_msg */
+ int debug; /* copy from c_debug */
+ int amp; /* allow more groups */
+ int strength /* minimal size for N */ ;
+ } SRP_ARG;
+
+#define SRP_NUMBER_ITERATIONS_FOR_PRIME 64
+
+static int SRP_Verify_N_and_g(BIGNUM *N, BIGNUM *g)
+ {
+ BN_CTX *bn_ctx = BN_CTX_new();
+ BIGNUM *p = BN_new();
+ BIGNUM *r = BN_new();
+ int ret =
+ g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) &&
+ BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) &&
+ p != NULL && BN_rshift1(p, N) &&
+
+ /* p = (N-1)/2 */
+ BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) &&
+ r != NULL &&
+
+ /* verify g^((N-1)/2) == -1 (mod N) */
+ BN_mod_exp(r, g, p, N, bn_ctx) &&
+ BN_add_word(r, 1) &&
+ BN_cmp(r, N) == 0;
+
+ if(r)
+ BN_free(r);
+ if(p)
+ BN_free(p);
+ if(bn_ctx)
+ BN_CTX_free(bn_ctx);
+ return ret;
+ }
+
+static int MS_CALLBACK ssl_srp_verify_param_cb(SSL *s, void *arg)
+ {
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ BIGNUM *N = NULL, *g = NULL;
+ if (!(N = SSL_get_srp_N(s)) || !(g = SSL_get_srp_g(s)))
+ return 0;
+ if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1)
+ {
+ BIO_printf(bio_err, "SRP parameters:\n");
+ BIO_printf(bio_err,"\tN="); BN_print(bio_err,N);
+ BIO_printf(bio_err,"\n\tg="); BN_print(bio_err,g);
+ BIO_printf(bio_err,"\n");
+ }
+
+ if (SRP_check_known_gN_param(g,N))
+ return 1;
+
+ if (srp_arg->amp == 1)
+ {
+ if (srp_arg->debug)
+ BIO_printf(bio_err, "SRP param N and g are not known params, going to check deeper.\n");
+
+/* The srp_moregroups must be used with caution, testing primes costs time.
+ Implementors should rather add the value to the known ones.
+ The minimal size has already been tested.
+*/
+ if (BN_num_bits(g) <= BN_BITS && SRP_Verify_N_and_g(N,g))
+ return 1;
+ }
+ BIO_printf(bio_err, "SRP param N and g rejected.\n");
+ return 0;
+ }
+
+#define PWD_STRLEN 1024
+
+static char * MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
+ {
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ char *pass = (char *)OPENSSL_malloc(PWD_STRLEN+1);
+ PW_CB_DATA cb_tmp;
+ int l;
+
+ cb_tmp.password = (char *)srp_arg->srppassin;
+ cb_tmp.prompt_info = "SRP user";
+ if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp))<0)
+ {
+ BIO_printf (bio_err, "Can't read Password\n");
+ OPENSSL_free(pass);
+ return NULL;
+ }
+ *(pass+l)= '\0';
+
+ return pass;
+ }
+
+static char * MS_CALLBACK missing_srp_username_callback(SSL *s, void *arg)
+ {
+ SRP_ARG *srp_arg = (SRP_ARG *)arg;
+ return BUF_strdup(srp_arg->srplogin);
+ }
+
+#endif
#endif
enum
@@ -440,6 +556,11 @@ int MAIN(int argc, char **argv)
#ifndef OPENSSL_NO_JPAKE
char *jpake_secret = NULL;
#endif
+#ifndef OPENSSL_NO_SRP
+ char * srppass = NULL;
+ int srp_lateuser = 0;
+ SRP_ARG srp_arg = {NULL,NULL,0,0,0,1024};
+#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
meth=SSLv23_client_method();
@@ -589,6 +710,37 @@ int MAIN(int argc, char **argv)
}
}
#endif
+#ifndef OPENSSL_NO_SRP
+ else if (strcmp(*argv,"-srpuser") == 0)
+ {
+ if (--argc < 1) goto bad;
+ srp_arg.srplogin= *(++argv);
+ meth=TLSv1_client_method();
+ }
+ else if (strcmp(*argv,"-srppass") == 0)
+ {
+ if (--argc < 1) goto bad;
+ srppass= *(++argv);
+ meth=TLSv1_client_method();
+ }
+ else if (strcmp(*argv,"-srp_strength") == 0)
+ {
+ if (--argc < 1) goto bad;
+ srp_arg.strength=atoi(*(++argv));
+ BIO_printf(bio_err,"SRP minimal length for N is %d\n",srp_arg.strength);
+ meth=TLSv1_client_method();
+ }
+ else if (strcmp(*argv,"-srp_lateuser") == 0)
+ {
+ srp_lateuser= 1;
+ meth=TLSv1_client_method();
+ }
+ else if (strcmp(*argv,"-srp_moregroups") == 0)
+ {
+ srp_arg.amp=1;
+ meth=TLSv1_client_method();
+ }
+#endif
#ifndef OPENSSL_NO_SSL2
else if (strcmp(*argv,"-ssl2") == 0)
meth=SSLv2_client_method();
@@ -840,6 +992,14 @@ bad:
}
}
+#ifndef OPENSSL_NO_SRP
+ if(!app_passwd(bio_err, srppass, NULL, &srp_arg.srppassin, NULL))
+ {
+ BIO_printf(bio_err, "Error getting password\n");
+ goto end;
+ }
+#endif
+
ctx=SSL_CTX_new(meth);
if (ctx == NULL)
{
@@ -919,6 +1079,26 @@ bad:
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
+#ifndef OPENSSL_NO_SRP
+ if (srp_arg.srplogin)
+ {
+ if (srp_lateuser)
+ SSL_CTX_set_srp_missing_srp_username_callback(ctx,missing_srp_username_callback);
+ else if (!SSL_CTX_set_srp_username(ctx, srp_arg.srplogin))
+ {
+ BIO_printf(bio_err,"Unable to set SRP username\n");
+ goto end;
+ }
+ srp_arg.msg = c_msg;
+ srp_arg.debug = c_debug ;
+ SSL_CTX_set_srp_cb_arg(ctx,&srp_arg);
+ SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
+ SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
+ if (c_msg || c_debug || srp_arg.amp == 0)
+ SSL_CTX_set_srp_verify_param_callback(ctx, ssl_srp_verify_param_cb);
+ }
+
+#endif
#endif
con=SSL_new(ctx);
diff --git a/apps/s_server.c b/apps/s_server.c
index 9e2f4830b0..a1934e893d 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -186,6 +186,9 @@ typedef unsigned int u_int;
#ifndef OPENSSL_NO_RSA
#include <openssl/rsa.h>
#endif
+#ifndef OPENSSL_NO_SRP
+#include <openssl/srp.h>
+#endif
#include "s_apps.h"
#include "timeouts.h"
@@ -369,6 +372,40 @@ static unsigned int psk_server_cb(SSL *ssl, const char *identity,
}
#endif
+#ifndef OPENSSL_NO_SRP
+/* This is a context that we pass to callbacks */
+typedef struct srpsrvparm_st
+ {
+ int verbose;
+ char *login;
+ SRP_VBASE *vb;
+ } srpsrvparm;
+
+static int MS_CALLBACK ssl_srp_server_param_cb(SSL *s, int *ad, void *arg)
+ {
+ srpsrvparm *p = (srpsrvparm *) arg;
+ SRP_user_pwd *user;
+
+ p->login = BUF_strdup(SSL_get_srp_username(s));
+ BIO_printf(bio_err, "SRP username = \"%s\"\n", p->login);
+
+ user = SRP_VBASE_get_by_user(p->vb, p->login);
+ if (user == NULL)
+ {
+ BIO_printf(bio_err, "User %s doesn't exist\n", p->login);
+ return SSL3_AL_FATAL;
+ }
+ if (SSL_set_srp_server_param(s, user->N, user->g, user->s, user->v,
+ user->info) < 0)
+ {
+ *ad = SSL_AD_INTERNAL_ERROR;
+ return SSL3_AL_FATAL;
+ }
+ return SSL_ERROR_NONE;
+ }
+
+#endif
+
#ifdef MONOLITH
static void s_server_init(void)
{
@@ -456,6 +493,10 @@ static void sv_usage(void)
BIO_printf(bio_err," -jpake arg - JPAKE secret to use\n");
# endif
#endif
+#ifndef OPENSSL_NO_SRP
+ BIO_printf(bio_err," -srpvfile file - The verifier file for SRP\n");
+ BIO_printf(bio_err," -srpuserseed string - A seed string for a default user salt.\n");
+#endif
BIO_printf(bio_err," -ssl2 - Just talk SSLv2\n");
BIO_printf(bio_err," -ssl3 - Just talk SSLv3\n");
BIO_printf(bio_err," -tls1_1 - Just talk TLSv1_1\n");
@@ -874,12 +915,21 @@ int MAIN(int argc, char *argv[])
/* by default do not send a PSK identity hint */
static char *psk_identity_hint=NULL;
#endif
+#ifndef OPENSSL_NO_SRP
+ char *srpuserseed = NULL;
+ char *srp_verifier_file = NULL;
+ srpsrvparm p;
+#endif
#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
meth=SSLv23_server_method();
#elif !defined(OPENSSL_NO_SSL3)
meth=SSLv3_server_method();
#elif !defined(OPENSSL_NO_SSL2)
meth=SSLv2_server_method();
+#elif !defined(OPENSSL_NO_TLS1)
+ meth=TLSv1_server_method();
+#else
+ /* #error no SSL version enabled */
#endif
local_argc=argc;
@@ -1112,6 +1162,20 @@ int MAIN(int argc, char *argv[])
}
}
#endif
+#ifndef OPENSSL_NO_SRP
+ else if (strcmp(*argv, "-srpvfile") == 0)
+ {
+ if (--argc < 1) goto bad;
+ srp_verifier_file = *(++argv);
+ meth=TLSv1_server_method();
+ }
+ else if (strcmp(*argv, "-srpuserseed") == 0)
+ {
+ if (--argc < 1) goto bad;
+ srpuserseed = *(++argv);
+ meth=TLSv1_server_method();
+ }
+#endif
else if (strcmp(*argv,"-www") == 0)
{ www=1; }
else if (strcmp(*argv,"-WWW") == 0)
@@ -1690,6 +1754,23 @@ bad:
}
#endif
+#ifndef OPENSSL_NO_SRP
+ if (srp_verifier_file != NULL)
+ {
+ p.vb = SRP_VBASE_new(srpuserseed);
+ if ((ret = SRP_VBASE_init(p.vb, srp_verifier_file)) != SRP_NO_ERROR)
+ {
+ BIO_printf(bio_err,
+ "Cannot initialize SRP verifier file \"%s\":ret=%d\n",
+ srp_verifier_file, ret);
+ goto end;
+ }
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE,verify_callback);
+ SSL_CTX_set_srp_cb_arg(ctx, &p);
+ SSL_CTX_set_srp_username_callback(ctx, ssl_srp_server_param_cb);
+ }
+ else
+#endif
if (CAfile != NULL)
{
SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
diff --git a/apps/srp.c b/apps/srp.c
new file mode 100644
index 0000000000..4b969ec6dd
--- /dev/null
+++ b/apps/srp.c
@@ -0,0 +1,759 @@
+/* apps/srp.c */
+/* Written by Peter Sylvester (peter.sylvester@edelweb.fr)
+ * for the EdelKey project and contributed to the OpenSSL project 2004.
+ */
+/* ====================================================================
+ * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_SRP
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <openssl/conf.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/txt_db.h>
+#include <openssl/buffer.h>
+#include <openssl/srp.h>
+
+#include "apps.h"
+
+#undef PROG
+#define PROG srp_main
+
+#define BASE_SECTION "srp"
+#define CONFIG_FILE "openssl.cnf"
+
+#define ENV_RANDFILE "RANDFILE"
+
+#define ENV_DATABASE "srpvfile"
+#define ENV_DEFAULT_SRP "default_srp"
+
+static char *srp_usage[]={
+"usage: srp [args] [user] \n",
+"\n",
+" -verbose Talk alot while doing things\n",
+" -config file A config file\n",
+" -name arg The particular srp definition to use\n",
+" -srpvfile arg The srp verifier file name\n",
+" -add add an user and srp verifier\n",
+" -modify modify the srp verifier of an existing user\n",
+" -delete delete user from verifier file\n",
+" -list list user\n",
+" -gn arg g and N values to be used for new verifier\n",
+" -userinfo arg additional info to be set for user\n",
+" -passin arg input file pass phrase source\n",
+" -passout arg output file pass phrase source\n",
+#ifndef OPENSSL_NO_ENGINE
+" -engine e - use engine e, possibly a hardware device.\n",
+#endif
+NULL
+};
+
+#ifdef EFENCE
+extern int EF_PROTECT_FREE;
+extern int EF_PROTECT_BELOW;
+extern int EF_ALIGNMENT;
+#endif
+
+static CONF *conf=NULL;
+static char *section=NULL;
+
+#define VERBOSE if (verbose)
+#define VVERBOSE if (verbose>1)
+
+
+int MAIN(int, char **);
+
+static int get_index(CA_DB *db, char* id, char type)
+ {
+ char ** pp;
+ int i;
+ if (id == NULL) return -1;
+ if (type == DB_SRP_INDEX)
+ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+ {
+ pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i);
+ if (pp[DB_srptype][0] == DB_SRP_INDEX && !strcmp(id, pp[DB_srpid]))
+ return i;
+ }
+ else for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++)
+ {
+ pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, i);
+
+ if (pp[DB_srptype][0] != DB_SRP_INDEX && !strcmp(id,pp[DB_srpid]))
+ return i;
+ }
+
+ return -1 ;
+ }
+
+static void print_entry(CA_DB *db, BIO *bio, int indx, int verbose, char *s)
+ {
+ if (indx >= 0 && verbose)
+ {
+ int j;
+ char **pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, indx);
+ BIO_printf(bio, "%s \"%s\"\n", s, pp[DB_srpid]);
+ for (j = 0; j < DB_NUMBER; j++)
+ {
+ BIO_printf(bio_err," %d = \"%s\"\n", j, pp[j]);
+ }
+ }
+ }
+
+static void print_index(CA_DB *db, BIO *bio, int indexindex, int verbose)
+ {
+ print_entry(db, bio, indexindex, verbose, "g N entry") ;
+ }
+
+static void print_user(CA_DB *db, BIO *bio, int userindex, int verbose)
+ {
+ if (verbose > 0)
+ {
+ char **pp = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex);
+
+ if (pp[DB_srptype][0] != 'I')
+ {
+ print_entry(db, bio, userindex, verbose, "User entry");
+ print_entry(db, bio, get_index(db, pp[DB_srpgN], 'I'), verbose, "g N entry");
+ }
+
+ }
+ }
+
+static int update_index(CA_DB *db, BIO *bio, char **row)
+ {
+ char ** irow;
+ int i;
+
+ if ((irow=(char **)OPENSSL_malloc(sizeof(char *)*(DB_NUMBER+1))) == NULL)
+ {
+ BIO_printf(bio_err,"Memory allocation failure\n");
+ return 0;
+ }
+
+ for (i=0; i<DB_NUMBER; i++)
+ {
+ irow[i]=row[i];
+ row[i]=NULL;
+ }
+ irow[DB_NUMBER]=NULL;
+
+ if (!TXT_DB_insert(db->db,irow))
+ {
+ BIO_printf(bio,"failed to update srpvfile\n");
+ BIO_printf(bio,"TXT_DB error number %ld\n",db->db->error);
+ OPENSSL_free(irow);
+ return 0;
+ }
+ return 1;
+ }
+
+static void lookup_fail(const char *name, char *tag)
+ {
+ BIO_printf(bio_err,"variable lookup failed for %s::%s\n",name,tag);
+ }
+
+
+static char *srp_verify_user(const char *user, const char *srp_verifier,
+ char *srp_usersalt, const char *g, const char *N,
+ const char *passin, BIO *bio, int verbose)
+ {
+ char password[1024];
+ PW_CB_DATA cb_tmp;
+ char *verifier = NULL;
+ char *gNid = NULL;
+
+ cb_tmp.prompt_info = user;
+ cb_tmp.password = passin;
+
+ if (password_callback(password, 1024, 0, &cb_tmp) >0)
+ {
+ VERBOSE BIO_printf(bio,"Validating\n user=\"%s\"\n srp_verifier=\"%s\"\n srp_usersalt=\"%s\"\n g=\"%s\"\n N=\"%s\"\n",user,srp_verifier,srp_usersalt, g, N);
+ BIO_printf(bio, "Pass %s\n", password);
+
+ if (!(gNid=SRP_create_verifier(user, password, &srp_usersalt, &verifier, N, g)))
+ {
+ BIO_printf(bio, "Internal error validating SRP verifier\n");
+ }
+ else
+ {
+ if (strcmp(verifier, srp_verifier))
+ gNid = NULL;
+ OPENSSL_free(verifier);
+ }
+ }
+ return gNid;
+ }
+
+static char *srp_create_user(char *user, char **srp_verifier,
+ char **srp_usersalt, char *g, char *N,
+ char *passout, BIO *bio, int verbose)
+ {
+ char password[1024];
+