srp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('openssl')
4
+ have_header("openssl/ssl.h")
5
+ have_library("ssl", "SSLv23_method")
6
+ create_makefile('srp/native')
@@ -0,0 +1,374 @@
1
+ #include <ruby.h>
2
+ #include "srp.h"
3
+
4
+ /* Helper function to convert a byte array to a hexadecimal string */
5
+ void bytes_to_hex(unsigned char *bytes, unsigned int len, char **hex)
6
+ {
7
+
8
+ char hex_str[]= "0123456789abcdef";
9
+ unsigned int i;
10
+
11
+ *hex = (char *)malloc(len * 2 + 1);
12
+ (*hex)[len * 2] = 0;
13
+
14
+ if (!hex)
15
+ return;
16
+
17
+ for (i = 0; i < len; i++) {
18
+ (*hex)[i * 2 + 0] = hex_str[bytes[i] >> 4 ];
19
+ (*hex)[i * 2 + 1] = hex_str[bytes[i] & 0x0F];
20
+ }
21
+
22
+ }
23
+
24
+ /* Helper function and macro to convert a hex string to a byte array */
25
+ #define digit_to_int(d) ((d) <= '9' ? (d) - '0' : (d) - 'a' + 10)
26
+
27
+ void hex_to_bytes(char* hex, unsigned char ** bytes) {
28
+
29
+ int i;
30
+ char a, b;
31
+
32
+ int hex_len = (int) strlen(hex);
33
+ int bin_len = hex_len / 2;
34
+
35
+ *bytes = (unsigned char*) malloc(bin_len);
36
+
37
+ for (i = 0; i < bin_len; ++i) {
38
+ a = hex[2 * i + 0]; b = hex[2 * i + 1];
39
+ (*bytes)[i] = (digit_to_int(a) << 4) | digit_to_int(b);
40
+ }
41
+
42
+ }
43
+
44
+ const char* get_as_string(VALUE self, char* ivar) {
45
+
46
+ VALUE val = rb_iv_get(self, ivar);
47
+ return StringValue(val);
48
+
49
+ }
50
+
51
+ const unsigned char* get_hex_as_bytes(VALUE self, char* ivar) {
52
+
53
+ const char* hex = get_as_string(self, ivar);
54
+ const unsigned char * bytes;
55
+ hex_to_bytes(hex, &bytes);
56
+
57
+ return bytes;
58
+
59
+ }
60
+
61
+ const unsigned char* hex_val_to_bytes(VALUE val) {
62
+
63
+ const char* str_val = StringValue(val);
64
+ const unsigned char * bytes;
65
+ hex_to_bytes(str_val, &bytes);
66
+
67
+ return bytes;
68
+
69
+ }
70
+
71
+ static VALUE csrp_verifier;
72
+ typedef struct SRPVerifier SRPVerifier;
73
+
74
+ SRP_HashAlgorithm unwrap_hash_fn(VALUE hash_fn) {
75
+ return (SRP_HashAlgorithm) NUM2INT(hash_fn);
76
+ }
77
+
78
+ SRP_NGType unwrap_ng_type(VALUE ng_type) {
79
+ return (SRP_NGType) NUM2INT(ng_type);
80
+ }
81
+
82
+ static VALUE csrp;
83
+ static VALUE csrp_client;
84
+ static VALUE csrp_server;
85
+
86
+ static VALUE client_initialize(VALUE self, VALUE hash_fn2, VALUE ng_type2)
87
+ {
88
+ SRP_HashAlgorithm hash_fn = SRP_SHA1;
89
+ SRP_NGType ng_type = SRP_NG_1024;
90
+
91
+ rb_iv_set(self, "@hash_fn", INT2NUM((int) hash_fn));
92
+ rb_iv_set(self, "@ng_type", INT2NUM((int) ng_type));
93
+
94
+ return self;
95
+ }
96
+
97
+ static VALUE client_set_salt(VALUE self, VALUE salt) {
98
+ rb_iv_set(self, "@salt", salt);
99
+ return self;
100
+ }
101
+
102
+ /* Create a salt+verification key for the user's password. The salt and
103
+ * key need to be computed at the time the user's password is set and
104
+ * must be stored by the server-side application for use during the
105
+ * authentication process.
106
+ */
107
+ static VALUE client_create_verifier(VALUE self, VALUE username_val, VALUE password_val) {
108
+
109
+ rb_iv_set(self, "@username", username_val);
110
+ rb_iv_set(self, "@password", password_val);
111
+
112
+ const char * username = StringValue(username_val);
113
+ const char * password = StringValue(password_val);
114
+
115
+ SRP_HashAlgorithm alg = unwrap_hash_fn(rb_iv_get(self, "@hash_fn"));
116
+ SRP_NGType ng_type = unwrap_ng_type(rb_iv_get(self, "@hash_fn"));
117
+
118
+ int len_s = 0;
119
+ int len_v = 0;
120
+
121
+ const unsigned char * bytes_v = 0;
122
+
123
+ const unsigned char* bytes_s = get_hex_as_bytes(self, "@salt");
124
+
125
+ srp_create_salted_verification_key( alg, ng_type, username,
126
+ (const unsigned char *)password,
127
+ strlen(password), bytes_s,
128
+ &bytes_v, &len_v,
129
+ NULL, NULL );
130
+
131
+ char * verifier_hex;
132
+ bytes_to_hex(bytes_v, len_v, &verifier_hex);
133
+ VALUE verifier = rb_str_new((const char*) verifier_hex, strlen(verifier_hex));
134
+ rb_iv_set(self, "@verifier", verifier);
135
+
136
+ return self;
137
+
138
+ }
139
+
140
+ static VALUE client_start_authentication(VALUE self) {
141
+
142
+ struct SRPUser * usr;
143
+
144
+ const char * username = get_as_string(self, "@username");
145
+ const char * password = get_as_string(self, "@password");
146
+
147
+ SRP_HashAlgorithm alg = unwrap_hash_fn(rb_iv_get(self, "@hash_fn"));
148
+ SRP_NGType ng_type = unwrap_ng_type(rb_iv_get(self, "@hash_fn"));
149
+
150
+ /* Begin authentication process */
151
+ usr = srp_user_new( alg, ng_type, username,
152
+ (const unsigned char *)password,
153
+ strlen(password), NULL, NULL );
154
+
155
+
156
+ const char * auth_username = 0;
157
+ const unsigned char * bytes_A = 0;
158
+ int len_A = 0;
159
+
160
+ srp_user_start_authentication( usr, &auth_username, &bytes_A, &len_A );
161
+
162
+ char * A_hex;
163
+ bytes_to_hex(bytes_A, len_A, &A_hex);
164
+ VALUE A = rb_str_new((const char*) A_hex, strlen(A_hex));
165
+ rb_iv_set(self, "@A", A);
166
+
167
+ return self;
168
+
169
+ }
170
+
171
+ static VALUE client_process_challenge(VALUE self, VALUE B) {
172
+
173
+ struct SRPUser * usr;
174
+
175
+ SRP_HashAlgorithm alg = unwrap_hash_fn(rb_iv_get(self, "@hash_fn"));
176
+ SRP_NGType ng_type = unwrap_ng_type(rb_iv_get(self, "@hash_fn"));
177
+
178
+ // Get username and password and convert to char*
179
+ const char * username = get_as_string(self, "@username");
180
+ const char * password = get_as_string(self, "@password");
181
+
182
+ // Get salt and convert to byte array
183
+ const unsigned char* bytes_s = get_hex_as_bytes(self, "@salt");
184
+ int len_s = (int) sizeof(bytes_s);
185
+
186
+ // Get B and convert to byte array
187
+ const unsigned char* bytes_B = hex_val_to_bytes(B);
188
+ int len_B = (int) sizeof(bytes_B);
189
+
190
+ // Build user
191
+ usr = srp_user_new( alg, ng_type, username,
192
+ (const unsigned char *)password,
193
+ strlen(password), NULL, NULL );
194
+
195
+ int len_M;
196
+ const unsigned char * bytes_M;
197
+
198
+ /* Host -> User: (bytes_s, bytes_B) */
199
+ srp_user_process_challenge( usr, bytes_s, len_s, bytes_B, len_B, &bytes_M, &len_M );
200
+
201
+ if ( !bytes_M ) {
202
+ printf("User SRP-6a safety check violation!\n");
203
+ return Qfalse;
204
+ }
205
+
206
+ char * M_hex;
207
+ bytes_to_hex(bytes_M, len_M, &M_hex);
208
+ VALUE M = rb_str_new((const char*) M_hex, strlen(M_hex));
209
+ rb_iv_set(self, "@M", M);
210
+
211
+ return self;
212
+
213
+ }
214
+
215
+ static VALUE server_initialize(VALUE self, VALUE hash_fn2, VALUE ng_type2)
216
+ {
217
+
218
+ if (1) {
219
+
220
+ SRP_HashAlgorithm hash_fn = SRP_SHA1;
221
+ SRP_NGType ng_type = SRP_NG_1024;
222
+
223
+ rb_iv_set(self, "@hash_fn", INT2NUM((int) hash_fn));
224
+ rb_iv_set(self, "@ng_type", INT2NUM((int) ng_type));
225
+
226
+ } else {
227
+
228
+ rb_iv_set(self, "@hash_fn", hash_fn2);
229
+ rb_iv_set(self, "@ng_type", ng_type2);
230
+
231
+ }
232
+
233
+ return self;
234
+ }
235
+
236
+ /* Set username, salt and verifier */
237
+ static VALUE server_set_credentials(VALUE self, VALUE username, VALUE salt_hex, VALUE verifier_hex)
238
+ {
239
+
240
+ rb_iv_set(self, "@username", username);
241
+ rb_iv_set(self, "@salt", salt_hex);
242
+ rb_iv_set(self, "@verifier", verifier_hex);
243
+
244
+ return self;
245
+ }
246
+
247
+ static VALUE server_start_authentication(VALUE self, VALUE A) {
248
+
249
+ struct SRPVerifier * ver;
250
+
251
+ SRP_HashAlgorithm alg = unwrap_hash_fn(rb_iv_get(self, "@hash_fn"));
252
+ SRP_NGType ng_type = unwrap_ng_type(rb_iv_get(self, "@ng_type"));
253
+
254
+ // Get username from instance
255
+ VALUE username_val = get_as_string(self, "@username");
256
+ const char* username = StringValue(username_val);
257
+
258
+ // Get hex salt and convert to bytes
259
+ const unsigned char* bytes_s = get_hex_as_bytes(self, "@salt");
260
+ int len_s = (int) sizeof(bytes_s);
261
+
262
+ // Get hex verifier and convert to bytes
263
+ const unsigned char* bytes_v = get_hex_as_bytes(self, "@verifier");
264
+ int len_v = (int) sizeof(bytes_v);
265
+
266
+ // Convert client A value to bytes
267
+ const unsigned char* bytes_A = hex_val_to_bytes(A);
268
+ int len_A = (int) sizeof(bytes_A);
269
+
270
+ // Create buffer for server B value
271
+ const unsigned char * bytes_B;
272
+ int len_B = 0;
273
+
274
+ /* User -> Host: (username, bytes_A) */
275
+ ver = srp_verifier_new(alg, ng_type, username, bytes_s, len_s, bytes_v, len_v,
276
+ bytes_A, len_A, &bytes_B, &len_B, NULL, NULL);
277
+
278
+ // Store the
279
+ char * B_hex;
280
+ bytes_to_hex(bytes_B, len_B, &B_hex);
281
+ VALUE B = rb_str_new((const char*) B_hex, strlen(B_hex));
282
+ rb_iv_set(self, "@B", B);
283
+
284
+ VALUE verifier = Data_Wrap_Struct(csrp_verifier, 0, free, ver);
285
+
286
+ rb_iv_set(self, "@verifier", verifier);
287
+
288
+ }
289
+
290
+ static VALUE server_verify_session(VALUE self, VALUE M) {
291
+
292
+ VALUE verifier = rb_iv_get(self, "@verifier");
293
+
294
+ struct SRPVerifier * ver;
295
+ Data_Get_Struct(verifier, SRPVerifier, ver);
296
+
297
+ // Convert client M value to bytes
298
+ const unsigned char* bytes_M = hex_val_to_bytes(M);
299
+
300
+ // Create buffer for H AMK
301
+ const unsigned char *bytes_HAMK;
302
+
303
+ // User -> Host: (bytes_M)
304
+ srp_verifier_verify_session( ver, bytes_M, &bytes_HAMK );
305
+
306
+ if ( !bytes_HAMK ) {
307
+ printf("User authentication failed!\n");
308
+ return Qfalse;
309
+ }
310
+
311
+ char * HAMK_hex;
312
+ bytes_to_hex(bytes_HAMK, (int) sizeof(bytes_HAMK), &HAMK_hex);
313
+ VALUE HAMK = rb_str_new((const char*) HAMK_hex, strlen(HAMK_hex));
314
+ rb_iv_set(self, "@HAMK", HAMK);
315
+
316
+ return self;
317
+
318
+ }
319
+
320
+ static VALUE csrp_test(VALUE self) {
321
+ /*
322
+
323
+ // Host -> User: (HAMK)
324
+ srp_user_verify_session( usr, bytes_HAMK );
325
+
326
+ if ( !srp_user_is_authenticated(usr) ) {
327
+ printf("Server authentication failed!\n");
328
+ goto auth_failed;
329
+ }
330
+
331
+ return Qtrue;
332
+
333
+ auth_failed:
334
+ srp_verifier_delete( ver );
335
+ srp_user_delete( usr );
336
+
337
+ free( (char *)bytes_s );
338
+ free( (char *)bytes_v );
339
+
340
+ return Qfalse;
341
+ */
342
+ return Qnil;
343
+
344
+ };
345
+
346
+ void Init_native(void) {
347
+
348
+ csrp = rb_define_module("CSRP");
349
+
350
+ csrp_verifier = rb_define_class_under(csrp, "Verifier", rb_cObject);
351
+
352
+ csrp_client = rb_define_class_under(csrp, "Client", rb_cObject);
353
+
354
+ rb_define_method(csrp_client, "initialize", client_initialize, 2);
355
+ rb_define_method(csrp_client, "salt=", client_set_salt, 1);
356
+ rb_define_method(csrp_client, "create_verifier", client_create_verifier, 2);
357
+ rb_define_method(csrp_client, "start_authentication", client_start_authentication, 0);
358
+ rb_define_method(csrp_client, "process_challenge", client_process_challenge, 1);
359
+
360
+ rb_attr(csrp_client, rb_intern("salt"), 1, 1, 1);
361
+ rb_attr(csrp_client, rb_intern("verifier"), 1, 1, 1);
362
+ rb_attr(csrp_client, rb_intern("A"), 1, 1, 1);
363
+ rb_attr(csrp_client, rb_intern("M"), 1, 1, 1);
364
+
365
+ csrp_server = rb_define_class_under(csrp, "Server", rb_cObject);
366
+
367
+ rb_define_method(csrp_server, "initialize", server_initialize, 2);
368
+ rb_define_method(csrp_server, "set_credentials", server_set_credentials, 3);
369
+ rb_define_method(csrp_server, "start_authentication", server_start_authentication, 1);
370
+ rb_define_method(csrp_server, "verify_session", server_verify_session, 1);
371
+ rb_attr(csrp_server, rb_intern("B"), 1, 1, 1);
372
+ rb_attr(csrp_server, rb_intern("HAMK"), 1, 1, 1);
373
+
374
+ }
@@ -0,0 +1,900 @@
1
+ /*
2
+ * Secure Remote Password 6a implementation
3
+ * Copyright (c) 2010 Tom Cocagne. All rights reserved.
4
+ * https://github.com/cocagne/csrp
5
+ *
6
+ * The MIT License (MIT)
7
+ *
8
+ * Copyright (c) 2013 Tom Cocagne
9
+ *
10
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
11
+ * this software and associated documentation files (the "Software"), to deal in
12
+ * the Software without restriction, including without limitation the rights to
13
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14
+ * of the Software, and to permit persons to whom the Software is furnished to do
15
+ * so, subject to the following conditions:
16
+ *
17
+ * The above copyright notice and this permission notice shall be included in all
18
+ * copies or substantial portions of the Software.
19
+ *
20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ *
28
+ */
29
+
30
+ #ifdef WIN32
31
+ #include <Wincrypt.h>
32
+ #else
33
+ #include <sys/time.h>
34
+ #endif
35
+
36
+ #include <stdlib.h>
37
+ #include <string.h>
38
+ #include <stdio.h>
39
+
40
+ #include "srp.h"
41
+
42
+ static int g_initialized = 0;
43
+
44
+ typedef struct
45
+ {
46
+ BIGNUM * N;
47
+ BIGNUM * g;
48
+ } NGConstant;
49
+
50
+ struct NGHex
51
+ {
52
+ const char * n_hex;
53
+ const char * g_hex;
54
+ };
55
+
56
+ /* All constants here were pulled from Appendix A of RFC 5054 */
57
+ static struct NGHex global_Ng_constants[] = {
58
+ { /* 1024 */
59
+ "EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496"
60
+ "EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8E"
61
+ "F4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA"
62
+ "9AFD5138FE8376435B9FC61D2FC0EB06E3",
63
+ "2"
64
+ },
65
+ { /* 2048 */
66
+ "AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4"
67
+ "A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF60"
68
+ "95179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF"
69
+ "747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B907"
70
+ "8717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB37861"
71
+ "60279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DB"
72
+ "FBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73",
73
+ "2"
74
+ },
75
+ { /* 4096 */
76
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
77
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
78
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
79
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
80
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
81
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
82
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
83
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
84
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
85
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
86
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
87
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
88
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
89
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
90
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
91
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
92
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
93
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
94
+ "FFFFFFFFFFFFFFFF",
95
+ "5"
96
+ },
97
+ { /* 8192 */
98
+ "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
99
+ "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
100
+ "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
101
+ "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
102
+ "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
103
+ "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
104
+ "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
105
+ "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
106
+ "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
107
+ "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
108
+ "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
109
+ "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
110
+ "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
111
+ "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
112
+ "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
113
+ "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
114
+ "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
115
+ "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
116
+ "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
117
+ "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
118
+ "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
119
+ "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
120
+ "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
121
+ "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
122
+ "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
123
+ "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
124
+ "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"
125
+ "6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA"
126
+ "3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C"
127
+ "5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
128
+ "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886"
129
+ "2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6"
130
+ "6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5"
131
+ "0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268"
132
+ "359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6"
133
+ "FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
134
+ "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
135
+ "13"
136
+ },
137
+ {0,0} /* null sentinel */
138
+ };
139
+
140
+
141
+ static NGConstant * new_ng( SRP_NGType ng_type, const char * n_hex, const char * g_hex )
142
+ {
143
+ NGConstant * ng = (NGConstant *) malloc( sizeof(NGConstant) );
144
+ ng->N = BN_new();
145
+ ng->g = BN_new();
146
+
147
+ if( !ng || !ng->N || !ng->g )
148
+ return 0;
149
+
150
+ if ( ng_type != SRP_NG_CUSTOM )
151
+ {
152
+ n_hex = global_Ng_constants[ ng_type ].n_hex;
153
+ g_hex = global_Ng_constants[ ng_type ].g_hex;
154
+ }
155
+
156
+ BN_hex2bn( &ng->N, n_hex );
157
+ BN_hex2bn( &ng->g, g_hex );
158
+
159
+ return ng;
160
+ }
161
+
162
+ static void delete_ng( NGConstant * ng )
163
+ {
164
+ if (ng)
165
+ {
166
+ BN_free( ng->N );
167
+ BN_free( ng->g );
168
+ ng->N = 0;
169
+ ng->g = 0;
170
+ free(ng);
171
+ }
172
+ }
173
+
174
+
175
+
176
+ typedef union
177
+ {
178
+ SHA_CTX sha;
179
+ SHA256_CTX sha256;
180
+ SHA512_CTX sha512;
181
+ } HashCTX;
182
+
183
+
184
+ struct SRPVerifier
185
+ {
186
+ SRP_HashAlgorithm hash_alg;
187
+ NGConstant *ng;
188
+
189
+ const char * username;
190
+ const unsigned char * bytes_B;
191
+ int authenticated;
192
+
193
+ unsigned char M [SHA512_DIGEST_LENGTH];
194
+ unsigned char H_AMK [SHA512_DIGEST_LENGTH];
195
+ unsigned char session_key [SHA512_DIGEST_LENGTH];
196
+ };
197
+
198
+ struct SRPUser
199
+ {
200
+ SRP_HashAlgorithm hash_alg;
201
+ NGConstant *ng;
202
+
203
+ BIGNUM *a;
204
+ BIGNUM *A;
205
+ BIGNUM *S;
206
+
207
+ const unsigned char * bytes_A;
208
+ int authenticated;
209
+
210
+ const char * username;
211
+ const unsigned char * password;
212
+ int password_len;
213
+
214
+ unsigned char M [SHA512_DIGEST_LENGTH];
215
+ unsigned char H_AMK [SHA512_DIGEST_LENGTH];
216
+ unsigned char session_key [SHA512_DIGEST_LENGTH];
217
+ };
218
+
219
+
220
+ static int hash_init( SRP_HashAlgorithm alg, HashCTX *c )
221
+ {
222
+ switch (alg)
223
+ {
224
+ case SRP_SHA1 : return SHA1_Init( &c->sha );
225
+ case SRP_SHA224: return SHA224_Init( &c->sha256 );
226
+ case SRP_SHA256: return SHA256_Init( &c->sha256 );
227
+ case SRP_SHA384: return SHA384_Init( &c->sha512 );
228
+ case SRP_SHA512: return SHA512_Init( &c->sha512 );
229
+ default:
230
+ return -1;
231
+ };
232
+ }
233
+ static int hash_update( SRP_HashAlgorithm alg, HashCTX *c, const void *data, size_t len )
234
+ {
235
+ switch (alg)
236
+ {
237
+ case SRP_SHA1 : return SHA1_Update( &c->sha, data, len );
238
+ case SRP_SHA224: return SHA224_Update( &c->sha256, data, len );
239
+ case SRP_SHA256: return SHA256_Update( &c->sha256, data, len );
240
+ case SRP_SHA384: return SHA384_Update( &c->sha512, data, len );
241
+ case SRP_SHA512: return SHA512_Update( &c->sha512, data, len );
242
+ default:
243
+ return -1;
244
+ };
245
+ }
246
+ static int hash_final( SRP_HashAlgorithm alg, HashCTX *c, unsigned char *md )
247
+ {
248
+ switch (alg)
249
+ {
250
+ case SRP_SHA1 : return SHA1_Final( md, &c->sha );
251
+ case SRP_SHA224: return SHA224_Final( md, &c->sha256 );
252
+ case SRP_SHA256: return SHA256_Final( md, &c->sha256 );
253
+ case SRP_SHA384: return SHA384_Final( md, &c->sha512 );
254
+ case SRP_SHA512: return SHA512_Final( md, &c->sha512 );
255
+ default:
256
+ return -1;
257
+ };
258
+ }
259
+ static unsigned char * hash( SRP_HashAlgorithm alg, const unsigned char *d, size_t n, unsigned char *md )
260
+ {
261
+ switch (alg)
262
+ {
263
+ case SRP_SHA1 : return SHA1( d, n, md );
264
+ case SRP_SHA224: return SHA224( d, n, md );
265
+ case SRP_SHA256: return SHA256( d, n, md );
266
+ case SRP_SHA384: return SHA384( d, n, md );
267
+ case SRP_SHA512: return SHA512( d, n, md );
268
+ default:
269
+ return 0;
270
+ };
271
+ }
272
+ static int hash_length( SRP_HashAlgorithm alg )
273
+ {
274
+ switch (alg)
275
+ {
276
+ case SRP_SHA1 : return SHA_DIGEST_LENGTH;
277
+ case SRP_SHA224: return SHA224_DIGEST_LENGTH;
278
+ case SRP_SHA256: return SHA256_DIGEST_LENGTH;
279
+ case SRP_SHA384: return SHA384_DIGEST_LENGTH;
280
+ case SRP_SHA512: return SHA512_DIGEST_LENGTH;
281
+ default:
282
+ return -1;
283
+ };
284
+ }
285
+
286
+
287
+ static BIGNUM * H_nn( SRP_HashAlgorithm alg, const BIGNUM * n1, const BIGNUM * n2 )
288
+ {
289
+ unsigned char buff[ SHA512_DIGEST_LENGTH ];
290
+ int len_n1 = BN_num_bytes(n1);
291
+ int len_n2 = BN_num_bytes(n2);
292
+ int nbytes = len_n1 + len_n2;
293
+ unsigned char * bin = (unsigned char *) malloc( nbytes );
294
+ if (!bin)
295
+ return 0;
296
+ BN_bn2bin(n1, bin);
297
+ BN_bn2bin(n2, bin + len_n1);
298
+ hash( alg, bin, nbytes, buff );
299
+ free(bin);
300
+ return BN_bin2bn(buff, hash_length(alg), NULL);
301
+ }
302
+
303
+ static BIGNUM * H_ns( SRP_HashAlgorithm alg, const BIGNUM * n, const unsigned char * bytes, int len_bytes )
304
+ {
305
+ unsigned char buff[ SHA512_DIGEST_LENGTH ];
306
+ int len_n = BN_num_bytes(n);
307
+ int nbytes = len_n + len_bytes;
308
+ unsigned char * bin = (unsigned char *) malloc( nbytes );
309
+ if (!bin)
310
+ return 0;
311
+ BN_bn2bin(n, bin);
312
+ memcpy( bin + len_n, bytes, len_bytes );
313
+ hash( alg, bin, nbytes, buff );
314
+ free(bin);
315
+ return BN_bin2bn(buff, hash_length(alg), NULL);
316
+ }
317
+
318
+ static BIGNUM * calculate_x( SRP_HashAlgorithm alg, const BIGNUM * salt, const char * username, const unsigned char * password, int password_len )
319
+ {
320
+ unsigned char ucp_hash[SHA512_DIGEST_LENGTH];
321
+ HashCTX ctx;
322
+
323
+ hash_init( alg, &ctx );
324
+
325
+ hash_update( alg, &ctx, username, strlen(username) );
326
+ hash_update( alg, &ctx, ":", 1 );
327
+ hash_update( alg, &ctx, password, password_len );
328
+
329
+ hash_final( alg, &ctx, ucp_hash );
330
+
331
+ return H_ns( alg, salt, ucp_hash, hash_length(alg) );
332
+ }
333
+
334
+ static void update_hash_n( SRP_HashAlgorithm alg, HashCTX *ctx, const BIGNUM * n )
335
+ {
336
+ unsigned long len = BN_num_bytes(n);
337
+ unsigned char * n_bytes = (unsigned char *) malloc( len );
338
+ if (!n_bytes)
339
+ return;
340
+ BN_bn2bin(n, n_bytes);
341
+ hash_update(alg, ctx, n_bytes, len);
342
+ free(n_bytes);
343
+ }
344
+
345
+ static void hash_num( SRP_HashAlgorithm alg, const BIGNUM * n, unsigned char * dest )
346
+ {
347
+ int nbytes = BN_num_bytes(n);
348
+ unsigned char * bin = (unsigned char *) malloc( nbytes );
349
+ if(!bin)
350
+ return;
351
+ BN_bn2bin(n, bin);
352
+ hash( alg, bin, nbytes, dest );
353
+ free(bin);
354
+ }
355
+
356
+ static void calculate_M( SRP_HashAlgorithm alg, NGConstant *ng, unsigned char * dest, const char * I, const BIGNUM * s,
357
+ const BIGNUM * A, const BIGNUM * B, const unsigned char * K )
358
+ {
359
+ unsigned char H_N[ SHA512_DIGEST_LENGTH ];
360
+ unsigned char H_g[ SHA512_DIGEST_LENGTH ];
361
+ unsigned char H_I[ SHA512_DIGEST_LENGTH ];
362
+ unsigned char H_xor[ SHA512_DIGEST_LENGTH ];
363
+ HashCTX ctx;
364
+ int i = 0;
365
+ int hash_len = hash_length(alg);
366
+
367
+ hash_num( alg, ng->N, H_N );
368
+ hash_num( alg, ng->g, H_g );
369
+
370
+ hash(alg, (const unsigned char *)I, strlen(I), H_I);
371
+
372
+
373
+ for (i=0; i < hash_len; i++ )
374
+ H_xor[i] = H_N[i] ^ H_g[i];
375
+
376
+ hash_init( alg, &ctx );
377
+
378
+ hash_update( alg, &ctx, H_xor, hash_len );
379
+ hash_update( alg, &ctx, H_I, hash_len );
380
+ update_hash_n( alg, &ctx, s );
381
+ update_hash_n( alg, &ctx, A );
382
+ update_hash_n( alg, &ctx, B );
383
+ hash_update( alg, &ctx, K, hash_len );
384
+
385
+ hash_final( alg, &ctx, dest );
386
+ }
387
+
388
+ static void calculate_H_AMK( SRP_HashAlgorithm alg, unsigned char *dest, const BIGNUM * A, const unsigned char * M, const unsigned char * K )
389
+ {
390
+ HashCTX ctx;
391
+
392
+ hash_init( alg, &ctx );
393
+
394
+ update_hash_n( alg, &ctx, A );
395
+ hash_update( alg, &ctx, M, hash_length(alg) );
396
+ hash_update( alg, &ctx, K, hash_length(alg) );
397
+
398
+ hash_final( alg, &ctx, dest );
399
+ }
400
+
401
+
402
+ static void init_random()
403
+ {
404
+ if (g_initialized)
405
+ return;
406
+
407
+ #ifdef WIN32
408
+ HCRYPTPROV wctx;
409
+ #else
410
+ FILE *fp = 0;
411
+ #endif
412
+
413
+ unsigned char buff[64];
414
+
415
+
416
+ #ifdef WIN32
417
+
418
+ CryptAcquireContext(&wctx, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
419
+
420
+ CryptGenRandom(wctx, sizeof(buff), (BYTE*) buff);
421
+
422
+ CryptReleaseContext(wctx, 0);
423
+
424
+ g_initialized = 1;
425
+
426
+ #else
427
+ fp = fopen("/dev/urandom", "r");
428
+
429
+ if (fp)
430
+ {
431
+ fread(buff, sizeof(buff), 1, fp);
432
+ fclose(fp);
433
+ g_initialized = 1;
434
+ }
435
+ #endif
436
+
437
+ if (g_initialized)
438
+ RAND_seed( buff, sizeof(buff) );
439
+ }
440
+
441
+
442
+ /***********************************************************************************************************
443
+ *
444
+ * Exported Functions
445
+ *
446
+ ***********************************************************************************************************/
447
+
448
+ void srp_random_seed( const unsigned char * random_data, int data_length )
449
+ {
450
+ g_initialized = 1;
451
+
452
+ if (random_data)
453
+ RAND_seed( random_data, data_length );
454
+ }
455
+
456
+
457
+ void srp_create_salted_verification_key( SRP_HashAlgorithm alg,
458
+ SRP_NGType ng_type, const char * username,
459
+ const unsigned char * password, int len_password,
460
+ const unsigned char * bytes_s,
461
+ const unsigned char ** bytes_v, int * len_v,
462
+ const char * n_hex, const char * g_hex )
463
+ {
464
+ BIGNUM * s = BN_new();
465
+ BIGNUM * v = BN_new();
466
+ BIGNUM * x = 0;
467
+ BN_CTX * ctx = BN_CTX_new();
468
+ NGConstant * ng = new_ng( ng_type, n_hex, g_hex );
469
+
470
+ if( !s || !v || !ctx || !ng )
471
+ goto cleanup_and_exit;
472
+
473
+ BN_bin2bn(bytes_s, (int) sizeof(bytes_s), s);
474
+
475
+ init_random(); /* Only happens once */
476
+
477
+ x = calculate_x( alg, s, username, password, len_password );
478
+
479
+ if( !x )
480
+ goto cleanup_and_exit;
481
+
482
+ BN_mod_exp(v, ng->g, x, ng->N, ctx);
483
+
484
+ *len_v = BN_num_bytes(v);
485
+
486
+ *bytes_v = (const unsigned char *) malloc( *len_v );
487
+
488
+ if (!bytes_s || !bytes_v)
489
+ goto cleanup_and_exit;
490
+
491
+ BN_bn2bin(v, (unsigned char *) *bytes_v);
492
+
493
+ cleanup_and_exit:
494
+ delete_ng( ng );
495
+ BN_free(s);
496
+ BN_free(v);
497
+ BN_free(x);
498
+ BN_CTX_free(ctx);
499
+ }
500
+
501
+
502
+
503
+ /* Out: bytes_B, len_B.
504
+ *
505
+ * On failure, bytes_B will be set to NULL and len_B will be set to 0
506
+ */
507
+ struct SRPVerifier * srp_verifier_new( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char * username,
508
+ const unsigned char * bytes_s, int len_s,
509
+ const unsigned char * bytes_v, int len_v,
510
+ const unsigned char * bytes_A, int len_A,
511
+ const unsigned char ** bytes_B, int * len_B,
512
+ const char * n_hex, const char * g_hex )
513
+ {
514
+ BIGNUM *s = BN_bin2bn(bytes_s, len_s, NULL);
515
+ BIGNUM *v = BN_bin2bn(bytes_v, len_v, NULL);
516
+ BIGNUM *A = BN_bin2bn(bytes_A, len_A, NULL);
517
+ BIGNUM *u = 0;
518
+ BIGNUM *B = BN_new();
519
+ BIGNUM *S = BN_new();
520
+ BIGNUM *b = BN_new();
521
+ BIGNUM *k = 0;
522
+ BIGNUM *tmp1 = BN_new();
523
+ BIGNUM *tmp2 = BN_new();
524
+ BN_CTX *ctx = BN_CTX_new();
525
+ int ulen = strlen(username) + 1;
526
+ NGConstant *ng = new_ng( ng_type, n_hex, g_hex );
527
+ struct SRPVerifier *ver = 0;
528
+
529
+ *len_B = 0;
530
+ *bytes_B = 0;
531
+
532
+ if( !s || !v || !A || !B || !S || !b || !tmp1 || !tmp2 || !ctx || !ng )
533
+ goto cleanup_and_exit;
534
+
535
+ ver = (struct SRPVerifier *) malloc( sizeof(struct SRPVerifier) );
536
+
537
+ if (!ver)
538
+ goto cleanup_and_exit;
539
+
540
+ init_random(); /* Only happens once */
541
+
542
+ ver->username = (char *) malloc( ulen );
543
+ ver->hash_alg = alg;
544
+ ver->ng = ng;
545
+
546
+ if (!ver->username)
547
+ {
548
+ free(ver);
549
+ ver = 0;
550
+ goto cleanup_and_exit;
551
+ }
552
+
553
+ memcpy( (char*)ver->username, username, ulen );
554
+
555
+ ver->authenticated = 0;
556
+
557
+ /* SRP-6a safety check */
558
+ BN_mod(tmp1, A, ng->N, ctx);
559
+ if ( !BN_is_zero(tmp1) )
560
+ {
561
+ BN_rand(b, 256, -1, 0);
562
+
563
+ k = H_nn(alg, ng->N, ng->g);
564
+
565
+ /* B = kv + g^b */
566
+ BN_mul(tmp1, k, v, ctx);
567
+ BN_mod_exp(tmp2, ng->g, b, ng->N, ctx);
568
+ BN_add(B, tmp1, tmp2);
569
+
570
+ u = H_nn(alg, A, B);
571
+
572
+ /* S = (A *(v^u)) ^ b */
573
+ BN_mod_exp(tmp1, v, u, ng->N, ctx);
574
+ BN_mul(tmp2, A, tmp1, ctx);
575
+ BN_mod_exp(S, tmp2, b, ng->N, ctx);
576
+
577
+ hash_num(alg, S, ver->session_key);
578
+
579
+ calculate_M( alg, ng, ver->M, username, s, A, B, ver->session_key );
580
+ calculate_H_AMK( alg, ver->H_AMK, A, ver->M, ver->session_key );
581
+
582
+ *len_B = BN_num_bytes(B);
583
+ *bytes_B = malloc( *len_B );
584
+
585
+ if( !*bytes_B )
586
+ {
587
+ free( (void*) ver->username );
588
+ free( ver );
589
+ ver = 0;
590
+ *len_B = 0;
591
+ goto cleanup_and_exit;
592
+ }
593
+
594
+ BN_bn2bin( B, (unsigned char *) *bytes_B );
595
+
596
+ ver->bytes_B = *bytes_B;
597
+ }
598
+
599
+ cleanup_and_exit:
600
+ BN_free(s);
601
+ BN_free(v);
602
+ BN_free(A);
603
+ if (u) BN_free(u);
604
+ if (k) BN_free(k);
605
+ BN_free(B);
606
+ BN_free(S);
607
+ BN_free(b);
608
+ BN_free(tmp1);
609
+ BN_free(tmp2);
610
+ BN_CTX_free(ctx);
611
+
612
+ return ver;
613
+ }
614
+
615
+
616
+
617
+
618
+ void srp_verifier_delete( struct SRPVerifier * ver )
619
+ {
620
+ if (ver)
621
+ {
622
+ delete_ng( ver->ng );
623
+ free( (char *) ver->username );
624
+ free( (unsigned char *) ver->bytes_B );
625
+ memset(ver, 0, sizeof(*ver));
626
+ free( ver );
627
+ }
628
+ }
629
+
630
+
631
+
632
+ int srp_verifier_is_authenticated( struct SRPVerifier * ver )
633
+ {
634
+ return ver->authenticated;
635
+ }
636
+
637
+
638
+ const char * srp_verifier_get_username( struct SRPVerifier * ver )
639
+ {
640
+ return ver->username;
641
+ }
642
+
643
+
644
+ const unsigned char * srp_verifier_get_session_key( struct SRPVerifier * ver, int * key_length )
645
+ {
646
+ if (key_length)
647
+ *key_length = hash_length( ver->hash_alg );
648
+ return ver->session_key;
649
+ }
650
+
651
+
652
+ int srp_verifier_get_session_key_length( struct SRPVerifier * ver )
653
+ {
654
+ return hash_length( ver->hash_alg );
655
+ }
656
+
657
+
658
+ /* user_M must be exactly SHA512_DIGEST_LENGTH bytes in size */
659
+ void srp_verifier_verify_session( struct SRPVerifier * ver, const unsigned char * user_M, const unsigned char ** bytes_HAMK )
660
+ {
661
+ if ( memcmp( ver->M, user_M, hash_length(ver->hash_alg) ) == 0 )
662
+ {
663
+ ver->authenticated = 1;
664
+ *bytes_HAMK = ver->H_AMK;
665
+ }
666
+ else
667
+ *bytes_HAMK = NULL;
668
+ }
669
+
670
+ /*******************************************************************************/
671
+
672
+ struct SRPUser * srp_user_new( SRP_HashAlgorithm alg, SRP_NGType ng_type, const char * username,
673
+ const unsigned char * bytes_password, int len_password,
674
+ const char * n_hex, const char * g_hex )
675
+ {
676
+ struct SRPUser *usr = (struct SRPUser *) malloc( sizeof(struct SRPUser) );
677
+ int ulen = strlen(username) + 1;
678
+
679
+ if (!usr)
680
+ goto err_exit;
681
+
682
+ init_random(); /* Only happens once */
683
+
684
+ usr->hash_alg = alg;
685
+ usr->ng = new_ng( ng_type, n_hex, g_hex );
686
+
687
+ usr->a = BN_new();
688
+ usr->A = BN_new();
689
+ usr->S = BN_new();
690
+
691
+ if (!usr->ng || !usr->a || !usr->A || !usr->S)
692
+ goto err_exit;
693
+
694
+ usr->username = (const char *) malloc(ulen);
695
+ usr->password = (const unsigned char *) malloc(len_password);
696
+ usr->password_len = len_password;
697
+
698
+ if (!usr->username || !usr->password)
699
+ goto err_exit;
700
+
701
+ memcpy((char *)usr->username, username, ulen);
702
+ memcpy((char *)usr->password, bytes_password, len_password);
703
+
704
+ usr->authenticated = 0;
705
+
706
+ usr->bytes_A = 0;
707
+
708
+ return usr;
709
+
710
+ err_exit:
711
+ if (usr)
712
+ {
713
+ BN_free(usr->a);
714
+ BN_free(usr->A);
715
+ BN_free(usr->S);
716
+ if (usr->username)
717
+ free((void*)usr->username);
718
+ if (usr->password)
719
+ {
720
+ memset((void*)usr->password, 0, usr->password_len);
721
+ free((void*)usr->password);
722
+ }
723
+ free(usr);
724
+ }
725
+
726
+ return 0;
727
+ }
728
+
729
+
730
+
731
+ void srp_user_delete( struct SRPUser * usr )
732
+ {
733
+ if( usr )
734
+ {
735
+ BN_free( usr->a );
736
+ BN_free( usr->A );
737
+ BN_free( usr->S );
738
+
739
+ delete_ng( usr->ng );
740
+
741
+ memset((void*)usr->password, 0, usr->password_len);
742
+
743
+ free((char *)usr->username);
744
+ free((char *)usr->password);
745
+
746
+ if (usr->bytes_A)
747
+ free( (char *)usr->bytes_A );
748
+
749
+ memset(usr, 0, sizeof(*usr));
750
+ free( usr );
751
+ }
752
+ }
753
+
754
+
755
+
756
+ int srp_user_is_authenticated( struct SRPUser * usr)
757
+ {
758
+ return usr->authenticated;
759
+ }
760
+
761
+
762
+ const char * srp_user_get_username( struct SRPUser * usr )
763
+ {
764
+ return usr->username;
765
+ }
766
+
767
+
768
+
769
+ const unsigned char * srp_user_get_session_key( struct SRPUser * usr, int * key_length )
770
+ {
771
+ if (key_length)
772
+ *key_length = hash_length( usr->hash_alg );
773
+ return usr->session_key;
774
+ }
775
+
776
+
777
+ int srp_user_get_session_key_length( struct SRPUser * usr )
778
+ {
779
+ return hash_length( usr->hash_alg );
780
+ }
781
+
782
+
783
+
784
+ /* Output: username, bytes_A, len_A */
785
+ void srp_user_start_authentication( struct SRPUser * usr, const char ** username,
786
+ const unsigned char ** bytes_A, int * len_A )
787
+ {
788
+ BN_CTX *ctx = BN_CTX_new();
789
+
790
+ BN_rand(usr->a, 256, -1, 0);
791
+
792
+ BN_mod_exp(usr->A, usr->ng->g, usr->a, usr->ng->N, ctx);
793
+
794
+ BN_CTX_free(ctx);
795
+
796
+ *len_A = BN_num_bytes(usr->A);
797
+ *bytes_A = malloc( *len_A );
798
+
799
+ if (!*bytes_A)
800
+ {
801
+ *len_A = 0;
802
+ *bytes_A = 0;
803
+ *username = 0;
804
+ return;
805
+ }
806
+
807
+ BN_bn2bin( usr->A, (unsigned char *) *bytes_A );
808
+
809
+ usr->bytes_A = *bytes_A;
810
+ *username = usr->username;
811
+ }
812
+
813
+
814
+ /* Output: bytes_M. Buffer length is SHA512_DIGEST_LENGTH */
815
+ void srp_user_process_challenge( struct SRPUser * usr,
816
+ const unsigned char * bytes_s, int len_s,
817
+ const unsigned char * bytes_B, int len_B,
818
+ const unsigned char ** bytes_M, int * len_M )
819
+ {
820
+ BIGNUM *s = BN_bin2bn(bytes_s, len_s, NULL);
821
+ BIGNUM *B = BN_bin2bn(bytes_B, len_B, NULL);
822
+ BIGNUM *u = 0;
823
+ BIGNUM *x = 0;
824
+ BIGNUM *k = 0;
825
+ BIGNUM *v = BN_new();
826
+ BIGNUM *tmp1 = BN_new();
827
+ BIGNUM *tmp2 = BN_new();
828
+ BIGNUM *tmp3 = BN_new();
829
+ BN_CTX *ctx = BN_CTX_new();
830
+
831
+ *len_M = 0;
832
+ *bytes_M = 0;
833
+
834
+ if( !s || !B || !v || !tmp1 || !tmp2 || !tmp3 || !ctx )
835
+ goto cleanup_and_exit;
836
+
837
+ u = H_nn(usr->hash_alg, usr->A, B);
838
+
839
+ if (!u)
840
+ goto cleanup_and_exit;
841
+
842
+ x = calculate_x( usr->hash_alg, s, usr->username, usr->password, usr->password_len );
843
+
844
+ if (!x)
845
+ goto cleanup_and_exit;
846
+
847
+ k = H_nn(usr->hash_alg, usr->ng->N, usr->ng->g);
848
+
849
+ if (!k)
850
+ goto cleanup_and_exit;
851
+
852
+ /* SRP-6a safety check */
853
+ if ( !BN_is_zero(B) && !BN_is_zero(u) )
854
+ {
855
+ BN_mod_exp(v, usr->ng->g, x, usr->ng->N, ctx);
856
+
857
+ /* S = (B - k*(g^x)) ^ (a + ux) */
858
+ BN_mul(tmp1, u, x, ctx);
859
+ BN_add(tmp2, usr->a, tmp1); /* tmp2 = (a + ux) */
860
+ BN_mod_exp(tmp1, usr->ng->g, x, usr->ng->N, ctx);
861
+ BN_mul(tmp3, k, tmp1, ctx); /* tmp3 = k*(g^x) */
862
+ BN_sub(tmp1, B, tmp3); /* tmp1 = (B - K*(g^x)) */
863
+ BN_mod_exp(usr->S, tmp1, tmp2, usr->ng->N, ctx);
864
+
865
+ hash_num(usr->hash_alg, usr->S, usr->session_key);
866
+
867
+ calculate_M( usr->hash_alg, usr->ng, usr->M, usr->username, s, usr->A, B, usr->session_key );
868
+ calculate_H_AMK( usr->hash_alg, usr->H_AMK, usr->A, usr->M, usr->session_key );
869
+
870
+ *bytes_M = usr->M;
871
+ if (len_M)
872
+ *len_M = hash_length( usr->hash_alg );
873
+ }
874
+ else
875
+ {
876
+ *bytes_M = NULL;
877
+ if (len_M)
878
+ *len_M = 0;
879
+ }
880
+
881
+ cleanup_and_exit:
882
+
883
+ BN_free(s);
884
+ BN_free(B);
885
+ BN_free(u);
886
+ BN_free(x);
887
+ BN_free(k);
888
+ BN_free(v);
889
+ BN_free(tmp1);
890
+ BN_free(tmp2);
891
+ BN_free(tmp3);
892
+ BN_CTX_free(ctx);
893
+ }
894
+
895
+
896
+ void srp_user_verify_session( struct SRPUser * usr, const unsigned char * bytes_HAMK )
897
+ {
898
+ if ( memcmp( usr->H_AMK, bytes_HAMK, hash_length(usr->hash_alg) ) == 0 )
899
+ usr->authenticated = 1;
900
+ }