| 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 |