1 /* ============================================================
2 *
3 * This file is a part of KDE project
4 *
5 *
6 * Date : 2010-11-14
7 * Description : Yandex authentication module
8 *
9 * This is an Yandex implementation of RSA algorithm.
10 * It differs from the standard RSA and incompatible with it.
11 *
12 * Based on code parts from pegwit program written by George Barwood.
13 * This code is in the public domain; do with it what you wish.
14 *
15 * See links for more details:
16 * Author homepage
17 * http://www.george-barwood.pwp.blueyonder.co.uk/hp/
18 *
19 * Getting token for Yandex.Fotki web service
20 * http://api.yandex.ru/fotki/doc/overview/authorization-token.xml
21 *
22 * Yandex published source code
23 * http://download.yandex.ru/api-fotki/c-yamrsa.tar.gz
24 *
25 * Yandex company web site
26 * http://company.yandex.com/
27 *
28 * Included by Roman Tsisyk <roman at tsisyk dot com>
29 * All unneeded parts was commented out and can be removed
30 *
31 * ============================================================ */
32
33 #include "yandexrsa.h"
34
35 // C++ includes
36
37 #include <cstdlib> // std::size_t
38 #include <cstring>
39
40 namespace YandexAuth
41 {
42
43 static vlong modexp( const vlong& x, const vlong& e, const vlong& m ); // m must be odd
44 //static vlong gcd( const vlong &X, const vlong &Y ); // greatest common denominator
45 static vlong modinv( const vlong& a, const vlong& m ); // modular inverse
46
47 // VLONG.CPP -----------------------------------
48
49 class flex_unit // Provides storage allocation and index checking
50 {
51 public:
52
53 unsigned* a; // array of units
54 unsigned z; // units allocated
55
56 unsigned n; // used units (read-only)
57 flex_unit();
58 ~flex_unit();
59 void clear(); // set n to zero
60 unsigned get( unsigned i ) const; // get ith unsigned
61 void set( unsigned i, unsigned x ); // set ith unsigned
62 void reserve( unsigned x ); // storage hint
63
64 // Time critical routine
65 void fast_mul( flex_unit& x, flex_unit& y, unsigned n );
66 };
67
68 class vlong_value : public flex_unit
69 {
70 public:
71 unsigned share; // share count, used by vlong to delay physical copying
72 int is_zero() const;
73 int test( unsigned i ) const;
74 unsigned bits() const;
75 int cf( vlong_value& x ) const;
76 void shl();
77 void shr();
78 void shr( unsigned n );
79 void add( vlong_value& x );
80 void subtract( vlong_value& x );
81 void init( unsigned x );
82 void copy( vlong_value& x );
83 operator unsigned(); // Unsafe conversion to unsigned
84 vlong_value();
85 void mul( vlong_value& x, vlong_value& y );
86 void divide( vlong_value& x, vlong_value& y, vlong_value& rem );
87 };
88
get(unsigned i) const89 unsigned flex_unit::get( unsigned i ) const
90 {
91 if ( i >= n )
92 {
93 return 0;
94 }
95
96 return a[i];
97 }
98
clear()99 void flex_unit::clear()
100 {
101 n = 0;
102 }
103
flex_unit()104 flex_unit::flex_unit()
105 {
106 z = 0;
107 a = nullptr;
108 n = 0;
109 }
110
~flex_unit()111 flex_unit::~flex_unit()
112 {
113 unsigned i=z;
114
115 while (i)
116 {
117 i-=1; // burn
118 a[i] = 0;
119 }
120
121 delete [] a;
122 }
123
reserve(unsigned x)124 void flex_unit::reserve( unsigned x )
125 {
126 if (x > z)
127 {
128 unsigned* na = new unsigned[x];
129
130 for (unsigned i=0; i<n; i+=1)
131 {
132 na[i] = a[i];
133 }
134
135 delete [] a;
136 a = na;
137 z = x;
138 }
139 }
140
set(unsigned i,unsigned x)141 void flex_unit::set( unsigned i, unsigned x )
142 {
143 if ( i < n )
144 {
145 a[i] = x;
146
147 if (x==0) while (n && a[n-1]==0)
148 {
149 n-=1; // normalise
150 }
151 }
152 else if ( x )
153 {
154 reserve(i+1);
155
156 for (unsigned j=n; j<i; j+=1)
157 {
158 a[j] = 0;
159 }
160
161 a[i] = x;
162 n = i+1;
163 }
164 }
165
166 // Macros for doing double precision multiply
167 #define BPU ( 8*sizeof(unsigned) ) // Number of bits in an unsigned
168 #define lo(x) ( (x) & ((1<<(BPU/2))-1) ) // lower half of unsigned
169 #define hi(x) ( (x) >> (BPU/2) ) // upper half
170 #define lh(x) ( (x) << (BPU/2) ) // make upper half
171
fast_mul(flex_unit & x,flex_unit & y,unsigned keep)172 void flex_unit::fast_mul( flex_unit& x, flex_unit& y, unsigned keep )
173 {
174 // *this = (x*y) % (2**keep)
175 unsigned i,j,limit = (keep+BPU-1)/BPU; // size of result in words
176 reserve(limit);
177
178 for (i=0; i<limit; i+=1)
179 {
180 a[i] = 0;
181 }
182
183 unsigned min = x.n;
184
185 if (min>limit)
186 {
187 min = limit;
188 }
189
190 for (i=0; i<min; i+=1)
191 {
192 unsigned m = x.a[i];
193 unsigned c = 0; // carry
194 unsigned min = i+y.n;
195
196 if (min>limit)
197 {
198 min = limit;
199 }
200
201 for ( j=i; j<min; j+=1 )
202 {
203 // This is the critical loop
204 // Machine dependent code could help here
205 // c:a[j] = a[j] + c + m*y.a[j-i];
206 unsigned w, v = a[j], p = y.a[j-i];
207 v += c;
208 c = ( v < c );
209 w = lo(p)*lo(m);
210 v += w;
211 c += ( v < w );
212 w = lo(p)*hi(m);
213 c += hi(w);
214 w = lh(w);
215 v += w;
216 c += ( v < w );
217 w = hi(p)*lo(m);
218 c += hi(w);
219 w = lh(w);
220 v += w;
221 c += ( v < w );
222 c += hi(p) * hi(m);
223 a[j] = v;
224 }
225
226 while ( c && j<limit )
227 {
228 a[j] += c;
229 c = a[j] < c;
230 j += 1;
231 }
232 }
233
234 // eliminate unwanted bits
235 keep %= BPU;
236
237 if (keep)
238 {
239 a[limit-1] &= (1<<keep)-1;
240 }
241
242 // calculate n
243 while (limit && a[limit-1]==0)
244 {
245 limit-=1;
246 }
247
248 n = limit;
249 }
250
operator unsigned()251 vlong_value::operator unsigned()
252 {
253 return get(0);
254 }
255
is_zero() const256 int vlong_value::is_zero() const
257 {
258 return n==0;
259 }
260
test(unsigned i) const261 int vlong_value::test( unsigned i ) const
262 {
263 return ( get(i/BPU) & (1<<(i%BPU)) ) != 0;
264 }
265
bits() const266 unsigned vlong_value::bits() const
267 {
268 unsigned x = n*BPU;
269
270 while (x && test(x-1)==0)
271 {
272 x -= 1;
273 }
274
275 return x;
276 }
277
cf(vlong_value & x) const278 int vlong_value::cf( vlong_value& x ) const
279 {
280 if ( n > x.n )
281 {
282 return +1;
283 }
284
285 if ( n < x.n )
286 {
287 return -1;
288 }
289
290 unsigned i = n;
291
292 while (i)
293 {
294 i -= 1;
295
296 if ( get(i) > x.get(i) )
297 {
298 return +1;
299 }
300
301 if ( get(i) < x.get(i) )
302 {
303 return -1;
304 }
305 }
306
307 return 0;
308 }
309
shl()310 void vlong_value::shl()
311 {
312 unsigned carry = 0;
313 unsigned N = n; // necessary, since n can change
314
315 for (unsigned i=0; i<=N; i+=1)
316 {
317 unsigned u = get(i);
318 set(i,(u<<1)+carry);
319 carry = u>>(BPU-1);
320 }
321 }
322
shr()323 void vlong_value::shr()
324 {
325 unsigned carry = 0;
326 unsigned i=n;
327
328 while (i)
329 {
330 i -= 1;
331 unsigned u = get(i);
332 set(i,(u>>1)+carry);
333 carry = u<<(BPU-1);
334 }
335 }
336
shr(unsigned x)337 void vlong_value::shr( unsigned x )
338 {
339 unsigned delta = x/BPU;
340 x %= BPU;
341
342 for (unsigned i=0; i<n; i+=1)
343 {
344 unsigned u = get(i+delta);
345
346 if (x)
347 {
348 u >>= x;
349 u += get(i+delta+1) << (BPU-x);
350 }
351
352 set(i,u);
353 }
354 }
355
add(vlong_value & x)356 void vlong_value::add( vlong_value& x )
357 {
358 unsigned carry = 0;
359 unsigned max = n;
360
361 if (max<x.n)
362 {
363 max = x.n;
364 }
365
366 reserve(max);
367
368 for (unsigned i=0; i<max+1; i+=1)
369 {
370 unsigned u = get(i);
371 u = u + carry;
372 carry = ( u < carry );
373 unsigned ux = x.get(i);
374 u = u + ux;
375 carry += ( u < ux );
376 set(i,u);
377 }
378 }
379
subtract(vlong_value & x)380 void vlong_value::subtract( vlong_value& x )
381 {
382 unsigned carry = 0;
383 unsigned N = n;
384
385 for (unsigned i=0; i<N; i+=1)
386 {
387 unsigned ux = x.get(i);
388 ux += carry;
389
390 if ( ux >= carry )
391 {
392 unsigned u = get(i);
393 unsigned nu = u - ux;
394 carry = nu > u;
395 set(i,nu);
396 }
397 }
398 }
399
init(unsigned x)400 void vlong_value::init( unsigned x )
401 {
402 clear();
403 set(0,x);
404 }
405
copy(vlong_value & x)406 void vlong_value::copy( vlong_value& x )
407 {
408 clear();
409 unsigned i=x.n;
410
411 while (i)
412 {
413 i -= 1;
414 set( i, x.get(i) );
415 }
416 }
417
vlong_value()418 vlong_value::vlong_value()
419 {
420 share = 0;
421 }
422
mul(vlong_value & x,vlong_value & y)423 void vlong_value::mul( vlong_value& x, vlong_value& y )
424 {
425 fast_mul( x, y, x.bits()+y.bits() );
426 }
427
divide(vlong_value & x,vlong_value & y,vlong_value & rem)428 void vlong_value::divide( vlong_value& x, vlong_value& y, vlong_value& rem )
429 {
430 init(0);
431 rem.copy(x);
432 vlong_value m,s;
433 m.copy(y);
434 s.init(1);
435
436 while ( rem.cf(m) > 0 )
437 {
438 m.shl();
439 s.shl();
440 }
441
442 while ( rem.cf(y) >= 0 )
443 {
444 while ( rem.cf(m) < 0 )
445 {
446 m.shr();
447 s.shr();
448 }
449
450 rem.subtract( m );
451 add( s );
452 }
453 }
454
455 // Implementation of vlong
456
load(unsigned * a,unsigned n)457 void vlong::load( unsigned* a, unsigned n )
458 {
459 docopy();
460 value->clear();
461
462 for (unsigned i=0; i<n; i+=1)
463 {
464 value->set(i,a[i]);
465 }
466 }
467
store(unsigned * a,unsigned n) const468 void vlong::store( unsigned* a, unsigned n ) const
469 {
470 for (unsigned i=0; i<n; i+=1)
471 {
472 a[i] = value->get(i);
473 }
474 }
475
get_nunits() const476 unsigned vlong::get_nunits() const
477 {
478 return value->n;
479 }
480
bits() const481 unsigned vlong::bits() const
482 {
483 return value->bits();
484 }
485
docopy()486 void vlong::docopy()
487 {
488 if ( value->share )
489 {
490 value->share -= 1;
491 vlong_value* nv = new vlong_value;
492 nv->copy(*value);
493 value = nv;
494 }
495 }
496
cf(const vlong & x) const497 int vlong::cf( const vlong& x ) const
498 {
499 int neg = negative && !value->is_zero();
500 //int neg2 = x.negative && !x.value->is_zero();
501
502 if ( neg == (x.negative && !x.value->is_zero()) )
503 //if ( neg == neg2)
504 {
505 return value->cf( *x.value );
506 }
507
508 else if ( neg )
509 {
510 return -1;
511 }
512 else
513 {
514 return +1;
515 }
516 }
517
vlong(unsigned x)518 vlong::vlong (unsigned x)
519 {
520 value = new vlong_value;
521 negative = 0;
522 value->init(x);
523 }
524
vlong(const vlong & x)525 vlong::vlong ( const vlong& x ) // copy constructor
526 {
527 negative = x.negative;
528 value = x.value;
529 value->share += 1;
530 }
531
operator =(const vlong & x)532 vlong& vlong::operator =(const vlong& x)
533 {
534 if ( value->share )
535 {
536 value->share -=1;
537 }
538 else
539 {
540 delete value;
541 }
542
543 value = x.value;
544 value->share += 1;
545 negative = x.negative;
546 return *this;
547 }
548
~vlong()549 vlong::~vlong()
550 {
551 if ( value->share )
552 {
553 value->share -=1;
554 }
555 else
556 {
557 delete value;
558 }
559 }
560
operator unsigned()561 vlong::operator unsigned () // conversion to unsigned
562 {
563 return *value;
564 }
565
operator +=(const vlong & x)566 vlong& vlong::operator +=(const vlong& x)
567 {
568 if ( negative == x.negative )
569 {
570 docopy();
571 value->add( *x.value );
572 }
573 else if ( value->cf( *x.value ) >= 0 )
574 {
575 docopy();
576 value->subtract( *x.value );
577 }
578 else
579 {
580 vlong tmp = *this;
581 *this = x;
582 *this += tmp;
583 }
584
585 return *this;
586 }
587
operator -=(const vlong & x)588 vlong& vlong::operator -=(const vlong& x)
589 {
590 if ( negative != x.negative )
591 {
592 docopy();
593 value->add( *x.value );
594 }
595 else if ( value->cf( *x.value ) >= 0 )
596 {
597 docopy();
598 value->subtract( *x.value );
599 }
600 else
601 {
602 vlong tmp = *this;
603 *this = x;
604 *this -= tmp;
605 negative = 1 - negative;
606 }
607
608 return *this;
609 }
610
operator +(const vlong & x,const vlong & y)611 vlong operator +( const vlong& x, const vlong& y )
612 {
613 vlong result = x;
614 result += y;
615 return result;
616 }
617
operator -(const vlong & x,const vlong & y)618 vlong operator -( const vlong& x, const vlong& y )
619 {
620 vlong result = x;
621 result -= y;
622 return result;
623 }
624
operator *(const vlong & x,const vlong & y)625 vlong operator *( const vlong& x, const vlong& y )
626 {
627 vlong result;
628 result.value->mul( *x.value, *y.value );
629 result.negative = x.negative ^ y.negative;
630 return result;
631 }
632
operator /(const vlong & x,const vlong & y)633 vlong operator /( const vlong& x, const vlong& y )
634 {
635 vlong result;
636 vlong_value rem;
637 result.value->divide( *x.value, *y.value, rem );
638 result.negative = x.negative ^ y.negative;
639 return result;
640 }
641
642 #if defined(__DEBUG__)
print_vlong(const vlong_value & v,const char * name)643 void print_vlong( const vlong_value& v, const char* name )
644 {
645 printf("%s value(%d): ", name, v.n * sizeof(unsigned int));
646
647 for (int i = 0; i < v.n; ++i)
648 {
649 printf("%08X", v.a[i]);
650 }
651
652 printf("\n");
653 }
654 #endif
655
operator %(const vlong & x,const vlong & y)656 vlong operator %( const vlong& x, const vlong& y )
657 {
658 vlong result;
659 vlong_value divide;
660 divide.divide( *x.value, *y.value, *result.value );
661 result.negative = x.negative; // not sure about this?
662 return result;
663 }
664 /*
665 static vlong gcd( const vlong &X, const vlong &Y )
666 {
667 vlong x=X, y=Y;
668 while (1)
669 {
670 if ( y == (vlong)0 ) return x;
671 x = x % y;
672 if ( x == (vlong)0 ) return y;
673 y = y % x;
674 }
675 }
676 */
677
modinv(const vlong & a,const vlong & m)678 static vlong modinv( const vlong& a, const vlong& m ) // modular inverse
679 // returns i in range 1..m-1 such that i*a = 1 mod m
680 // a must be in range 1..m-1
681 {
682 vlong j=1,i=0,b=m,c=a,x,y;
683
684 while ( c != (vlong)0 )
685 {
686 x = b / c;
687 y = b - x*c;
688 b = c;
689 c = y;
690 y = j;
691 j = i - j*x;
692 i = y;
693 }
694
695 if ( i < (vlong)0 )
696 {
697 i += m;
698 }
699
700 return i;
701 }
702
703 class monty // class for montgomery modular exponentiation
704 {
705 vlong R,R1,m,n1;
706 vlong T,k; // work registers
707 unsigned N; // bits for R
708 void mul( vlong& x, const vlong& y );
709 public:
710 vlong exp( const vlong& x, const vlong& e );
711 monty( const vlong& M );
712 };
713
monty(const vlong & M)714 monty::monty( const vlong& M )
715 {
716 m = M;
717 N = 0;
718 R = 1;
719
720 while ( R < M )
721 {
722 R += R;
723 N += 1;
724 }
725
726 R1 = modinv( R-m, m );
727 n1 = R - modinv( m, R );
728 }
729
mul(vlong & x,const vlong & y)730 void monty::mul( vlong& x, const vlong& y )
731 {
732 // T = x*y;
733 T.value->fast_mul( *x.value, *y.value, N*2 );
734
735 // k = ( T * n1 ) % R;
736 k.value->fast_mul( *T.value, *n1.value, N );
737
738 // x = ( T + k*m ) / R;
739 x.value->fast_mul( *k.value, *m.value, N*2 );
740 x += T;
741 x.value->shr( N );
742
743 if (x>=m)
744 {
745 x -= m;
746 }
747 }
748
exp(const vlong & x,const vlong & e)749 vlong monty::exp( const vlong& x, const vlong& e )
750 {
751 vlong result = R-m, t = ( x * R ) % m;
752 unsigned bits = e.value->bits();
753 unsigned i = 0;
754
755 while (1)
756 {
757 if ( e.value->test(i) )
758 {
759 mul( result, t);
760 }
761
762 i += 1;
763
764 if ( i == bits )
765 {
766 break;
767 }
768
769 mul( t, t );
770 }
771
772 return ( result * R1 ) % m;
773 }
774
modexp(const vlong & x,const vlong & e,const vlong & m)775 static vlong modexp( const vlong& x, const vlong& e, const vlong& m )
776 {
777 monty me(m);
778 return me.exp( x,e );
779 }
780
781 // RSA.CPP -----------------------------------
782
encrypt(const vlong & plain)783 vlong public_key::encrypt( const vlong& plain )
784 {
785 #if defined(__DEBUG__)
786
787 if ( plain >= m )
788 {
789 printf("ERROR: plain too big for this key\n");
790 }
791
792 #endif
793 return modexp( plain, e, m );
794 }
795
796 /*
797 vlong private_key::decrypt( const vlong& cipher )
798 {
799 // Calculate values for performing decryption
800 // These could be cached, but the calculation is quite fast
801 vlong d = modinv( e, (p-(vlong)1)*(q-(vlong)1) );
802 vlong u = modinv( p, q );
803 vlong dp = d % (p-(vlong)1);
804 vlong dq = d % (q-(vlong)1);
805
806 // Apply chinese remainder theorem
807 vlong a = modexp( cipher % p, dp, p );
808 vlong b = modexp( cipher % q, dq, q );
809 if ( b < a ) b += q;
810 return a + p * ( ((b-a)*u) % q );
811 }
812
813 void vlong_pair_2_str (char *me_str,vlong &m,vlong &e)
814 {
815 const char *hex_str = "0123456789ABCDEF";
816
817 char tmp_str[MAX_CRYPT_BITS/2+1];
818
819 unsigned int x;
820 unsigned int me_len = 0;
821 unsigned int i;
822 unsigned int j;
823 vlong m1 = m;
824 vlong e1 = e;
825 vlong zero = 0;
826
827 i = 0;
828 while (m1 != zero)
829 {
830 x = m1 % (vlong) 16;
831 m1 = m1 / (vlong) 16;
832 tmp_str[i++] = hex_str[x];
833 }
834
835 for (j=0; j < i; ++j)
836 me_str[me_len++] = tmp_str[i-1-j];
837
838 me_str[me_len++] = '#';
839
840 i = 0;
841 while (e1 != zero)
842 {
843 x = e1 %(vlong)16;
844 e1 = e1 / (vlong)16;
845 tmp_str[i++] = hex_str[x];
846 }
847
848 for (j=0; j < i; ++j)
849 me_str[me_len++] = tmp_str[i-1-j];
850
851 me_str[me_len] = 0;
852 }
853 */
854
str_2_vlong_pair(const char * me_str,vlong & m,vlong & e)855 void str_2_vlong_pair (const char* me_str,vlong& m,vlong& e)
856 {
857 int i;
858 int dash_pos = 0;
859 m = 0;
860 e = 0;
861
862 int me_len = (int)strlen (me_str);
863
864 for (i = me_len-1; i>0; --i)
865 if (me_str[i] == '#')
866 {
867 dash_pos = i;
868 break;
869 }
870
871 if (dash_pos == 0)
872 {
873 return;
874 }
875
876
877 for (i = 0; i<dash_pos; ++i)
878 {
879 m = m * (vlong)16;
880
881 if (me_str[i] > '9')
882 {
883 m = m + (vlong) (me_str[i]-'A'+10);
884 }
885 else
886 {
887 m = m + (vlong) (me_str[i]-'0');
888 }
889 }
890
891 for (i = dash_pos+1; i<me_len; ++i)
892 {
893 e = e * (vlong)16;
894
895 if (me_str[i] > '9')
896 {
897 e = e + (vlong) (me_str[i]-'A'+10);
898 }
899 else
900 {
901 e = e + (vlong) (me_str[i]-'0');
902 }
903 }
904
905
906 }
907
908 /*
909 void private_key::MakeMeStr(char * me_str)
910 {
911 vlong_pair_2_str (me_str,m,e);
912 }
913
914 void private_key::MakePqStr(char * me_str)
915 {
916 vlong_pair_2_str (me_str,p,q);
917 }
918
919
920 void private_key::MakePq (const char *me_str)
921 {
922 str_2_vlong_pair (me_str,p,q);
923 {
924 m = p*q;
925 e = 50001; // must be odd since p-1 and q-1 are even
926 while ( gcd(p-(vlong)1,e) != (vlong)1 || gcd(q-(vlong)1,e) != (vlong)1 ) e += 2;
927 }
928
929 }
930 */
931
MakeMe(const char * me_str)932 void public_key::MakeMe(const char* me_str)
933 {
934 str_2_vlong_pair (me_str,m,e);
935 }
936
CCryptoProviderRSA()937 CCryptoProviderRSA::CCryptoProviderRSA()
938 {
939 }
940
~CCryptoProviderRSA()941 CCryptoProviderRSA::~CCryptoProviderRSA()
942 {
943 }
944
_rmemcpy(char * dst,const char * src,size_t size)945 void inline _rmemcpy (char* dst,const char* src,size_t size)
946 {
947 src += size;
948
949 while (size--)
950 {
951 *dst++ = *(--src);
952 }
953 }
954 /*
955 void CCryptoProviderRSA::GetBlockSize(int &enbs, int &debs)
956 {
957 enbs=0;
958 debs=0;
959 }
960 */
EncryptPortion(const char * pt,size_t pt_size,char * ct,size_t & ct_size)961 void CCryptoProviderRSA::EncryptPortion(const char* pt, size_t pt_size, char* ct, size_t& ct_size)
962 {
963 vlong plain, cipher;
964
965 const size_t bytes_per_unit = BPU / 8;
966
967 size_t padding = (pt_size & 3) ? (4 - (pt_size & 3)) : 0;
968 char tmp[MAX_CRYPT_BITS/4];
969
970 // ensure big-endianness
971 _rmemcpy(tmp, pt, pt_size);
972 memset(tmp + pt_size, 0, padding);
973 plain.load(reinterpret_cast<unsigned int*>(tmp), (int)(pt_size+padding) / bytes_per_unit);
974
975 cipher = prkface.encrypt(plain);
976 ct_size = cipher.get_nunits() * bytes_per_unit;
977
978 // ensure big-endianness
979 cipher.store(reinterpret_cast<unsigned int*>(tmp), (int)ct_size / bytes_per_unit);
980 _rmemcpy(ct, tmp, ct_size);
981 }
982
983 /*
984 void CCryptoProviderRSA::DecryptPortion(const char *ct, size_t ct_size, char *pt, size_t &pt_size)
985 {
986 vlong plain, cipher;
987
988 const size_t bytes_per_unit = BPU / 8;
989
990 char tmp[MAX_CRYPT_BITS/4];
991
992 // ensure big-endianness
993 _rmemcpy(tmp, ct, ct_size);
994
995 cipher.load((unsigned int*)tmp, (int)ct_size / bytes_per_unit);
996 plain = prkface.decrypt(cipher);
997
998 // ensure big-endianness
999 plain.store((unsigned int*)tmp, plain.get_nunits());
1000 _rmemcpy(pt, tmp, pt_size);
1001 }
1002 */
1003
ImportPublicKey(const char * pk)1004 void CCryptoProviderRSA::ImportPublicKey(const char* pk)
1005 {
1006 prkface.MakeMe(pk);
1007 }
1008
1009 /*
1010 void CCryptoProviderRSA::ImportPrivateKey(const char *pk)
1011 {
1012 prkface.MakePq(pk);
1013 }
1014
1015 void CCryptoProviderRSA::ExportPublicKey(char *pk)
1016 {
1017 prkface.MakeMeStr(pk);
1018 }
1019
1020 void CCryptoProviderRSA::ExportPrivateKey(char *pk)
1021 {
1022 prkface.MakePqStr(pk);
1023 }
1024
1025 #if defined(__DEBUG__)
1026 void printbuf(const char * buf, int size)
1027 {
1028 for(const char * p = buf; p < buf + size; ++p)
1029 {
1030 printf("%02X", *p & 0x000000ff);
1031 }
1032 printf("\n");
1033 }
1034 #endif
1035 */
1036
Encrypt(const char * inbuf,size_t in_size,char * outbuf,size_t & out_size)1037 void CCryptoProviderRSA::Encrypt(const char* inbuf, size_t in_size,char* outbuf, size_t& out_size)
1038 {
1039 size_t i,cp_size;
1040
1041 char portbuf[MAX_CRYPT_BITS/8];
1042 char cpbuf[MAX_CRYPT_BITS/4];
1043 const char* inp = inbuf;
1044
1045 unsigned short lm;
1046
1047 // must ensure that any data block would be < key's modulus
1048 // hence -1
1049 int portion_len = (prkface.m.bits() - 1) / 8;
1050
1051 if (portion_len < 0) portion_len = 0;
1052
1053 char* prev_crypted = new char[portion_len];
1054 memset(prev_crypted, 0, portion_len);
1055
1056 out_size = 0;
1057
1058 while (in_size)
1059 {
1060 size_t uportion_len = (std::size_t) (portion_len);
1061 size_t cur_size = in_size > uportion_len ? uportion_len : in_size;
1062
1063 for (i=0; i<cur_size; ++i)
1064 {
1065 portbuf[i] = inp[i] ^ prev_crypted[i];
1066 }
1067
1068 EncryptPortion(portbuf, cur_size, cpbuf, cp_size);
1069
1070 for (i=0; i< uportion_len; ++i)
1071 {
1072 prev_crypted[i] = i < cp_size ? cpbuf[i] : 0;
1073 }
1074
1075 lm=cur_size;
1076 memcpy (outbuf+out_size,&lm, sizeof(unsigned short));
1077 out_size+=sizeof (unsigned short);
1078 lm=(unsigned short)cp_size;
1079 memcpy (outbuf+out_size,&lm, sizeof(unsigned short));
1080 out_size+=sizeof (unsigned short);
1081 memcpy (outbuf+out_size,cpbuf, cp_size);
1082 out_size+=cp_size;
1083 inp+=cur_size;
1084 in_size-=cur_size;
1085 }
1086
1087 delete [] prev_crypted;
1088 return;
1089 }
1090
1091 /*
1092 void CCryptoProviderRSA::Decrypt(const char *inbuf, size_t in_size,char *outbuf, size_t &out_size)
1093 {
1094 size_t i, cp_size,pt_size;
1095
1096 char portbuf[MAX_CRYPT_BITS/8];
1097 char cpbuf[MAX_CRYPT_BITS/4];
1098
1099 unsigned short lmi, lmo;
1100
1101 // must ensure that any data block would be < key's modulus
1102 // hence -1
1103 // TODO: size_t here ?
1104 int portion_len = (prkface.m.bits() - 1) / 8;
1105 char prev_crypted[portion_len];
1106 memset(&prev_crypted, 0, portion_len);
1107
1108 const char *inp=inbuf;
1109 out_size = 0;
1110
1111 while(in_size)
1112 {
1113 memcpy (&lmi,inp,sizeof (unsigned short)); inp += sizeof(unsigned short); in_size -= sizeof(unsigned short);
1114 memcpy (&lmo,inp,sizeof (unsigned short)); inp += sizeof(unsigned short); in_size -= sizeof(unsigned short);
1115
1116 if (lmo>in_size)
1117 break;
1118
1119 memcpy (cpbuf,inp,lmo);
1120 cp_size = lmo;
1121 pt_size = lmi;
1122
1123 DecryptPortion(cpbuf, cp_size, portbuf, pt_size);
1124
1125 if (lmi>pt_size)
1126 lmi=(unsigned short)pt_size;
1127
1128 for (i=0; i<lmi; ++i)
1129 portbuf[i] ^= prev_crypted[i];
1130
1131 for (i=0; i< portion_len; ++i)
1132 prev_crypted[i] = i < cp_size ? cpbuf[i] : 0;
1133
1134 memcpy (outbuf+out_size,portbuf,lmi);
1135 out_size += lmi;
1136
1137 inp+=lmo;
1138 in_size-=lmo;
1139 }
1140 return;
1141 }
1142 */
1143
1144 } // namespace YandexAuth
1145