OLD | NEW |
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 /* This file implements moduluar exponentiation using Montgomery's | 5 /* This file implements moduluar exponentiation using Montgomery's |
6 * method for modular reduction. This file implements the method | 6 * method for modular reduction. This file implements the method |
7 * described as "Improvement 2" in the paper "A Cryptogrpahic Library for | 7 * described as "Improvement 2" in the paper "A Cryptogrpahic Library for |
8 * the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr. | 8 * the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr. |
9 * published in "Advances in Cryptology: Proceedings of EUROCRYPT '90" | 9 * published in "Advances in Cryptology: Proceedings of EUROCRYPT '90" |
10 * "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244, | 10 * "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244, |
(...skipping 865 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
876 mp_size window_bits, | 876 mp_size window_bits, |
877 mp_size num_powers) | 877 mp_size num_powers) |
878 { | 878 { |
879 mp_int *pa1, *pa2, *ptmp; | 879 mp_int *pa1, *pa2, *ptmp; |
880 mp_size i; | 880 mp_size i; |
881 mp_size first_window; | 881 mp_size first_window; |
882 mp_err res; | 882 mp_err res; |
883 int expOff; | 883 int expOff; |
884 mp_int accum1, accum2, accum[WEAVE_WORD_SIZE]; | 884 mp_int accum1, accum2, accum[WEAVE_WORD_SIZE]; |
885 mp_int tmp; | 885 mp_int tmp; |
886 unsigned char *powersArray; | 886 unsigned char *powersArray = NULL; |
887 unsigned char *powers; | 887 unsigned char *powers = NULL; |
888 | 888 |
889 MP_DIGITS(&accum1) = 0; | 889 MP_DIGITS(&accum1) = 0; |
890 MP_DIGITS(&accum2) = 0; | 890 MP_DIGITS(&accum2) = 0; |
891 MP_DIGITS(&accum[0]) = 0; | 891 MP_DIGITS(&accum[0]) = 0; |
892 MP_DIGITS(&accum[1]) = 0; | 892 MP_DIGITS(&accum[1]) = 0; |
893 MP_DIGITS(&accum[2]) = 0; | 893 MP_DIGITS(&accum[2]) = 0; |
894 MP_DIGITS(&accum[3]) = 0; | 894 MP_DIGITS(&accum[3]) = 0; |
895 MP_DIGITS(&tmp) = 0; | 895 MP_DIGITS(&tmp) = 0; |
896 | 896 |
897 powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1)); | |
898 if (powersArray == NULL) { | |
899 res = MP_MEM; | |
900 goto CLEANUP; | |
901 } | |
902 | |
903 /* powers[i] = base ** (i); */ | |
904 powers = (unsigned char *)MP_ALIGN(powersArray,num_powers); | |
905 | |
906 /* grab the first window value. This allows us to preload accumulator1 | 897 /* grab the first window value. This allows us to preload accumulator1 |
907 * and save a conversion, some squares and a multiple*/ | 898 * and save a conversion, some squares and a multiple*/ |
908 MP_CHECKOK( mpl_get_bits(exponent, | 899 MP_CHECKOK( mpl_get_bits(exponent, |
909 bits_in_exponent-window_bits, window_bits) ); | 900 bits_in_exponent-window_bits, window_bits) ); |
910 first_window = (mp_size)res; | 901 first_window = (mp_size)res; |
911 | 902 |
912 MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); | 903 MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) ); |
913 MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); | 904 MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) ); |
914 MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) ); | |
915 | 905 |
916 /* build the first WEAVE_WORD powers inline */ | 906 /* build the first WEAVE_WORD powers inline */ |
917 /* if WEAVE_WORD_SIZE is not 4, this code will have to change */ | 907 /* if WEAVE_WORD_SIZE is not 4, this code will have to change */ |
918 if (num_powers > 2) { | 908 if (num_powers > 2) { |
919 MP_CHECKOK( mp_init_size(&accum[0], 3 * nLen + 2) ); | 909 MP_CHECKOK( mp_init_size(&accum[0], 3 * nLen + 2) ); |
920 MP_CHECKOK( mp_init_size(&accum[1], 3 * nLen + 2) ); | 910 MP_CHECKOK( mp_init_size(&accum[1], 3 * nLen + 2) ); |
921 MP_CHECKOK( mp_init_size(&accum[2], 3 * nLen + 2) ); | 911 MP_CHECKOK( mp_init_size(&accum[2], 3 * nLen + 2) ); |
922 MP_CHECKOK( mp_init_size(&accum[3], 3 * nLen + 2) ); | 912 MP_CHECKOK( mp_init_size(&accum[3], 3 * nLen + 2) ); |
923 mp_set(&accum[0], 1); | 913 mp_set(&accum[0], 1); |
924 MP_CHECKOK( s_mp_to_mont(&accum[0], mmm, &accum[0]) ); | 914 MP_CHECKOK( s_mp_to_mont(&accum[0], mmm, &accum[0]) ); |
925 MP_CHECKOK( mp_copy(montBase, &accum[1]) ); | 915 MP_CHECKOK( mp_copy(montBase, &accum[1]) ); |
926 SQR(montBase, &accum[2]); | 916 SQR(montBase, &accum[2]); |
927 MUL_NOWEAVE(montBase, &accum[2], &accum[3]); | 917 MUL_NOWEAVE(montBase, &accum[2], &accum[3]); |
| 918 powersArray = (unsigned char *)malloc(num_powers*(nLen*sizeof(mp_digit)+1)); |
| 919 if (!powersArray) { |
| 920 res = MP_MEM; |
| 921 goto CLEANUP; |
| 922 } |
| 923 /* powers[i] = base ** (i); */ \ |
| 924 powers = (unsigned char *)MP_ALIGN(powersArray,num_powers); \ |
928 MP_CHECKOK( mpi_to_weave(accum, powers, nLen, num_powers) ); | 925 MP_CHECKOK( mpi_to_weave(accum, powers, nLen, num_powers) ); |
929 if (first_window < 4) { | 926 if (first_window < 4) { |
930 MP_CHECKOK( mp_copy(&accum[first_window], &accum1) ); | 927 MP_CHECKOK( mp_copy(&accum[first_window], &accum1) ); |
931 first_window = num_powers; | 928 first_window = num_powers; |
932 } | 929 } |
933 } else { | 930 } else { |
934 if (first_window == 0) { | 931 if (first_window == 0) { |
935 mp_set(&accum1, 1); | 932 mp_set(&accum1, 1); |
936 MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); | 933 MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) ); |
937 } else { | 934 } else { |
938 /* assert first_window == 1? */ | 935 /* assert first_window == 1? */ |
939 MP_CHECKOK( mp_copy(montBase, &accum1) ); | 936 MP_CHECKOK( mp_copy(montBase, &accum1) ); |
940 } | 937 } |
941 } | 938 } |
942 | 939 |
943 /* | 940 /* |
944 * calculate all the powers in the powers array. | 941 * calculate all the powers in the powers array. |
945 * this adds 2**(k-1)-2 square operations over just calculating the | 942 * this adds 2**(k-1)-2 square operations over just calculating the |
946 * odd powers where k is the window size in the two other mp_modexpt | 943 * odd powers where k is the window size in the two other mp_modexpt |
947 * implementations in this file. We will get some of that | 944 * implementations in this file. We will get some of that |
948 * back by not needing the first 'k' squares and one multiply for the | 945 * back by not needing the first 'k' squares and one multiply for the |
949 * first window */ | 946 * first window. |
| 947 * Given the value of 4 for WEAVE_WORD_SIZE, this loop will only execute if |
| 948 * num_powers > 2, in which case powers will have been allocated. |
| 949 */ |
950 for (i = WEAVE_WORD_SIZE; i < num_powers; i++) { | 950 for (i = WEAVE_WORD_SIZE; i < num_powers; i++) { |
951 int acc_index = i & (WEAVE_WORD_SIZE-1); /* i % WEAVE_WORD_SIZE */ | 951 int acc_index = i & (WEAVE_WORD_SIZE-1); /* i % WEAVE_WORD_SIZE */ |
952 if ( i & 1 ) { | 952 if ( i & 1 ) { |
953 MUL_NOWEAVE(montBase, &accum[acc_index-1] , &accum[acc_index]); | 953 MUL_NOWEAVE(montBase, &accum[acc_index-1] , &accum[acc_index]); |
954 /* we've filled the array do our 'per array' processing */ | 954 /* we've filled the array do our 'per array' processing */ |
955 if (acc_index == (WEAVE_WORD_SIZE-1)) { | 955 if (acc_index == (WEAVE_WORD_SIZE-1)) { |
956 MP_CHECKOK( mpi_to_weave(accum, powers + i - (WEAVE_WORD_SIZE-1), | 956 MP_CHECKOK( mpi_to_weave(accum, powers + i - (WEAVE_WORD_SIZE-1), |
957 nLen, num_powers) ); | 957 nLen, num_powers) ); |
958 | 958 |
959 if (first_window <= i) { | 959 if (first_window <= i) { |
(...skipping 26 matching lines...) Expand all Loading... |
986 * above and is an internal programming error. | 986 * above and is an internal programming error. |
987 */ | 987 */ |
988 #if MP_ARGCHK == 2 | 988 #if MP_ARGCHK == 2 |
989 assert(MP_USED(&accum1) != 0); | 989 assert(MP_USED(&accum1) != 0); |
990 #endif | 990 #endif |
991 | 991 |
992 /* set accumulator to montgomery residue of 1 */ | 992 /* set accumulator to montgomery residue of 1 */ |
993 pa1 = &accum1; | 993 pa1 = &accum1; |
994 pa2 = &accum2; | 994 pa2 = &accum2; |
995 | 995 |
| 996 /* tmp is not used if window_bits == 1. */ |
| 997 if (window_bits != 1) { |
| 998 MP_CHECKOK( mp_init_size(&tmp, 3 * nLen + 2) ); |
| 999 } |
| 1000 |
996 for (expOff = bits_in_exponent - window_bits*2; expOff >= 0; expOff -= window_
bits) { | 1001 for (expOff = bits_in_exponent - window_bits*2; expOff >= 0; expOff -= window_
bits) { |
997 mp_size smallExp; | 1002 mp_size smallExp; |
998 MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); | 1003 MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) ); |
999 smallExp = (mp_size)res; | 1004 smallExp = (mp_size)res; |
1000 | 1005 |
1001 /* handle unroll the loops */ | 1006 /* handle unroll the loops */ |
1002 switch (window_bits) { | 1007 switch (window_bits) { |
1003 case 1: | 1008 case 1: |
1004 if (!smallExp) { | 1009 if (!smallExp) { |
1005 SQR(pa1,pa2); SWAPPA; | 1010 SQR(pa1,pa2); SWAPPA; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1164 | 1169 |
1165 CLEANUP: | 1170 CLEANUP: |
1166 mp_clear(&montBase); | 1171 mp_clear(&montBase); |
1167 mp_clear(&goodBase); | 1172 mp_clear(&goodBase); |
1168 /* Don't mp_clear mmm.N because it is merely a copy of modulus. | 1173 /* Don't mp_clear mmm.N because it is merely a copy of modulus. |
1169 ** Just zap it. | 1174 ** Just zap it. |
1170 */ | 1175 */ |
1171 memset(&mmm, 0, sizeof mmm); | 1176 memset(&mmm, 0, sizeof mmm); |
1172 return res; | 1177 return res; |
1173 } | 1178 } |
OLD | NEW |