static int SSLSRPServerParamCallback(SSL *s, int *ad, void *arg) { const char* userName = SSL_get_srp_username(s); LOG(INFO) << "User " << userName; const User* user = GetUser(userName); if (!user) { LOG(ERROR) << "User " << userName << " doesn't exist"; *ad = SSL_AD_UNKNOWN_PSK_IDENTITY; return SSL3_AL_FATAL; } SRP_gN *GN = SRP_get_default_gN(FLAGS_srp_default_gN.c_str()); if(GN == NULL) { *ad = SSL_AD_INTERNAL_ERROR; return SSL3_AL_FATAL; } if (!SSL_set_srp_server_param(s, GN->N, GN->g, user->GetSalt(), user->GetVerifier(), NULL)) { *ad = SSL_AD_INTERNAL_ERROR; return SSL3_AL_FATAL; } return SSL_ERROR_NONE; }
/* If the server just has the raw password, make up a verifier entry on the fly */ int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass, const char *grp) { SRP_gN *GN = SRP_get_default_gN(grp); if(GN == NULL) return -1; s->srp_ctx.N = BN_dup(GN->N); s->srp_ctx.g = BN_dup(GN->g); if(s->srp_ctx.v != NULL) { BN_clear_free(s->srp_ctx.v); s->srp_ctx.v = NULL; } if(s->srp_ctx.s != NULL) { BN_clear_free(s->srp_ctx.s); s->srp_ctx.s = NULL; } if(!SRP_create_verifier_BN(user, pass, &s->srp_ctx.s, &s->srp_ctx.v, GN->N, GN->g)) return -1; return 1; }
int MAIN(int argc, char **argv) { int add_user = 0; int list_user= 0; int delete_user= 0; int modify_user= 0; char * user = NULL; char *passargin = NULL, *passargout = NULL; char *passin = NULL, *passout = NULL; char * gN = NULL; int gNindex = -1; char ** gNrow = NULL; int maxgN = -1; char * userinfo = NULL; int badops=0; int ret=1; int errors=0; int verbose=0; int doupdatedb=0; char *configfile=NULL; char *dbfile=NULL; CA_DB *db=NULL; char **pp ; int i; long errorline = -1; char *randfile=NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif char *tofree=NULL; DB_ATTR db_attr; #ifdef EFENCE EF_PROTECT_FREE=1; EF_PROTECT_BELOW=1; EF_ALIGNMENT=0; #endif apps_startup(); conf = NULL; section = NULL; if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); argc--; argv++; while (argc >= 1 && badops == 0) { if (strcmp(*argv,"-verbose") == 0) verbose++; else if (strcmp(*argv,"-config") == 0) { if (--argc < 1) goto bad; configfile= *(++argv); } else if (strcmp(*argv,"-name") == 0) { if (--argc < 1) goto bad; section= *(++argv); } else if (strcmp(*argv,"-srpvfile") == 0) { if (--argc < 1) goto bad; dbfile= *(++argv); } else if (strcmp(*argv,"-add") == 0) add_user=1; else if (strcmp(*argv,"-delete") == 0) delete_user=1; else if (strcmp(*argv,"-modify") == 0) modify_user=1; else if (strcmp(*argv,"-list") == 0) list_user=1; else if (strcmp(*argv,"-gn") == 0) { if (--argc < 1) goto bad; gN= *(++argv); } else if (strcmp(*argv,"-userinfo") == 0) { if (--argc < 1) goto bad; userinfo= *(++argv); } else if (strcmp(*argv,"-passin") == 0) { if (--argc < 1) goto bad; passargin= *(++argv); } else if (strcmp(*argv,"-passout") == 0) { if (--argc < 1) goto bad; passargout= *(++argv); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (**argv == '-') { bad: BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } else break; argc--; argv++; } if (dbfile && configfile) { BIO_printf(bio_err,"-dbfile and -configfile cannot be specified together.\n"); badops = 1; } if (add_user+delete_user+modify_user+list_user != 1) { BIO_printf(bio_err,"Exactly one of the options -add, -delete, -modify -list must be specified.\n"); badops = 1; } if (delete_user+modify_user+delete_user== 1 && argc <= 0) { BIO_printf(bio_err,"Need at least one user for options -add, -delete, -modify. \n"); badops = 1; } if ((passin || passout) && argc != 1 ) { BIO_printf(bio_err,"-passin, -passout arguments only valid with one user.\n"); badops = 1; } if (badops) { for (pp=srp_usage; (*pp != NULL); pp++) BIO_printf(bio_err,"%s",*pp); BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err," load the file (or the files in the directory) into\n"); BIO_printf(bio_err," the random number generator\n"); goto err; } ERR_load_crypto_strings(); #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto err; } if (!dbfile) { /*****************************************************************/ tofree=NULL; if (configfile == NULL) configfile = getenv("OPENSSL_CONF"); if (configfile == NULL) configfile = getenv("SSLEAY_CONF"); if (configfile == NULL) { const char *s=X509_get_default_cert_area(); size_t len; #ifdef OPENSSL_SYS_VMS len = strlen(s)+sizeof(CONFIG_FILE); tofree=OPENSSL_malloc(len); strcpy(tofree,s); #else len = strlen(s)+sizeof(CONFIG_FILE)+1; tofree=OPENSSL_malloc(len); BUF_strlcpy(tofree,s,len); BUF_strlcat(tofree,"/",len); #endif BUF_strlcat(tofree,CONFIG_FILE,len); configfile=tofree; } VERBOSE BIO_printf(bio_err,"Using configuration from %s\n",configfile); conf = NCONF_new(NULL); if (NCONF_load(conf,configfile,&errorline) <= 0) { if (errorline <= 0) BIO_printf(bio_err,"error loading the config file '%s'\n", configfile); else BIO_printf(bio_err,"error on line %ld of config file '%s'\n" ,errorline,configfile); goto err; } if(tofree) { OPENSSL_free(tofree); tofree = NULL; } if (!load_config(bio_err, conf)) goto err; /* Lets get the config section we are using */ if (section == NULL) { VERBOSE BIO_printf(bio_err,"trying to read " ENV_DEFAULT_SRP " in \" BASE_SECTION \"\n"); section=NCONF_get_string(conf,BASE_SECTION,ENV_DEFAULT_SRP); if (section == NULL) { lookup_fail(BASE_SECTION,ENV_DEFAULT_SRP); goto err; } } if (randfile == NULL && conf) randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); VERBOSE BIO_printf(bio_err,"trying to read " ENV_DATABASE " in section \"%s\"\n",section); if ((dbfile=NCONF_get_string(conf,section,ENV_DATABASE)) == NULL) { lookup_fail(section,ENV_DATABASE); goto err; } } if (randfile == NULL) ERR_clear_error(); else app_RAND_load_file(randfile, bio_err, 0); VERBOSE BIO_printf(bio_err,"Trying to read SRP verifier file \"%s\"\n",dbfile); db = load_index(dbfile, &db_attr); if (db == NULL) goto err; /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_srptype][0] == DB_SRP_INDEX) { maxgN = i; if (gNindex < 0 && gN != NULL && !strcmp(gN, pp[DB_srpid])) gNindex = i; print_index(db, bio_err, i, verbose > 1); } } VERBOSE BIO_printf(bio_err, "Database initialised\n"); if (gNindex >= 0) { gNrow = sk_OPENSSL_PSTRING_value(db->db->data,gNindex); print_entry(db, bio_err, gNindex, verbose > 1, "Default g and N"); } else if (maxgN > 0 && !SRP_get_default_gN(gN)) { BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN); goto err; } else { VERBOSE BIO_printf(bio_err, "Database has no g N information.\n"); gNrow = NULL; } VVERBOSE BIO_printf(bio_err,"Starting user processing\n"); if (argc > 0) user = *(argv++) ; while (list_user || user) { int userindex = -1; if (user) VVERBOSE BIO_printf(bio_err, "Processing user \"%s\"\n", user); if ((userindex = get_index(db, user, 'U')) >= 0) { print_user(db, bio_err, userindex, (verbose > 0) || list_user); } if (list_user) { if (user == NULL) { BIO_printf(bio_err,"List all users\n"); for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { print_user(db,bio_err, i, 1); } list_user = 0; } else if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n", user); errors++; } } else if (add_user) { if (userindex >= 0) { /* reactivation of a new user */ char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex); BIO_printf(bio_err, "user \"%s\" reactivated.\n", user); row[DB_srptype][0] = 'V'; doupdatedb = 1; } else { char *row[DB_NUMBER] ; char *gNid; row[DB_srpverifier] = NULL; row[DB_srpsalt] = NULL; row[DB_srpinfo] = NULL; if (!(gNid = srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:gN,gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose))) { BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned .\n", user); errors++; goto err; } row[DB_srpid] = BUF_strdup(user); row[DB_srptype] = BUF_strdup("v"); row[DB_srpgN] = BUF_strdup(gNid); if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] || (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo)))) || !update_index(db, bio_err, row)) { if (row[DB_srpid]) OPENSSL_free(row[DB_srpid]); if (row[DB_srpgN]) OPENSSL_free(row[DB_srpgN]); if (row[DB_srpinfo]) OPENSSL_free(row[DB_srpinfo]); if (row[DB_srptype]) OPENSSL_free(row[DB_srptype]); if (row[DB_srpverifier]) OPENSSL_free(row[DB_srpverifier]); if (row[DB_srpsalt]) OPENSSL_free(row[DB_srpsalt]); goto err; } doupdatedb = 1; } } else if (modify_user) { if (userindex < 0) { BIO_printf(bio_err,"user \"%s\" does not exist, operation ignored.\n",user); errors++; } else { char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex); char type = row[DB_srptype][0]; if (type == 'v') { BIO_printf(bio_err,"user \"%s\" already updated, operation ignored.\n",user); errors++; } else { char *gNid; if (row[DB_srptype][0] == 'V') { int user_gN; char **irow = NULL; VERBOSE BIO_printf(bio_err,"Verifying password for user \"%s\"\n",user); if ( (user_gN = get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0) irow = (char **)sk_OPENSSL_PSTRING_value(db->db->data, userindex); if (!srp_verify_user(user, row[DB_srpverifier], row[DB_srpsalt], irow ? irow[DB_srpsalt] : row[DB_srpgN], irow ? irow[DB_srpverifier] : NULL, passin, bio_err, verbose)) { BIO_printf(bio_err, "Invalid password for user \"%s\", operation abandoned.\n", user); errors++; goto err; } } VERBOSE BIO_printf(bio_err,"Password for user \"%s\" ok.\n",user); if (!(gNid=srp_create_user(user,&(row[DB_srpverifier]), &(row[DB_srpsalt]),gNrow?gNrow[DB_srpsalt]:NULL, gNrow?gNrow[DB_srpverifier]:NULL, passout, bio_err,verbose))) { BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user); errors++; goto err; } row[DB_srptype][0] = 'v'; row[DB_srpgN] = BUF_strdup(gNid); if (!row[DB_srpid] || !row[DB_srpgN] || !row[DB_srptype] || !row[DB_srpverifier] || !row[DB_srpsalt] || (userinfo && (!(row[DB_srpinfo] = BUF_strdup(userinfo))))) goto err; doupdatedb = 1; } } } else if (delete_user) { if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user); errors++; } else { char **xpp = sk_OPENSSL_PSTRING_value(db->db->data,userindex); BIO_printf(bio_err, "user \"%s\" revoked. t\n", user); xpp[DB_srptype][0] = 'R'; doupdatedb = 1; } } if (--argc > 0) user = *(argv++) ; else { user = NULL; list_user = 0; } } VERBOSE BIO_printf(bio_err,"User procession done.\n"); if (doupdatedb) { /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { pp = sk_OPENSSL_PSTRING_value(db->db->data,i); if (pp[DB_srptype][0] == 'v') { pp[DB_srptype][0] = 'V'; print_user(db, bio_err, i, verbose); } } VERBOSE BIO_printf(bio_err, "Trying to update srpvfile.\n"); if (!save_index(dbfile, "new", db)) goto err; VERBOSE BIO_printf(bio_err, "Temporary srpvfile created.\n"); if (!rotate_index(dbfile, "new", "old")) goto err; VERBOSE BIO_printf(bio_err, "srpvfile updated.\n"); } ret = (errors != 0); err: if (errors != 0) VERBOSE BIO_printf(bio_err,"User errors %d.\n",errors); VERBOSE BIO_printf(bio_err,"SRP terminating with code %d.\n",ret); if(tofree) OPENSSL_free(tofree); if (ret) ERR_print_errors(bio_err); if (randfile) app_RAND_write_file(randfile, bio_err); if (conf) NCONF_free(conf); if (db) free_index(db); OBJ_cleanup(); apps_shutdown(); OPENSSL_EXIT(ret); }
static int run_srp(const char *username, const char *client_pass, const char *server_pass) { int ret=-1; BIGNUM *s = NULL; BIGNUM *v = NULL; BIGNUM *a = NULL; BIGNUM *b = NULL; BIGNUM *u = NULL; BIGNUM *x = NULL; BIGNUM *Apub = NULL; BIGNUM *Bpub = NULL; BIGNUM *Kclient = NULL; BIGNUM *Kserver = NULL; unsigned char rand_tmp[RANDOM_SIZE]; /* use builtin 1024-bit params */ const SRP_gN *GN = SRP_get_default_gN("1024"); if(GN == NULL) { fprintf(stderr, "Failed to get SRP parameters\n"); return -1; } /* Set up server's password entry */ if(!SRP_create_verifier_BN(username, server_pass, &s, &v, GN->N, GN->g)) { fprintf(stderr, "Failed to create SRP verifier\n"); return -1; } showbn("N", GN->N); showbn("g", GN->g); showbn("Salt", s); showbn("Verifier", v); /* Server random */ RAND_pseudo_bytes(rand_tmp, sizeof(rand_tmp)); b = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); /* TODO - check b != 0 */ showbn("b", b); /* Server's first message */ Bpub = SRP_Calc_B(b, GN->N, GN->g, v); showbn("B", Bpub); if(!SRP_Verify_B_mod_N(Bpub, GN->N)) { fprintf(stderr, "Invalid B\n"); return -1; } /* Client random */ RAND_pseudo_bytes(rand_tmp, sizeof(rand_tmp)); a = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); /* TODO - check a != 0 */ showbn("a", a); /* Client's response */ Apub = SRP_Calc_A(a, GN->N, GN->g); showbn("A", Apub); if(!SRP_Verify_A_mod_N(Apub, GN->N)) { fprintf(stderr, "Invalid A\n"); return -1; } /* Both sides calculate u */ u = SRP_Calc_u(Apub, Bpub, GN->N); /* Client's key */ x = SRP_Calc_x(s, username, client_pass); Kclient = SRP_Calc_client_key(GN->N, Bpub, GN->g, x, a, u); showbn("Client's key", Kclient); /* Server's key */ Kserver = SRP_Calc_server_key(Apub, v, u, b, GN->N); showbn("Server's key", Kserver); if(BN_cmp(Kclient, Kserver) == 0) { ret = 0; } else { fprintf(stderr, "Keys mismatch\n"); ret = 1; } BN_clear_free(Kclient); BN_clear_free(Kserver); BN_clear_free(x); BN_free(u); BN_free(Apub); BN_clear_free(a); BN_free(Bpub); BN_clear_free(b); BN_free(s); BN_clear_free(v); return ret; }
/* SRP test vectors from RFC5054 */ static int run_srp_kat(void) { int ret = 0; BIGNUM *s = NULL; BIGNUM *v = NULL; BIGNUM *a = NULL; BIGNUM *b = NULL; BIGNUM *u = NULL; BIGNUM *x = NULL; BIGNUM *Apub = NULL; BIGNUM *Bpub = NULL; BIGNUM *Kclient = NULL; BIGNUM *Kserver = NULL; /* use builtin 1024-bit params */ const SRP_gN *GN = SRP_get_default_gN("1024"); if (GN == NULL) { fprintf(stderr, "Failed to get SRP parameters\n"); goto err; } BN_hex2bn(&s, "BEB25379D1A8581EB5A727673A2441EE"); /* Set up server's password entry */ if (!SRP_create_verifier_BN("alice", "password123", &s, &v, GN->N, GN->g)) { fprintf(stderr, "Failed to create SRP verifier\n"); goto err; } if (!check_bn("v", v, "7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812" "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5" "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5" "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78" "E955A5E29E7AB245DB2BE315E2099AFB")) goto err; /* Server random */ BN_hex2bn(&b, "E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" "05284D20"); /* Server's first message */ Bpub = SRP_Calc_B(b, GN->N, GN->g, v); if (!SRP_Verify_B_mod_N(Bpub, GN->N)) { fprintf(stderr, "Invalid B\n"); goto err; } if (!check_bn("B", Bpub, "BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011" "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99" "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA" "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE" "EB4012B7D7665238A8E3FB004B117B58")) goto err; /* Client random */ BN_hex2bn(&a, "60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" "DA2D4393"); /* Client's response */ Apub = SRP_Calc_A(a, GN->N, GN->g); if (!SRP_Verify_A_mod_N(Apub, GN->N)) { fprintf(stderr, "Invalid A\n"); return -1; } if (!check_bn("A", Apub, "61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4" "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC" "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44" "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA" "B349EF5D76988A3672FAC47B0769447B")) goto err; /* Both sides calculate u */ u = SRP_Calc_u(Apub, Bpub, GN->N); if (!check_bn("u", u, "CE38B9593487DA98554ED47D70A7AE5F462EF019")) goto err; /* Client's key */ x = SRP_Calc_x(s, "alice", "password123"); Kclient = SRP_Calc_client_key(GN->N, Bpub, GN->g, x, a, u); if (!check_bn("Client's key", Kclient, "B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F" "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" "C346D7E474B29EDE8A469FFECA686E5A")) goto err; /* Server's key */ Kserver = SRP_Calc_server_key(Apub, v, u, b, GN->N); if (!check_bn("Server's key", Kserver, "B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F" "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" "C346D7E474B29EDE8A469FFECA686E5A")) goto err; ret = 1; err: BN_clear_free(Kclient); BN_clear_free(Kserver); BN_clear_free(x); BN_free(u); BN_free(Apub); BN_clear_free(a); BN_free(Bpub); BN_clear_free(b); BN_free(s); BN_clear_free(v); return ret; }
int srp_main(int argc, char **argv) { CA_DB *db = NULL; CONF *conf = NULL; int gNindex = -1, maxgN = -1, ret = 1, errors = 0, verbose = 0, i; int doupdatedb = 0, mode = OPT_ERR; char *user = NULL, *passinarg = NULL, *passoutarg = NULL; char *passin = NULL, *passout = NULL, *gN = NULL, *userinfo = NULL; char *randfile = NULL, *section = NULL; char **gNrow = NULL, *configfile = NULL; char *srpvfile = NULL, **pp, *prog; OPTION_CHOICE o; prog = opt_init(argc, argv, srp_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(srp_options); ret = 0; goto end; case OPT_VERBOSE: verbose++; break; case OPT_CONFIG: configfile = opt_arg(); break; case OPT_NAME: section = opt_arg(); break; case OPT_SRPVFILE: srpvfile = opt_arg(); break; case OPT_ADD: case OPT_DELETE: case OPT_MODIFY: case OPT_LIST: if (mode != OPT_ERR) { BIO_printf(bio_err, "%s: Only one of -add/delete-modify/-list\n", prog); goto opthelp; } mode = o; break; case OPT_GN: gN = opt_arg(); break; case OPT_USERINFO: userinfo = opt_arg(); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_PASSOUT: passoutarg = opt_arg(); break; case OPT_ENGINE: (void)setup_engine(opt_arg(), 0); break; } } argc = opt_num_rest(); argv = opt_rest(); if (srpvfile && configfile) { BIO_printf(bio_err, "-srpvfile and -configfile cannot be specified together.\n"); goto end; } if (mode == OPT_ERR) { BIO_printf(bio_err, "Exactly one of the options -add, -delete, -modify -list must be specified.\n"); goto opthelp; } if ((mode == OPT_DELETE || mode == OPT_MODIFY || mode == OPT_ADD) && argc < 1) { BIO_printf(bio_err, "Need at least one user for options -add, -delete, -modify. \n"); goto opthelp; } if ((passin || passout) && argc != 1) { BIO_printf(bio_err, "-passin, -passout arguments only valid with one user.\n"); goto opthelp; } if (!app_passwd(passinarg, passoutarg, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } if (!srpvfile) { if (!configfile) configfile = default_config_file; if (verbose) BIO_printf(bio_err, "Using configuration from %s\n", configfile); conf = app_load_config(configfile); if (conf == NULL) goto end; if (configfile != default_config_file && !app_load_modules(conf)) goto end; /* Lets get the config section we are using */ if (section == NULL) { if (verbose) BIO_printf(bio_err, "trying to read " ENV_DEFAULT_SRP " in " BASE_SECTION "\n"); section = lookup_conf(conf, BASE_SECTION, ENV_DEFAULT_SRP); if (section == NULL) goto end; } if (randfile == NULL) randfile = NCONF_get_string(conf, BASE_SECTION, "RANDFILE"); if (verbose) BIO_printf(bio_err, "trying to read " ENV_DATABASE " in section \"%s\"\n", section); srpvfile = lookup_conf(conf, section, ENV_DATABASE); if (srpvfile == NULL) goto end; } if (randfile == NULL) ERR_clear_error(); else app_RAND_load_file(randfile, 0); if (verbose) BIO_printf(bio_err, "Trying to read SRP verifier file \"%s\"\n", srpvfile); db = load_index(srpvfile, NULL); if (db == NULL) goto end; /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_srptype][0] == DB_SRP_INDEX) { maxgN = i; if ((gNindex < 0) && (gN != NULL) && strcmp(gN, pp[DB_srpid]) == 0) gNindex = i; print_index(db, i, verbose > 1); } } if (verbose) BIO_printf(bio_err, "Database initialised\n"); if (gNindex >= 0) { gNrow = sk_OPENSSL_PSTRING_value(db->db->data, gNindex); print_entry(db, gNindex, verbose > 1, "Default g and N"); } else if (maxgN > 0 && !SRP_get_default_gN(gN)) { BIO_printf(bio_err, "No g and N value for index \"%s\"\n", gN); goto end; } else { if (verbose) BIO_printf(bio_err, "Database has no g N information.\n"); gNrow = NULL; } if (verbose > 1) BIO_printf(bio_err, "Starting user processing\n"); if (argc > 0) user = *(argv++); while (mode == OPT_LIST || user) { int userindex = -1; if (user != NULL && verbose > 1) BIO_printf(bio_err, "Processing user \"%s\"\n", user); if ((userindex = get_index(db, user, 'U')) >= 0) { print_user(db, userindex, (verbose > 0) || mode == OPT_LIST); } if (mode == OPT_LIST) { if (user == NULL) { BIO_printf(bio_err, "List all users\n"); for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { print_user(db, i, 1); } } else if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, ignored. t\n", user); errors++; } } else if (mode == OPT_ADD) { if (userindex >= 0) { /* reactivation of a new user */ char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex); BIO_printf(bio_err, "user \"%s\" reactivated.\n", user); row[DB_srptype][0] = 'V'; doupdatedb = 1; } else { char *row[DB_NUMBER]; char *gNid; row[DB_srpverifier] = NULL; row[DB_srpsalt] = NULL; row[DB_srpinfo] = NULL; if (! (gNid = srp_create_user(user, &(row[DB_srpverifier]), &(row[DB_srpsalt]), gNrow ? gNrow[DB_srpsalt] : gN, gNrow ? gNrow[DB_srpverifier] : NULL, passout, verbose))) { BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned .\n", user); errors++; goto end; } row[DB_srpid] = OPENSSL_strdup(user); row[DB_srptype] = OPENSSL_strdup("v"); row[DB_srpgN] = OPENSSL_strdup(gNid); if ((row[DB_srpid] == NULL) || (row[DB_srpgN] == NULL) || (row[DB_srptype] == NULL) || (row[DB_srpverifier] == NULL) || (row[DB_srpsalt] == NULL) || (userinfo && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL)) || !update_index(db, row)) { OPENSSL_free(row[DB_srpid]); OPENSSL_free(row[DB_srpgN]); OPENSSL_free(row[DB_srpinfo]); OPENSSL_free(row[DB_srptype]); OPENSSL_free(row[DB_srpverifier]); OPENSSL_free(row[DB_srpsalt]); goto end; } doupdatedb = 1; } } else if (mode == OPT_MODIFY) { if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored.\n", user); errors++; } else { char **row = sk_OPENSSL_PSTRING_value(db->db->data, userindex); char type = row[DB_srptype][0]; if (type == 'v') { BIO_printf(bio_err, "user \"%s\" already updated, operation ignored.\n", user); errors++; } else { char *gNid; if (row[DB_srptype][0] == 'V') { int user_gN; char **irow = NULL; if (verbose) BIO_printf(bio_err, "Verifying password for user \"%s\"\n", user); if ((user_gN = get_index(db, row[DB_srpgN], DB_SRP_INDEX)) >= 0) irow = sk_OPENSSL_PSTRING_value(db->db->data, userindex); if (!srp_verify_user (user, row[DB_srpverifier], row[DB_srpsalt], irow ? irow[DB_srpsalt] : row[DB_srpgN], irow ? irow[DB_srpverifier] : NULL, passin, verbose)) { BIO_printf(bio_err, "Invalid password for user \"%s\", operation abandoned.\n", user); errors++; goto end; } } if (verbose) BIO_printf(bio_err, "Password for user \"%s\" ok.\n", user); if (! (gNid = srp_create_user(user, &(row[DB_srpverifier]), &(row[DB_srpsalt]), gNrow ? gNrow[DB_srpsalt] : NULL, gNrow ? gNrow[DB_srpverifier] : NULL, passout, verbose))) { BIO_printf(bio_err, "Cannot create srp verifier for user \"%s\", operation abandoned.\n", user); errors++; goto end; } row[DB_srptype][0] = 'v'; row[DB_srpgN] = OPENSSL_strdup(gNid); if (row[DB_srpid] == NULL || row[DB_srpgN] == NULL || row[DB_srptype] == NULL || row[DB_srpverifier] == NULL || row[DB_srpsalt] == NULL || (userinfo && ((row[DB_srpinfo] = OPENSSL_strdup(userinfo)) == NULL))) goto end; doupdatedb = 1; } } } else if (mode == OPT_DELETE) { if (userindex < 0) { BIO_printf(bio_err, "user \"%s\" does not exist, operation ignored. t\n", user); errors++; } else { char **xpp = sk_OPENSSL_PSTRING_value(db->db->data, userindex); BIO_printf(bio_err, "user \"%s\" revoked. t\n", user); xpp[DB_srptype][0] = 'R'; doupdatedb = 1; } } if (--argc > 0) user = *(argv++); else { user = NULL; } } if (verbose) BIO_printf(bio_err, "User procession done.\n"); if (doupdatedb) { /* Lets check some fields */ for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { pp = sk_OPENSSL_PSTRING_value(db->db->data, i); if (pp[DB_srptype][0] == 'v') { pp[DB_srptype][0] = 'V'; print_user(db, i, verbose); } } if (verbose) BIO_printf(bio_err, "Trying to update srpvfile.\n"); if (!save_index(srpvfile, "new", db)) goto end; if (verbose) BIO_printf(bio_err, "Temporary srpvfile created.\n"); if (!rotate_index(srpvfile, "new", "old")) goto end; if (verbose) BIO_printf(bio_err, "srpvfile updated.\n"); } ret = (errors != 0); end: if (errors != 0) if (verbose) BIO_printf(bio_err, "User errors %d.\n", errors); if (verbose) BIO_printf(bio_err, "SRP terminating with code %d.\n", ret); OPENSSL_free(passin); OPENSSL_free(passout); if (ret) ERR_print_errors(bio_err); if (randfile) app_RAND_write_file(randfile); NCONF_free(conf); free_index(db); return (ret); }
static int run_srp(const char *username, const char *client_pass, const char *server_pass) { int ret = 0; BIGNUM *s = NULL; BIGNUM *v = NULL; BIGNUM *a = NULL; BIGNUM *b = NULL; BIGNUM *u = NULL; BIGNUM *x = NULL; BIGNUM *Apub = NULL; BIGNUM *Bpub = NULL; BIGNUM *Kclient = NULL; BIGNUM *Kserver = NULL; unsigned char rand_tmp[RANDOM_SIZE]; /* use builtin 1024-bit params */ const SRP_gN *GN; if (!TEST_ptr(GN = SRP_get_default_gN("1024"))) return 0; /* Set up server's password entry */ if (!TEST_true(SRP_create_verifier_BN(username, server_pass, &s, &v, GN->N, GN->g))) goto end; showbn("N", GN->N); showbn("g", GN->g); showbn("Salt", s); showbn("Verifier", v); /* Server random */ RAND_bytes(rand_tmp, sizeof(rand_tmp)); b = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); if (!TEST_BN_ne_zero(b)) goto end; showbn("b", b); /* Server's first message */ Bpub = SRP_Calc_B(b, GN->N, GN->g, v); showbn("B", Bpub); if (!TEST_true(SRP_Verify_B_mod_N(Bpub, GN->N))) goto end; /* Client random */ RAND_bytes(rand_tmp, sizeof(rand_tmp)); a = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); if (!TEST_BN_ne_zero(a)) goto end; showbn("a", a); /* Client's response */ Apub = SRP_Calc_A(a, GN->N, GN->g); showbn("A", Apub); if (!TEST_true(SRP_Verify_A_mod_N(Apub, GN->N))) goto end; /* Both sides calculate u */ u = SRP_Calc_u(Apub, Bpub, GN->N); /* Client's key */ x = SRP_Calc_x(s, username, client_pass); Kclient = SRP_Calc_client_key(GN->N, Bpub, GN->g, x, a, u); showbn("Client's key", Kclient); /* Server's key */ Kserver = SRP_Calc_server_key(Apub, v, u, b, GN->N); showbn("Server's key", Kserver); if (!TEST_BN_eq(Kclient, Kserver)) goto end; ret = 1; end: BN_clear_free(Kclient); BN_clear_free(Kserver); BN_clear_free(x); BN_free(u); BN_free(Apub); BN_clear_free(a); BN_free(Bpub); BN_clear_free(b); BN_free(s); BN_clear_free(v); return ret; }