*** empty log message ***
[gnutls.git] / libextra / crypt_srpsha1.c
blob78d8764f05bbe4317eefeb783d3a0b787e32e558
1 /*
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"
23 #ifdef ENABLE_SRP
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;
41 int passwd_len;
42 GNUTLS_HASH_HANDLE h1;
43 int vsize, hash_len = _gnutls_hash_get_algo_len(GNUTLS_MAC_SHA);
44 opaque *tmp;
45 uint8 *rtext, *csalt;
46 int rsalt_size, tmpsize;
47 size_t len;
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) {
60 gnutls_assert();
61 return NULL;
63 strcpy((char *) local_salt, salt); /* Flawfinder: ignore */
65 sp = index( local_salt, ':'); /* move to salt - after verifier */
66 if (sp==NULL) {
67 gnutls_assert();
68 gnutls_free( local_salt);
69 return NULL;
71 sp++;
73 spe = rindex(sp, ':');
74 if (spe==NULL) { /* parse error */
75 len = strlen(sp);
76 } else
77 len = (ptrdiff_t)spe - (ptrdiff_t)sp;
79 rsalt_size = _gnutls_sbase64_decode(sp, len, &csalt);
80 if (rsalt_size < 0) {
81 gnutls_assert();
82 gnutls_free(local_salt);
83 return NULL;
86 h1 = _gnutls_hash_init(GNUTLS_MAC_SHA);
87 if (h1==NULL) {
88 gnutls_assert();
89 gnutls_free(local_salt);
90 return NULL;
92 _gnutls_hash(h1, csalt, rsalt_size);
93 gnutls_free(csalt);
95 _gnutls_hash(h1, r1, hash_len);
97 _gnutls_hash_deinit(h1, r1);
99 /* v = g^x mod n */
100 vsize = _gnutls_srp_gx(r1, hash_len, &v, g, n);
102 if (vsize == -1 || v == NULL) {
103 gnutls_assert();
104 gnutls_free(local_salt);
105 return NULL;
108 if (_gnutls_sbase64_encode(v, vsize, &rtext) < 0) {
109 gnutls_free(v);
110 gnutls_free(local_salt);
111 gnutls_assert();
112 return NULL;
114 gnutls_free(v);
116 tmpsize = strlen(sp) + strlen(rtext) + strlen(magic) + 1 + 1;
117 tmp =
118 gnutls_malloc( tmpsize);
119 if (tmp==NULL) {
120 gnutls_assert();
121 gnutls_free(local_salt);
122 return NULL;
124 sprintf(tmp, "%s%s:%s", magic, rtext, sp); /* Flawfinder: ignore */
126 gnutls_free(rtext);
127 gnutls_free(local_salt);
129 return tmp;
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;
137 char *tcp;
138 opaque *rand;
139 char *e = NULL;
140 int result_size;
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) {
147 gnutls_assert();
148 return NULL;
151 result_size = _gnutls_sbase64_encode(rand, salt, &result);
152 if (result_size < 0) {
153 gnutls_free(rand);
154 gnutls_assert();
155 return NULL;
158 tcp = gnutls_calloc(1, 1+ result_size + 1);
159 if (tcp==NULL) {
160 gnutls_assert();
161 gnutls_free(rand);
162 return NULL;
164 sprintf(tcp, ":%s", result); /* Flawfinder: ignore */
166 gnutls_free(result);
167 gnutls_free(rand);
168 /* no longer need cleartext */
170 e = crypt_srpsha1(username, pass_new, (const char *) tcp, g, n);
171 gnutls_free(tcp);
173 return e;
176 #endif