1 /** 2 * Monty 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_monty; 13 14 import botan_math.mp_word; 15 import botan_math.mp_bigint; 16 import botan_math.mp_comba; 17 import botan_math.mp_karatsuba; 18 19 /* 20 * Multiplication Algorithm Dispatcher 21 */ 22 void bigint_mul(word* z, size_t z_size, word* workspace, 23 in word* x, size_t x_size, size_t x_sw, 24 in word* y, size_t y_size, size_t y_sw) 25 { 26 if (x_sw == 1) 27 { 28 bigint_linmul3(z, y, y_sw, x[0]); 29 } 30 else if (y_sw == 1) 31 { 32 bigint_linmul3(z, x, x_sw, y[0]); 33 } 34 else if (x_sw <= 4 && x_size >= 4 && 35 y_sw <= 4 && y_size >= 4 && z_size >= 8) 36 { 37 bigint_comba_mul4(*cast(word[8]*) z, *cast(word[4]*) x, *cast(word[4]*) y); 38 } 39 else if (x_sw <= 6 && x_size >= 6 && 40 y_sw <= 6 && y_size >= 6 && z_size >= 12) 41 { 42 bigint_comba_mul6(*cast(word[12]*) z, *cast(word[6]*) x, *cast(word[6]*) y); 43 } 44 else if (x_sw <= 8 && x_size >= 8 && 45 y_sw <= 8 && y_size >= 8 && z_size >= 16) 46 { 47 bigint_comba_mul8(*cast(word[16]*) z, *cast(word[8]*) x, *cast(word[8]*) y); 48 } 49 else if (x_sw <= 9 && x_size >= 9 && 50 y_sw <= 9 && y_size >= 9 && z_size >= 18) 51 { 52 bigint_comba_mul9(*cast(word[18]*) z, *cast(word[9]*) x, *cast(word[9]*) y); 53 } 54 else if (x_sw <= 16 && x_size >= 16 && 55 y_sw <= 16 && y_size >= 16 && z_size >= 32) 56 { 57 bigint_comba_mul16(*cast(word[32]*) z, *cast(word[16]*) x, *cast(word[16]*) y); 58 } 59 else if (x_sw < KARATSUBA_MULTIPLY_THRESHOLD || 60 y_sw < KARATSUBA_MULTIPLY_THRESHOLD || 61 !workspace) 62 { 63 bigint_simple_mul(z, x, x_sw, y, y_sw); 64 } 65 else 66 { 67 const size_t N = karatsuba_size(z_size, x_size, x_sw, y_size, y_sw); 68 69 if (N) 70 karatsuba_mul(z, x, y, N, workspace); 71 else 72 bigint_simple_mul(z, x, x_sw, y, y_sw); 73 } 74 } 75 76 /* 77 * Squaring Algorithm Dispatcher 78 */ 79 void bigint_sqr(word* z, size_t z_size, word* workspace, 80 in word* x, size_t x_size, size_t x_sw) 81 { 82 if (x_sw == 1) 83 { 84 bigint_linmul3(z, x, x_sw, x[0]); 85 } 86 else if (x_sw <= 4 && x_size >= 4 && z_size >= 8) 87 { 88 bigint_comba_sqr4(*cast(word[8]*) z, *cast(word[4]*) x); 89 } 90 else if (x_sw <= 6 && x_size >= 6 && z_size >= 12) 91 { 92 bigint_comba_sqr6(*cast(word[12]*) z, *cast(word[6]*) x); 93 } 94 else if (x_sw <= 8 && x_size >= 8 && z_size >= 16) 95 { 96 bigint_comba_sqr8(*cast(word[16]*) z, *cast(word[8]*) x); 97 } 98 else if (x_sw <= 9 && x_size >= 9 && z_size >= 18) 99 { 100 bigint_comba_sqr9(*cast(word[18]*) z, *cast(word[9]*) x); 101 } 102 else if (x_sw <= 16 && x_size >= 16 && z_size >= 32) 103 { 104 bigint_comba_sqr16(*cast(word[32]*) z, *cast(word[16]*) x); 105 } 106 else if (x_size < KARATSUBA_SQUARE_THRESHOLD || !workspace) 107 { 108 bigint_simple_sqr(z, x, x_sw); 109 } 110 else 111 { 112 const size_t N = karatsuba_size(z_size, x_size, x_sw); 113 114 if (N) 115 karatsuba_sqr(z, x, N, workspace); 116 else 117 bigint_simple_sqr(z, x, x_sw); 118 } 119 } 120 121 /* 122 * Montgomery Multiplication 123 */ 124 void bigint_monty_mul(word* z, size_t z_size, 125 in word* x, size_t x_size, size_t x_sw, 126 in word* y, size_t y_size, size_t y_sw, 127 in word* p, size_t p_size, word p_dash, 128 word* ws) 129 { 130 bigint_mul( z, z_size, ws, 131 x, x_size, x_sw, 132 y, y_size, y_sw); 133 134 bigint_monty_redc(z, p, p_size, p_dash, ws); 135 } 136 137 138 /* 139 * Montgomery Squaring 140 */ 141 void bigint_monty_sqr(word* z, size_t z_size, 142 in word* x, size_t x_size, size_t x_sw, 143 in word* p, size_t p_size, word p_dash, 144 word* ws) 145 { 146 bigint_sqr(z, z_size, ws, x, x_size, x_sw); 147 bigint_monty_redc(z, p, p_size, p_dash, ws); 148 } 149 150 151 152 /** 153 * Montgomery Reduction 154 * Params: 155 * z = integer to reduce, of size exactly 2*(p_size+1). 156 Output is in the first p_size+1 words, higher 157 words are set to zero. 158 * p = modulus 159 * p_size = size of p 160 * p_dash = Montgomery value 161 * ws = workspace array of at least 2*(p_size+1) words 162 */ 163 void bigint_monty_redc(word* z, in word* p, size_t p_size, word p_dash, word* ws) 164 { 165 const size_t z_size = 2*(p_size+1); 166 167 const size_t blocks_of_8 = p_size - (p_size % 8); 168 169 foreach (size_t i; 0 .. p_size) 170 { 171 word* z_i = z + i; 172 173 word y = (*z_i) * p_dash; 174 175 /* 176 bigint_linmul3(ws, p, p_size, y); 177 bigint_add2(z_i, z_size - i, ws, p_size+1); 178 */ 179 180 word carry = 0; 181 182 for (size_t j = 0; j < blocks_of_8; j += 8) 183 carry = word8_madd3(*cast(word[8]*) (z_i + j), *cast(word[8]*) (p + j), y, carry); 184 185 for (size_t j = blocks_of_8; j < p_size; j++) { 186 version(D_InlineAsm_X86_64) { 187 word* _x = (cast(word*)p) + j; 188 word* _z = z_i + j; 189 size_t word_size = word.sizeof; 190 asm pure nothrow @nogc { 191 mov R8, _x; 192 mov R9, _z; 193 mov RCX, carry; 194 195 mov RAX, [R8]; 196 mov RBX, y; 197 mul RBX; 198 add RAX, [R9]; 199 adc RDX, 0; 200 add RAX, RCX; 201 adc RDX, 0; 202 mov carry, RDX; 203 mov [R9], RAX; 204 } 205 } else 206 z_i[j] = word_madd3(p[j], y, z_i[j], &carry); 207 } 208 word z_sum = z_i[p_size] + carry; 209 carry = (z_sum < z_i[p_size]); 210 z_i[p_size] = z_sum; 211 212 for (size_t j = p_size + 1; carry && j != z_size - i; ++j) 213 { 214 ++z_i[j]; 215 carry = !z_i[j]; 216 } 217 } 218 219 word borrow = 0; 220 foreach (size_t i; 0 .. p_size) 221 ws[i] = word_sub(z[p_size + i], p[i], &borrow); 222 223 ws[p_size] = word_sub(z[p_size+p_size], 0, &borrow); 224 225 copyMem(ws + p_size + 1, z + p_size, p_size + 1); 226 227 copyMem(z, ws + borrow*(p_size+1), p_size + 1); 228 clearMem(z + p_size + 1, z_size - p_size - 1); 229 }