srp 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }