1 /** 2 * Karatsuba operations 3 * 4 * Copyright: 5 * (C) 1999-2010,2014 Jack Lloyd 6 * (C) 2014-2015 Etienne Cimon 7 * 2006 Luca Piccarreta 8 * 9 * License: 10 * Botan is released under the Simplified BSD License (see LICENSE.md) 11 */ 12 module botan_math.mp_karatsuba; 13 14 import botan_math.mp_types; 15 import botan_math.mp_bigint; 16 import botan_math.mp_comba; 17 18 __gshared immutable size_t KARATSUBA_MULTIPLY_THRESHOLD = 32; 19 __gshared immutable size_t KARATSUBA_SQUARE_THRESHOLD = 32; 20 21 /* 22 * Karatsuba Multiplication Operation 23 */ 24 void karatsuba_mul(word* z, in word* x, in word* y, size_t N, word* workspace) 25 { 26 if (N < KARATSUBA_MULTIPLY_THRESHOLD || N % 2) 27 { 28 if (N == 6) 29 return bigint_comba_mul6(*cast(word[12]*) z, *cast(word[6]*) x, *cast(word[6]*) y); 30 else if (N == 8) 31 return bigint_comba_mul8(*cast(word[16]*) z, *cast(word[8]*) x, *cast(word[8]*) y); 32 else if (N == 16) 33 return bigint_comba_mul16(*cast(word[32]*) z, *cast(word[16]*) x, *cast(word[16]*) y); 34 else 35 return bigint_simple_mul(z, x, N, y, N); 36 } 37 38 const size_t N2 = N / 2; 39 40 const word* x0 = x; 41 const word* x1 = x + N2; 42 const word* y0 = y; 43 const word* y1 = y + N2; 44 word* z0 = z; 45 word* z1 = z + N; 46 47 const int cmp0 = bigint_cmp(x0, N2, x1, N2); 48 const int cmp1 = bigint_cmp(y1, N2, y0, N2); 49 50 clearMem(workspace, 2*N); 51 52 //if (cmp0 && cmp1) 53 { 54 if (cmp0 > 0) 55 bigint_sub3(z0, x0, N2, x1, N2); 56 else 57 bigint_sub3(z0, x1, N2, x0, N2); 58 59 if (cmp1 > 0) 60 bigint_sub3(z1, y1, N2, y0, N2); 61 else 62 bigint_sub3(z1, y0, N2, y1, N2); 63 64 karatsuba_mul(workspace, z0, z1, N2, workspace+N); 65 } 66 67 karatsuba_mul(z0, x0, y0, N2, workspace+N); 68 karatsuba_mul(z1, x1, y1, N2, workspace+N); 69 70 const word ws_carry = bigint_add3_nc(workspace + N, z0, N, z1, N); 71 word z_carry = bigint_add2_nc(z + N2, N, workspace + N, N); 72 73 z_carry += bigint_add2_nc(z + N + N2, N2, &ws_carry, 1); 74 bigint_add2_nc(z + N + N2, N2, &z_carry, 1); 75 76 if ((cmp0 == cmp1) || (cmp0 == 0) || (cmp1 == 0)) 77 bigint_add2(z + N2, 2*N-N2, workspace, N); 78 else 79 bigint_sub2(z + N2, 2*N-N2, workspace, N); 80 } 81 82 /* 83 * Karatsuba Squaring Operation 84 */ 85 void karatsuba_sqr(word* z, in word* x, size_t N, word* workspace) 86 { 87 if (N < KARATSUBA_SQUARE_THRESHOLD || N % 2) 88 { 89 if (N == 6) 90 return bigint_comba_sqr6(*cast(word[12]*) z, *cast(word[6]*) x); 91 else if (N == 8) 92 return bigint_comba_sqr8(*cast(word[16]*) z, *cast(word[8]*) x); 93 else if (N == 16) 94 return bigint_comba_sqr16(*cast(word[32]*) z, *cast(word[16]*) x); 95 else 96 return bigint_simple_sqr(z, x, N); 97 } 98 99 const size_t N2 = N / 2; 100 101 const word* x0 = x; 102 const word* x1 = x + N2; 103 word* z0 = z; 104 word* z1 = z + N; 105 106 const int cmp = bigint_cmp(x0, N2, x1, N2); 107 108 clearMem(workspace, 2*N); 109 110 //if (cmp) 111 { 112 if (cmp > 0) 113 bigint_sub3(z0, x0, N2, x1, N2); 114 else 115 bigint_sub3(z0, x1, N2, x0, N2); 116 117 karatsuba_sqr(workspace, z0, N2, workspace+N); 118 } 119 120 karatsuba_sqr(z0, x0, N2, workspace+N); 121 karatsuba_sqr(z1, x1, N2, workspace+N); 122 123 const word ws_carry = bigint_add3_nc(workspace + N, z0, N, z1, N); 124 word z_carry = bigint_add2_nc(z + N2, N, workspace + N, N); 125 126 z_carry += bigint_add2_nc(z + N + N2, N2, &ws_carry, 1); 127 bigint_add2_nc(z + N + N2, N2, &z_carry, 1); 128 129 /* 130 * This is only actually required if cmp is != 0, however 131 * if cmp==0 then workspace[0:N] == 0 and avoiding the jump 132 * hides a timing channel. 133 */ 134 bigint_sub2(z + N2, 2*N-N2, workspace, N); 135 } 136 137 /* 138 * Pick a good size for the Karatsuba multiply 139 */ 140 size_t karatsuba_size(size_t z_size, 141 size_t x_size, size_t x_sw, 142 size_t y_size, size_t y_sw) 143 { 144 if (x_sw > x_size || x_sw > y_size || y_sw > x_size || y_sw > y_size) 145 return 0; 146 147 if (((x_size == x_sw) && (x_size % 2)) || 148 ((y_size == y_sw) && (y_size % 2))) 149 return 0; 150 151 const size_t start = (x_sw > y_sw) ? x_sw : y_sw; 152 const size_t end = (x_size < y_size) ? x_size : y_size; 153 154 if (start == end) 155 { 156 if (start % 2) 157 return 0; 158 return start; 159 } 160 161 for (size_t j = start; j <= end; ++j) 162 { 163 if (j % 2) 164 continue; 165 166 if (2*j > z_size) 167 return 0; 168 169 if (x_sw <= j && j <= x_size && y_sw <= j && j <= y_size) 170 { 171 if (j % 4 == 2 && 172 (j+2) <= x_size && (j+2) <= y_size && 2*(j+2) <= z_size) 173 return j+2; 174 return j; 175 } 176 } 177 178 return 0; 179 } 180 181 /* 182 * Pick a good size for the Karatsuba squaring 183 */ 184 size_t karatsuba_size(size_t z_size, size_t x_size, size_t x_sw) 185 { 186 if (x_sw == x_size) 187 { 188 if (x_sw % 2) 189 return 0; 190 return x_sw; 191 } 192 193 for (size_t j = x_sw; j <= x_size; ++j) 194 { 195 if (j % 2) 196 continue; 197 198 if (2*j > z_size) 199 return 0; 200 201 if (j % 4 == 2 && (j+2) <= x_size && 2*(j+2) <= z_size) 202 return j+2; 203 return j; 204 } 205 206 return 0; 207 }