struct SRPUser * srp_user_new( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char * username, const unsigned char * bytes_password, int len_password, const char * n_hex, const char * g_hex ) { struct SRPUser *usr = (struct SRPUser *) malloc( sizeof(struct SRPUser) ); int ulen = (int)strlen(username) + 1; init_random(); /* Only happens once */ usr->hash_alg = alg; usr->ng = new_ng( ng_type, n_hex, g_hex ); usr->a = BN_new(); usr->A = BN_new(); usr->S = BN_new(); usr->username = (const char *) malloc(ulen); usr->password = (const unsigned char *) malloc(len_password); usr->password_len = len_password; usr->authenticated = 0; memcpy((char *)usr->username, username, ulen); memcpy((char *)usr->password, bytes_password, len_password); usr->bytes_A = 0; return usr; }
struct SRPUser *srp_user_new(SRP_HashAlgorithm alg, SRP_NGType ng_type, const char *username, const char *username_for_verifier, const unsigned char *bytes_password, size_t len_password, const char *n_hex, const char *g_hex) { struct SRPUser *usr = (struct SRPUser *)srp_alloc(sizeof(struct SRPUser)); size_t ulen = strlen(username) + 1; size_t uvlen = strlen(username_for_verifier) + 1; if (!usr) goto err_exit; if (init_random() != SRP_OK) /* Only happens once */ goto err_exit; usr->hash_alg = alg; usr->ng = new_ng(ng_type, n_hex, g_hex); mpz_init(usr->a); mpz_init(usr->A); mpz_init(usr->S); if (!usr->ng) goto err_exit; usr->username = (char *)srp_alloc(ulen); usr->username_verifier = (char *)srp_alloc(uvlen); usr->password = (unsigned char *)srp_alloc(len_password); usr->password_len = len_password; if (!usr->username || !usr->password || !usr->username_verifier) goto err_exit; memcpy(usr->username, username, ulen); memcpy(usr->username_verifier, username_for_verifier, uvlen); memcpy(usr->password, bytes_password, len_password); usr->authenticated = 0; usr->bytes_A = 0; return usr; err_exit: if (usr) { mpz_clear(usr->a); mpz_clear(usr->A); mpz_clear(usr->S); if (usr->ng) delete_ng(usr->ng); srp_free(usr->username); srp_free(usr->username_verifier); if (usr->password) { memset(usr->password, 0, usr->password_len); srp_free(usr->password); } srp_free(usr); } return 0; }
struct SRPUser * srp_user_new( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char * username, const char * bytes_password, int len_password, const char * n_hex, const char * g_hex ) { struct SRPUser *usr = (struct SRPUser *) malloc( sizeof(struct SRPUser) ); int ulen = strlen(username) + 1; if (!usr) goto err_exit; init_random(); /* Only happens once */ usr->hash_alg = alg; usr->ng = new_ng( ng_type, n_hex, g_hex ); usr->a = BN_new(); usr->A = BN_new(); usr->S = BN_new(); if (!usr->ng || !usr->a || !usr->A || !usr->S) goto err_exit; usr->username = (const char *) malloc(ulen); usr->password = (const unsigned char *) malloc(len_password); usr->password_len = len_password; if (!usr->username || !usr->password) goto err_exit; memcpy((char *)usr->username, username, ulen); memcpy((char *)usr->password, bytes_password, len_password); usr->authenticated = 0; usr->bytes_A = 0; return usr; err_exit: if (usr) { BN_free(usr->a); BN_free(usr->A); BN_free(usr->S); if (usr->username) free((void*)usr->username); if (usr->password) { memset((void*)usr->password, 0, usr->password_len); free((void*)usr->password); } free(usr); } return 0; }
// clang-format off SRP_Result srp_create_salted_verification_key( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char *username_for_verifier, const unsigned char *password, size_t len_password, unsigned char **bytes_s, size_t *len_s, unsigned char **bytes_v, size_t *len_v, const char *n_hex, const char *g_hex ) { SRP_Result ret = SRP_OK; mpz_t v; mpz_init(v); mpz_t x; mpz_init(x); // clang-format on NGConstant *ng = new_ng(ng_type, n_hex, g_hex); if (!ng) goto error_and_exit; if (init_random() != SRP_OK) /* Only happens once */ goto error_and_exit; if (*bytes_s == NULL) { size_t size_to_fill = 16; *len_s = size_to_fill; if (RAND_BUFF_MAX - g_rand_idx < size_to_fill) if (fill_buff() != SRP_OK) goto error_and_exit; *bytes_s = (unsigned char *)srp_alloc(size_to_fill); if (!*bytes_s) goto error_and_exit; memcpy(*bytes_s, g_rand_buff + g_rand_idx, size_to_fill); g_rand_idx += size_to_fill; } if (!calculate_x( x, alg, *bytes_s, *len_s, username_for_verifier, password, len_password)) goto error_and_exit; srp_dbg_num(x, "Server calculated x: "); mpz_powm(v, ng->g, x, ng->N); *len_v = mpz_num_bytes(v); *bytes_v = (unsigned char *)srp_alloc(*len_v); if (!*bytes_v) goto error_and_exit; mpz_to_bin(v, *bytes_v); cleanup_and_exit: delete_ng(ng); mpz_clear(v); mpz_clear(x); return ret; error_and_exit: ret = SRP_ERR; goto cleanup_and_exit; }
SRPUser * srp_user_new_with_a(SRP_HashAlgorithm alg, SRP_NGType ng_type, const char *username, const char *password, const char *n_hex, const char *g_hex, BIGNUM *a) { SRPUser *usr = (SRPUser *)malloc(sizeof(SRPUser)); int username_length = strlen(username) + 1; int password_length = strlen(password) + 1; if (!usr) goto err_exit; init_random(); usr->hash_alg = alg; usr->ng = new_ng(ng_type, n_hex, g_hex); usr->a = a; usr->A = BN_new(); usr->S = BN_new(); usr->Astr = 0; usr->HAMK = 0; if (!usr->ng || !usr->a || !usr->A || !usr->S) goto err_exit; usr->username = (const char *) malloc(username_length); usr->password = (const char *) malloc(password_length); usr->password_len = password_length; if (!usr->username || !usr->password) goto err_exit; memcpy((char *)usr->username, username, username_length); memcpy((char *)usr->password, password, password_length); usr->authenticated = 0; usr->bytes_A = 0; return usr; err_exit: if (usr) { BN_free(usr->a); BN_free(usr->A); BN_free(usr->S); if (usr->username) free((void*)usr->username); if (usr->password) { memset((void*)usr->password, 0, usr->password_len); free((void*)usr->password); } free(usr); } return 0; }
void srp_create_salted_verification_key( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char * username, const unsigned char * password, int len_password, const unsigned char ** bytes_s, int * len_s, const unsigned char ** bytes_v, int * len_v, const char * n_hex, const char * g_hex ) { BIGNUM * s = BN_new(); BIGNUM * v = BN_new(); BIGNUM * x = 0; BN_CTX * ctx = BN_CTX_new(); NGConstant * ng = new_ng( ng_type, n_hex, g_hex ); if( !s || !v || !ctx || !ng ) goto cleanup_and_exit; init_random(); /* Only happens once */ BN_rand(s, 32, -1, 0); x = calculate_x( alg, s, username, password, len_password ); if( !x ) goto cleanup_and_exit; BN_mod_exp(v, ng->g, x, ng->N, ctx); *len_s = BN_num_bytes(s); *len_v = BN_num_bytes(v); *bytes_s = (const unsigned char *) malloc( *len_s ); *bytes_v = (const unsigned char *) malloc( *len_v ); if (!bytes_s || !bytes_v) goto cleanup_and_exit; BN_bn2bin(s, (unsigned char *) *bytes_s); BN_bn2bin(v, (unsigned char *) *bytes_v); cleanup_and_exit: delete_ng( ng ); BN_free(s); BN_free(v); BN_free(x); BN_CTX_free(ctx); }
/* Out: bytes_B, len_B. * * On failure, bytes_B will be set to NULL and len_B will be set to 0 */ struct SRPVerifier * srp_verifier_new( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char * username, const unsigned char * bytes_s, int len_s, const unsigned char * bytes_v, int len_v, const unsigned char * bytes_A, int len_A, const unsigned char ** bytes_B, int * len_B, const char * n_hex, const char * g_hex ) { BIGNUM *s = BN_bin2bn(bytes_s, len_s, NULL); BIGNUM *v = BN_bin2bn(bytes_v, len_v, NULL); BIGNUM *A = BN_bin2bn(bytes_A, len_A, NULL); BIGNUM *u = 0; BIGNUM *B = BN_new(); BIGNUM *S = BN_new(); BIGNUM *b = BN_new(); BIGNUM *k = 0; BIGNUM *tmp1 = BN_new(); BIGNUM *tmp2 = BN_new(); BN_CTX *ctx = BN_CTX_new(); int ulen = strlen(username) + 1; NGConstant *ng = new_ng( ng_type, n_hex, g_hex ); struct SRPVerifier *ver = 0; *len_B = 0; *bytes_B = 0; if( !s || !v || !A || !B || !S || !b || !tmp1 || !tmp2 || !ctx || !ng ) goto cleanup_and_exit; ver = (struct SRPVerifier *) malloc( sizeof(struct SRPVerifier) ); if (!ver) goto cleanup_and_exit; init_random(); /* Only happens once */ ver->username = (char *) malloc( ulen ); ver->hash_alg = alg; ver->ng = ng; if (!ver->username) { free(ver); ver = 0; goto cleanup_and_exit; } memcpy( (char*)ver->username, username, ulen ); ver->authenticated = 0; /* SRP-6a safety check */ BN_mod(tmp1, A, ng->N, ctx); if ( !BN_is_zero(tmp1) ) { BN_rand(b, 256, -1, 0); k = H_nn(alg, ng->N, ng->g); /* B = kv + g^b */ BN_mul(tmp1, k, v, ctx); BN_mod_exp(tmp2, ng->g, b, ng->N, ctx); BN_add(B, tmp1, tmp2); u = H_nn(alg, A, B); /* S = (A *(v^u)) ^ b */ BN_mod_exp(tmp1, v, u, ng->N, ctx); BN_mul(tmp2, A, tmp1, ctx); BN_mod_exp(S, tmp2, b, ng->N, ctx); hash_num(alg, S, ver->session_key); calculate_M( alg, ng, ver->M, username, s, A, B, ver->session_key ); calculate_H_AMK( alg, ver->H_AMK, A, ver->M, ver->session_key ); *len_B = BN_num_bytes(B); *bytes_B = malloc( *len_B ); if( !*bytes_B ) { free( (void*) ver->username ); free( ver ); ver = 0; *len_B = 0; goto cleanup_and_exit; } BN_bn2bin( B, (unsigned char *) *bytes_B ); ver->bytes_B = *bytes_B; } cleanup_and_exit: BN_free(s); BN_free(v); BN_free(A); if (u) BN_free(u); if (k) BN_free(k); BN_free(B); BN_free(S); BN_free(b); BN_free(tmp1); BN_free(tmp2); BN_CTX_free(ctx); return ver; }
/* Out: bytes_B, len_B. * * On failure, bytes_B will be set to NULL and len_B will be set to 0 */ struct SRPVerifier *srp_verifier_new(SRP_HashAlgorithm alg, SRP_NGType ng_type, const char *username, const unsigned char *bytes_s, size_t len_s, const unsigned char *bytes_v, size_t len_v, const unsigned char *bytes_A, size_t len_A, const unsigned char *bytes_b, size_t len_b, unsigned char **bytes_B, size_t *len_B, const char *n_hex, const char *g_hex ) { mpz_t v; mpz_init(v); mpz_from_bin(bytes_v, len_v, v); mpz_t A; mpz_init(A); mpz_from_bin(bytes_A, len_A, A); mpz_t u; mpz_init(u); mpz_t B; mpz_init(B); mpz_t S; mpz_init(S); mpz_t b; mpz_init(b); mpz_t k; mpz_init(k); mpz_t tmp1; mpz_init(tmp1); mpz_t tmp2; mpz_init(tmp2); mpz_t tmp3; mpz_init(tmp3); // clang-format on size_t ulen = strlen(username) + 1; NGConstant *ng = new_ng(ng_type, n_hex, g_hex); struct SRPVerifier *ver = 0; *len_B = 0; *bytes_B = 0; if (!ng) goto cleanup_and_exit; ver = (struct SRPVerifier *)srp_alloc(sizeof(struct SRPVerifier)); if (!ver) goto cleanup_and_exit; if (init_random() != SRP_OK) { /* Only happens once */ srp_free(ver); ver = 0; goto cleanup_and_exit; } ver->username = (char *)srp_alloc(ulen); ver->hash_alg = alg; ver->ng = ng; if (!ver->username) { srp_free(ver); ver = 0; goto cleanup_and_exit; } memcpy((char *)ver->username, username, ulen); ver->authenticated = 0; /* SRP-6a safety check */ mpz_mod(tmp1, A, ng->N); if (mpz_sgn(tmp1) != 0) { if (bytes_b) { mpz_from_bin(bytes_b, len_b, b); } else { if (!mpz_fill_random(b)) goto ver_cleanup_and_exit; } if (!H_nn(k, alg, ng->N, ng->N, ng->g)) goto ver_cleanup_and_exit; /* B = kv + g^b */ mpz_mulm(tmp1, k, v, ng->N, tmp3); mpz_powm(tmp2, ng->g, b, ng->N); mpz_addm(B, tmp1, tmp2, ng->N, tmp3); if (!H_nn(u, alg, ng->N, A, B)) goto ver_cleanup_and_exit; srp_dbg_num(u, "Server calculated u: "); /* S = (A *(v^u)) ^ b */ mpz_powm(tmp1, v, u, ng->N); mpz_mulm(tmp2, A, tmp1, ng->N, tmp3); mpz_powm(S, tmp2, b, ng->N); if (!hash_num(alg, S, ver->session_key)) goto ver_cleanup_and_exit; if (!calculate_M( alg, ng, ver->M, username, bytes_s, len_s, A, B, ver->session_key)) { goto ver_cleanup_and_exit; } if (!calculate_H_AMK(alg, ver->H_AMK, A, ver->M, ver->session_key)) { goto ver_cleanup_and_exit; } *len_B = mpz_num_bytes(B); *bytes_B = (unsigned char *)srp_alloc(*len_B); if (!*bytes_B) { *len_B = 0; goto ver_cleanup_and_exit; } mpz_to_bin(B, *bytes_B); ver->bytes_B = *bytes_B; } else { srp_free(ver); ver = 0; } cleanup_and_exit: mpz_clear(v); mpz_clear(A); mpz_clear(u); mpz_clear(k); mpz_clear(B); mpz_clear(S); mpz_clear(b); mpz_clear(tmp1); mpz_clear(tmp2); mpz_clear(tmp3); return ver; ver_cleanup_and_exit: srp_free(ver->username); srp_free(ver); ver = 0; goto cleanup_and_exit; }