2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * GNUTLS-EXTRA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GNUTLS-EXTRA is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 #include "gnutls_int.h"
25 #include "gnutls_random.h"
26 #include "gnutls_hash_int.h"
27 #include "auth_srp_passwd.h"
28 #include "gnutls_srp.h"
29 #include <gnutls_errors.h>
31 /* x = SHA(<salt> | SHA(<username> | ":" | <raw password>)) */
33 static const char magic
[] = "";
35 char *crypt_srpsha1(const char *username
, const char *passwd
,
36 const char *salt
, GNUTLS_MPI g
, GNUTLS_MPI n
)
38 unsigned char *sp
, *spe
, r1
[MAX_HASH_SIZE
];
39 int salt_size
= strlen(salt
);
40 unsigned char *local_salt
, *v
;
42 GNUTLS_HASH_HANDLE h1
;
43 int vsize
, hash_len
= _gnutls_hash_get_algo_len(GNUTLS_MAC_SHA
);
46 int rsalt_size
, tmpsize
;
49 passwd_len
= strlen(passwd
); /* we do not want the null */
51 h1
= _gnutls_hash_init(GNUTLS_MAC_SHA
);
52 _gnutls_hash(h1
, (char *) username
, strlen(username
));
53 _gnutls_hash(h1
, ":", 1);
54 _gnutls_hash(h1
, (char *) passwd
, passwd_len
);
55 _gnutls_hash_deinit(h1
, r1
);
58 local_salt
= gnutls_malloc(salt_size
+ 1);
59 if (local_salt
==NULL
) {
63 strcpy((char *) local_salt
, salt
); /* Flawfinder: ignore */
65 sp
= index( local_salt
, ':'); /* move to salt - after verifier */
68 gnutls_free( local_salt
);
73 spe
= rindex(sp
, ':');
74 if (spe
==NULL
) { /* parse error */
77 len
= (ptrdiff_t)spe
- (ptrdiff_t)sp
;
79 rsalt_size
= _gnutls_sbase64_decode(sp
, len
, &csalt
);
82 gnutls_free(local_salt
);
86 h1
= _gnutls_hash_init(GNUTLS_MAC_SHA
);
89 gnutls_free(local_salt
);
92 _gnutls_hash(h1
, csalt
, rsalt_size
);
95 _gnutls_hash(h1
, r1
, hash_len
);
97 _gnutls_hash_deinit(h1
, r1
);
100 vsize
= _gnutls_srp_gx(r1
, hash_len
, &v
, g
, n
);
102 if (vsize
== -1 || v
== NULL
) {
104 gnutls_free(local_salt
);
108 if (_gnutls_sbase64_encode(v
, vsize
, &rtext
) < 0) {
110 gnutls_free(local_salt
);
116 tmpsize
= strlen(sp
) + strlen(rtext
) + strlen(magic
) + 1 + 1;
118 gnutls_malloc( tmpsize
);
121 gnutls_free(local_salt
);
124 sprintf(tmp
, "%s%s:%s", magic
, rtext
, sp
); /* Flawfinder: ignore */
127 gnutls_free(local_salt
);
132 /* salt here is the salt size */
133 char *crypt_srpsha1_wrapper(const char *username
, const char *pass_new
,
134 int salt
, GNUTLS_MPI g
, GNUTLS_MPI n
)
136 unsigned char *result
;
142 if (salt
> 50 || salt
<= 0)
143 return NULL
; /* wow that's pretty long salt */
145 rand
= gnutls_malloc(salt
);
146 if (rand
==NULL
|| _gnutls_get_random(rand
, salt
, GNUTLS_WEAK_RANDOM
) < 0) {
151 result_size
= _gnutls_sbase64_encode(rand
, salt
, &result
);
152 if (result_size
< 0) {
158 tcp
= gnutls_calloc(1, 1+ result_size
+ 1);
164 sprintf(tcp
, ":%s", result
); /* Flawfinder: ignore */
168 /* no longer need cleartext */
170 e
= crypt_srpsha1(username
, pass_new
, (const char *) tcp
, g
, n
);