source: trunk/src/sh_srp.c@ 446

Last change on this file since 446 was 225, checked in by katerina, 16 years ago

Fix for ticket #150 (flawed input verification in SRP). Release 2.5.4

File size: 16.5 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program 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. */
15/* */
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26
27#include "samhain.h"
28
29#ifdef USE_SRP_PROTOCOL
30
31#if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER))
32
33#include "sh_tiger.h"
34#include "sh_mem.h"
35#include "sh_utils.h"
36#include "sh_srp.h"
37
38#if !defined(HAVE_LIBGMP) || !defined(HAVE_GMP_H)
39#include "bignum.h"
40#else
41
42#include <gmp.h>
43
44#define BIG_OK 0
45#define bigerr_t int
46int big_errno = BIG_OK;
47
48#define bignum MP_INT
49
50inline
51int big_create (bignum * a)
52{
53 mpz_init(a);
54 return 0;
55}
56
57inline
58int big_zerop (bignum * a)
59{
60 mpz_t b;
61 int i;
62 mpz_init_set_str(b, "0", 10);
63 i = mpz_cmp(a, b);
64 mpz_clear(b);
65 if (i)
66 return 0;
67 else
68 return 1;
69}
70
71inline
72int big_trunc (bignum * a, bignum * b, bignum * q, bignum *r)
73{
74 mpz_tdiv_qr(q, r, a, b);
75 return 0;
76}
77
78inline
79int big_exptmod (bignum * a, bignum * b, bignum * c, bignum *d)
80{
81 mpz_powm(d, a, b, c);
82 return 0;
83}
84
85char * get_str_internal = NULL;
86int siz_str_internal = 0;
87
88inline
89char * big_string (bignum * a, int base)
90{
91 char * str = NULL;
92 int size;
93 int i;
94 str = mpz_get_str (str, base, a);
95
96 if (get_str_internal == NULL)
97 {
98 get_str_internal = malloc(512); /* only once */
99 if (get_str_internal)
100 {
101 siz_str_internal = 512;
102 }
103 else
104 {
105 if (str != NULL)
106 free(str);
107 return 0;
108 }
109 get_str_internal[0] = '\0';
110 }
111
112 if (str != NULL)
113 {
114 size = strlen(str) + 1;
115 if (size > siz_str_internal)
116 get_str_internal = realloc (get_str_internal, size);
117 if (get_str_internal == NULL)
118 {
119 free(str);
120 return NULL;
121 }
122 siz_str_internal = size;
123 sl_strlcpy (get_str_internal, str, siz_str_internal);
124 for (i = 0; i < (size-1); ++i)
125 if (get_str_internal[i] >= 'a' && get_str_internal[i] <= 'f' )
126 get_str_internal[i] = get_str_internal[i] - 'a' + 'A';
127 free (str);
128 }
129 return get_str_internal;
130}
131
132inline
133int big_add(bignum * a, bignum * b, bignum * c)
134{
135 mpz_add(c, a, b);
136 return 0;
137}
138
139inline
140int big_sub(bignum * a, bignum * b, bignum * c)
141{
142 mpz_sub(c, a, b);
143 return 0;
144}
145
146inline
147int big_mul(bignum * a, bignum * b, bignum * c)
148{
149 mpz_mul(c, a, b);
150 return 0;
151}
152
153inline
154int big_greaterp(bignum * a, bignum * b)
155{
156 return mpz_cmp(a, b) > 0;
157}
158
159inline
160int big_set_big(bignum * a, bignum * b)
161{
162 mpz_set(b, a);
163 return 0;
164}
165
166
167inline
168int big_set_string(const char * str, int base, bignum * a)
169{
170 mpz_set_str (a, str, base);
171 return 0;
172}
173
174
175#define big_init_pkg() 0
176#define big_release_pkg()
177#define big_destroy mpz_clear
178
179/* #if defined(HAVE_LIBGMP)
180 */
181#endif
182
183#undef FIL__
184#define FIL__ _("sh_srp.c")
185
186typedef struct sh_srp_struc {
187 char x[KEY_LEN+1];
188 bignum a;
189 bignum p;
190 bignum g;
191} sh_srp_t;
192
193static sh_srp_t sh_srp;
194
195void sh_srp_x (char * salt, char * password)
196{
197
198 char *combi;
199 size_t len, l2;
200 register int i;
201 unsigned char * dez = NULL;
202 char hashbuf[KEYBUF_SIZE];
203
204 SL_ENTER(_("sh_srp_x"));
205
206 /* patch by Andreas Piesk
207 */
208 if (password == NULL)
209 dez = (unsigned char *) &(skey->pw[0]);
210 else
211 dez = (unsigned char *) password;
212
213 for (i = 0; i < PW_LEN; ++i)
214 {
215 skey->vernam[i] = (char)(*dez);
216 ++dez;
217 }
218 skey->vernam[PW_LEN] = '\0';
219
220 (void) sl_strlcpy (skey->vernam,
221 sh_tiger_hash(skey->vernam, TIGER_DATA, PW_LEN,
222 hashbuf, sizeof(hashbuf)),
223 KEY_LEN);
224 skey->vernam[KEY_LEN] = '\0';
225
226 len = sl_strlen(salt) + 1;
227 l2 = sl_strlen(skey->vernam);
228 if (sl_ok_adds(len, l2))
229 len += l2;
230
231 /* H(s,P)
232 */
233 combi = SH_ALLOC(len);
234 (void) sl_strlcpy (combi, salt, len);
235 (void) sl_strlcat (combi, skey->vernam, len);
236 (void) sl_strlcpy (sh_srp.x,
237 sh_tiger_hash(combi, TIGER_DATA,
238 (unsigned long) sl_strlen(combi),
239 hashbuf, sizeof(hashbuf)),
240 KEY_LEN+1);
241 SH_FREE (combi);
242
243 SL_RET0(_("sh_srp_x"));
244}
245
246char * sh_srp_M (char * x1, char * x2, char * x3, char * hash, size_t size)
247{
248 char *combi;
249 size_t len, l2, l3;
250
251 SL_ENTER(_("sh_srp_M"));
252
253 ASSERT_RET((x1 != NULL && x2 != NULL && x3 !=NULL),
254 _("x1 != NULL && x2 != NULL && x3 !=NULL"), NULL);
255
256 len = sl_strlen(x1) + 1;
257 l2 = sl_strlen(x2);
258 l3 = sl_strlen(x3);
259
260 if (sl_ok_adds(len, l2))
261 len += l2;
262 if (sl_ok_adds(len, l3))
263 len += l3;
264
265 /* H(x1,x2,x3)
266 */
267 combi = SH_ALLOC(len);
268 (void) sl_strlcpy (combi, x1, len);
269 (void) sl_strlcat (combi, x2, len);
270 (void) sl_strlcat (combi, x3, len);
271 (void) sh_tiger_hash(combi, TIGER_DATA, (unsigned long) (len-1),
272 hash, size);
273 SH_FREE (combi);
274
275 SL_RETURN(hash, _("sh_srp_M"));
276}
277
278
279void sh_srp_exit()
280{
281 SL_ENTER(_("sh_srp_exit"));
282 big_destroy(&sh_srp.g);
283 big_destroy(&sh_srp.p);
284 big_destroy(&sh_srp.a);
285
286 big_release_pkg();
287
288 big_errno = BIG_OK;
289 SL_RET0(_("sh_srp_exit"));
290}
291
292
293int sh_srp_init()
294{
295 bigerr_t res;
296 char modulus[80*4];
297
298 SL_ENTER(_("sh_srp_init"));
299
300 big_errno = BIG_OK;
301
302 res = big_init_pkg();
303
304 if (res == BIG_OK)
305 {
306 res = big_create(&sh_srp.p);
307 if (res == BIG_OK)
308 res = big_create(&sh_srp.g);
309 if (res == BIG_OK)
310 res = big_create(&sh_srp.a);
311 if (res == BIG_OK)
312 {
313 (void) sl_strlcpy(modulus, SRP_MODULUS_1024_1, sizeof(modulus));
314 (void) sl_strlcat(modulus, SRP_MODULUS_1024_2, sizeof(modulus));
315 (void) sl_strlcat(modulus, SRP_MODULUS_1024_3, sizeof(modulus));
316 (void) sl_strlcat(modulus, SRP_MODULUS_1024_4, sizeof(modulus));
317 }
318 if (res == BIG_OK)
319 res = big_set_string (modulus, 16, &sh_srp.p);
320 if (res == BIG_OK)
321 res = big_set_string (SRP_GENERATOR_1024, 16, &sh_srp.g);
322 if (res == BIG_OK)
323 {
324 SL_RETURN (0, _("sh_srp_init"));
325 }
326 else
327 sh_srp_exit();
328 }
329 SL_RETURN ((-1), _("sh_srp_init"));
330}
331
332
333int sh_srp_make_a ()
334{
335 UINT32 randl[6];
336 int i;
337 int res;
338 char hash[KEY_LEN+1];
339 char hashbuf[KEYBUF_SIZE];
340
341 SL_ENTER(_("sh_srp_make_a"));
342
343 for (i = 0; i < 6; ++i)
344 randl[i] = (UINT32) taus_get ();
345
346 (void) sl_strlcpy (hash,
347 sh_tiger_hash((char *)&randl[0], TIGER_DATA,
348 (unsigned long) 6*sizeof(UINT32),
349 hashbuf, sizeof(hashbuf)),
350 KEY_LEN+1);
351
352 hash[KEY_LEN] = '\0';
353
354 res = big_set_string (hash, 16, &sh_srp.a);
355 if (res == BIG_OK)
356 {
357 SL_RETURN((0), _("sh_srp_make_a"));
358 }
359 else
360 {
361 SL_RETURN((-1), _("sh_srp_make_a"));
362 }
363}
364
365/* return 0 if AB is NOT zero
366 */
367int sh_srp_check_zero (char * AB_str)
368{
369 bignum AB, q, r;
370 bigerr_t res;
371 int val;
372
373 SL_ENTER(_("sh_srp_check_zero"));
374
375 ASSERT_RET((AB_str != NULL), _("AB_str != NULL"), (-1));
376
377 res = big_create(&AB);
378 if (res == BIG_OK)
379 res = big_create(&q);
380 if (res == BIG_OK)
381 res = big_create(&r);
382
383 if (res == BIG_OK)
384 res = big_set_string (AB_str, 16, &AB);
385 if (res == BIG_OK)
386 res = big_trunc(&AB, &sh_srp.p, &q, &r); /* is last one the remainder ? */
387
388 if (res != BIG_OK) val = (-1);
389 else if (0 != big_zerop(&AB) ) val = (-1); /* 0 != (sign == 0) */
390 else if (0 != big_zerop(&r) ) val = (-1); /* 0 != (sign == 0) */
391 else val = 0;
392
393 big_destroy(&AB);
394 big_destroy(&q);
395 big_destroy(&r);
396
397 SL_RETURN((val), _("sh_srp_check_zero"));
398}
399
400#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
401
402
403char * sh_srp_A ()
404{
405 bignum A;
406 char *str;
407 char *combi;
408 bigerr_t res;
409
410 SL_ENTER(_("sh_srp_A"));
411
412 res = big_create(&A);
413
414 if (res == BIG_OK)
415 res = big_exptmod (&sh_srp.g, &sh_srp.a, &sh_srp.p, &A);
416
417 if (res == BIG_OK)
418 str = big_string (&A, 16);
419 else
420 str = NULL;
421
422 if (str != NULL)
423 combi = sh_util_strdup(str);
424 else
425 combi = NULL;
426
427 big_destroy(&A);
428 SL_RETURN(combi, _("sh_srp_A"));
429}
430
431/* #ifdef SH_WITH_CLIENT */
432#endif
433
434#ifdef SH_WITH_SERVER
435
436char * sh_srp_B (char * verifier)
437{
438 bignum B, v, t, dummy;
439 char *str;
440 char *combi;
441 bigerr_t res;
442
443 SL_ENTER(_("sh_srp_B"));
444
445 ASSERT_RET((verifier != NULL), _("verifier != NULL"), (NULL));
446
447 res = big_create(&dummy);
448
449 if (res == BIG_OK)
450 res = big_create(&t);
451 if (res == BIG_OK)
452 res = big_create(&v);
453 if (res == BIG_OK)
454 res = big_create(&B);
455
456 if (res == BIG_OK)
457 res = big_exptmod (&sh_srp.g, &sh_srp.a, &sh_srp.p, &t);
458
459 if (res == BIG_OK)
460 big_set_string (verifier, 16, &v);
461
462 if (res == BIG_OK)
463 res = big_add (&t, &v, &dummy);
464
465 if (res == BIG_OK)
466 {
467 if ( big_greaterp(&dummy, &sh_srp.p) )
468 res = big_sub(&dummy, &sh_srp.p, &B);
469 else
470 res = big_set_big(&dummy, &B);
471 }
472
473 if (res == BIG_OK)
474 str = big_string (&B, 16);
475 else
476 str = NULL;
477
478 if (str != NULL)
479 combi = sh_util_strdup(str);
480 else
481 combi = NULL;
482
483 big_destroy(&B);
484 big_destroy(&v);
485 big_destroy(&t);
486 big_destroy(&dummy);
487
488 SL_RETURN(combi, _("sh_srp_B"));
489}
490/* #ifdef SH_WITH_SERVER */
491#endif
492
493
494#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
495
496char * sh_srp_S_c (char * u_str, char * B_str)
497{
498 bignum u, B, x, t, base, z1, z2;
499 char *str;
500 char *combi;
501 bigerr_t res;
502
503 SL_ENTER(_("sh_srp_S_c"));
504
505 ASSERT_RET((u_str != NULL && B_str != NULL),
506 _("u_str != NULL && B_str != NULL"), (NULL));
507
508 big_errno = BIG_OK;
509
510 res = big_create(&z2);
511 if (res == BIG_OK)
512 res = big_create(&z1);
513 if (res == BIG_OK)
514 res = big_create(&base);
515 if (res == BIG_OK)
516 res = big_create(&t);
517 if (res == BIG_OK)
518 res = big_create(&x);
519 if (res == BIG_OK)
520 res = big_create(&B);
521 if (res == BIG_OK)
522 res = big_create(&u);
523
524 if (res == BIG_OK)
525 res = big_set_string (B_str, 16, &B);
526 if (res == BIG_OK)
527 res = big_set_string (sh_srp.x, 16, &x);
528 if (res == BIG_OK)
529 res = big_set_string (u_str, 16, &u);
530
531 /* the base (B - g^x)
532 */
533 if (res == BIG_OK)
534 res = big_exptmod (&sh_srp.g, &x, &sh_srp.p, &t);
535
536 if (res == BIG_OK)
537 {
538 if ( big_greaterp(&B, &t) != 0)
539 {
540 res = big_sub(&B, &t, &base);
541 }
542 else
543 {
544 res = big_add(&B, &sh_srp.p, &z2);
545 if (res == BIG_OK)
546 res = big_sub(&z2, &t, &base);
547 }
548 }
549
550 /* the exponent (a + ux)
551 */
552 if (res == BIG_OK)
553 res = big_mul (&u, &x, &t);
554 if (res == BIG_OK)
555 res = big_trunc(&t, &sh_srp.p, &z1, &z2); /* is last one the remainder ? */
556 if (res == BIG_OK)
557 res = big_add(&sh_srp.a, &z2, &z1);
558 if (res == BIG_OK)
559 {
560 if ( big_greaterp(&z1, &sh_srp.p) != 0)
561 res = big_sub(&z1, &sh_srp.p, &z2);
562 else
563 res = big_set_big(&z1, &z2);
564 }
565
566 if (res == BIG_OK)
567 res = big_exptmod (&base, &z2, &sh_srp.p, &t);
568
569 if (res == BIG_OK)
570 str = big_string (&t, 16);
571 else
572 str = NULL;
573
574 if (str != NULL)
575 combi = sh_util_strdup(str);
576 else
577 combi = NULL;
578
579 big_destroy(&z1);
580 big_destroy(&z2);
581 big_destroy(&base);
582 big_destroy(&t);
583 big_destroy(&x);
584 big_destroy(&B);
585 big_destroy(&u);
586
587 SL_RETURN(combi, _("sh_srp_S_c"));
588}
589
590/* #ifdef SH_WITH_CLIENT */
591#endif
592
593#ifdef SH_WITH_SERVER
594
595
596char * sh_srp_S_s (char * u_str, char * A_str, char * v_str)
597{
598 bignum u, A, v, t, base, z1, z2;
599 char *str;
600 char *combi;
601 bigerr_t res;
602
603 SL_ENTER(_("sh_srp_S_s"));
604
605 ASSERT_RET((u_str != NULL && A_str != NULL && v_str != NULL),
606 _("u_str != NULL && A_str != NULL && v_str != NULL"),
607 (NULL));
608
609 big_errno = BIG_OK;
610
611 res = big_create(&z2);
612 if (res == BIG_OK)
613 res = big_create(&z1);
614 if (res == BIG_OK)
615 res = big_create(&base);
616 if (res == BIG_OK)
617 res = big_create(&t);
618 if (res == BIG_OK)
619 res = big_create(&v);
620 if (res == BIG_OK)
621 res = big_create(&A);
622 if (res == BIG_OK)
623 res = big_create(&u);
624
625 if (res == BIG_OK)
626 res = big_set_string (A_str, 16, &A);
627 if (res == BIG_OK)
628 res = big_set_string (v_str, 16, &v);
629 if (res == BIG_OK)
630 res = big_set_string (u_str, 16, &u);
631
632 /* the base (Av^u)
633 */
634 if (res == BIG_OK)
635 res = big_exptmod (&v, &u, &sh_srp.p, &t);
636 if (res == BIG_OK)
637 res = big_mul (&A, &t, &z1);
638 if (res == BIG_OK)
639 res = big_trunc(&z1, &sh_srp.p, &z2, &base); /* is last the remainder ? */
640
641 if (res == BIG_OK)
642 res = big_exptmod (&base, &sh_srp.a, &sh_srp.p, &t);
643
644 if (res == BIG_OK)
645 str = big_string (&t, 16);
646 else
647 str = NULL;
648
649 if (str != NULL)
650 combi = sh_util_strdup(str);
651 else
652 combi = NULL;
653
654 big_destroy(&z1);
655 big_destroy(&z2);
656 big_destroy(&base);
657 big_destroy(&t);
658 big_destroy(&v);
659 big_destroy(&A);
660 big_destroy(&u);
661
662 SL_RETURN(combi, _("sh_srp_S_s"));
663}
664
665/* #ifdef SH_WITH_SERVER */
666#endif
667
668
669char * sh_srp_verifier (void)
670{
671 bignum x, v;
672 char *combi;
673 char *str;
674 bigerr_t res;
675
676 SL_ENTER(_("sh_srp_verifier"));
677
678 res = big_create(&x);
679 if (res == BIG_OK)
680 res = big_create(&v);
681
682 if (res == BIG_OK)
683 res = big_set_string (sh_srp.x, 16, &x);
684
685 if (res == BIG_OK)
686 res = big_exptmod (&sh_srp.g, &x, &sh_srp.p, &v);
687
688 if (res == BIG_OK)
689 str = big_string (&v, 16);
690 else
691 str = NULL;
692
693 if (str != NULL)
694 combi = sh_util_strdup(str);
695 else
696 combi = NULL;
697
698 big_destroy(&x);
699 big_destroy(&v);
700
701 SL_RETURN(combi, _("sh_srp_verifier"));
702}
703
704
705/* #if (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER)) */
706
707#endif
708
709/* #ifdef USE_SRP_PROTOCOL */
710
711#endif
712
713
714#ifdef SH_CUTEST
715#include "CuTest.h"
716
717void Test_srp (CuTest *tc)
718{
719#if defined(USE_SRP_PROTOCOL) && (defined (SH_WITH_CLIENT) || defined (SH_WITH_SERVER))
720
721 int result;
722 char modulus[80*4];
723 bignum a, b, c;
724 bigerr_t res;
725 char *str = NULL;
726
727 res = sh_srp_init();
728 CuAssertTrue(tc, res == 0);
729
730 (void) sl_strlcpy(modulus, SRP_MODULUS_1024_1, sizeof(modulus));
731 (void) sl_strlcat(modulus, SRP_MODULUS_1024_2, sizeof(modulus));
732 (void) sl_strlcat(modulus, SRP_MODULUS_1024_3, sizeof(modulus));
733 (void) sl_strlcat(modulus, SRP_MODULUS_1024_4, sizeof(modulus));
734
735 res = big_create(&a);
736 CuAssertTrue(tc, res == BIG_OK);
737
738 /* Check plain zero
739 */
740 result = sh_srp_check_zero ("0");
741 CuAssertTrue(tc, result != 0);
742
743 res = big_set_string ("0", 16, &a);
744 CuAssertTrue(tc, res == BIG_OK);
745
746 result = sh_srp_check_zero (big_string(&a, 16));
747 CuAssertTrue(tc, result != 0);
748
749 /* Check modulus (equals 0 % M)
750 */
751 result = sh_srp_check_zero (modulus);
752 CuAssertTrue(tc, result != 0);
753
754 res = big_set_string (modulus, 16, &a);
755 CuAssertTrue(tc, res == BIG_OK);
756
757 result = sh_srp_check_zero (big_string(&a, 16));
758 CuAssertTrue(tc, result != 0);
759
760 /* Check non-zero
761 */
762 modulus[0] = 'a';
763
764 result = sh_srp_check_zero (modulus);
765 CuAssertTrue(tc, result == 0);
766
767 res = big_set_string (modulus, 16, &a);
768 CuAssertTrue(tc, res == BIG_OK);
769
770 result = sh_srp_check_zero (big_string(&a, 16));
771 CuAssertTrue(tc, result == 0);
772
773 modulus[0] = 'f';
774
775 /* Check multiple of modulus
776 */
777 res = big_set_string (modulus, 16, &a);
778 CuAssertTrue(tc, res == BIG_OK);
779
780 res = big_create(&b);
781 CuAssertTrue(tc, res == BIG_OK);
782
783 res = big_create(&c);
784 CuAssertTrue(tc, res == BIG_OK);
785
786 res = big_set_string ("deadbeef", 16, &b);
787 CuAssertTrue(tc, res == BIG_OK);
788
789 res = big_mul (&a, &b, &c);
790 CuAssertTrue(tc, res == BIG_OK);
791
792 str = strdup(big_string (&c, 16));
793 CuAssertPtrNotNull(tc, str);
794
795 result = sh_srp_check_zero (str);
796 CuAssertTrue(tc, result != 0);
797
798#else
799 (void) tc; /* fix compiler warning */
800#endif
801 return;
802}
803#endif
804
805
806
Note: See TracBrowser for help on using the repository browser.