| 1 | /* |
| 2 | Copyright (C) 1999-2007 The Botan Project. All rights reserved. |
| 3 | |
| 4 | Redistribution and use in source and binary forms, for any use, with or without |
| 5 | modification, is permitted provided that the following conditions are met: |
| 6 | |
| 7 | 1. Redistributions of source code must retain the above copyright notice, this |
| 8 | list of conditions, and the following disclaimer. |
| 9 | |
| 10 | 2. Redistributions in binary form must reproduce the above copyright notice, |
| 11 | this list of conditions, and the following disclaimer in the documentation |
| 12 | and/or other materials provided with the distribution. |
| 13 | |
| 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) "AS IS" AND ANY EXPRESS OR IMPLIED |
| 15 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 16 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. |
| 17 | |
| 18 | IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTOR(S) BE LIABLE FOR ANY DIRECT, |
| 19 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| 20 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| 23 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 24 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | */ |
| 26 | // LICENSEHEADER_END |
| 27 | namespace QCA { // WRAPNS_LINE |
| 28 | /************************************************* |
| 29 | * Lowest Level MPI Algorithms Source File * |
| 30 | * (C) 1999-2007 The Botan Project * |
| 31 | *************************************************/ |
| 32 | |
| 33 | } // WRAPNS_LINE |
| 34 | #include <botan/mp_asm.h> |
| 35 | namespace QCA { // WRAPNS_LINE |
| 36 | } // WRAPNS_LINE |
| 37 | #include <botan/mp_asmi.h> |
| 38 | namespace QCA { // WRAPNS_LINE |
| 39 | } // WRAPNS_LINE |
| 40 | #include <botan/mp_core.h> |
| 41 | namespace QCA { // WRAPNS_LINE |
| 42 | } // WRAPNS_LINE |
| 43 | #include <botan/mem_ops.h> |
| 44 | namespace QCA { // WRAPNS_LINE |
| 45 | |
| 46 | namespace Botan { |
| 47 | |
| 48 | extern "C" { |
| 49 | |
| 50 | /************************************************* |
| 51 | * Two Operand Addition, No Carry * |
| 52 | *************************************************/ |
| 53 | word bigint_add2_nc(word x[], u32bit x_size, const word y[], u32bit y_size) |
| 54 | { |
| 55 | word carry = 0; |
| 56 | |
| 57 | const u32bit blocks = y_size - (y_size % 8); |
| 58 | |
| 59 | for (u32bit j = 0; j != blocks; j += 8) |
| 60 | carry = word8_add2(x: x + j, y: y + j, carry); |
| 61 | |
| 62 | for (u32bit j = blocks; j != y_size; ++j) |
| 63 | x[j] = word_add(x: x[j], y: y[j], carry: &carry); |
| 64 | |
| 65 | if (!carry) |
| 66 | return 0; |
| 67 | |
| 68 | for (u32bit j = y_size; j != x_size; ++j) |
| 69 | if (++x[j]) |
| 70 | return 0; |
| 71 | |
| 72 | return 1; |
| 73 | } |
| 74 | |
| 75 | /************************************************* |
| 76 | * Three Operand Addition, No Carry * |
| 77 | *************************************************/ |
| 78 | word bigint_add3_nc(word z[], const word x[], u32bit x_size, const word y[], u32bit y_size) |
| 79 | { |
| 80 | if (x_size < y_size) { |
| 81 | return bigint_add3_nc(z, x: y, x_size: y_size, y: x, y_size: x_size); |
| 82 | } |
| 83 | |
| 84 | word carry = 0; |
| 85 | |
| 86 | const u32bit blocks = y_size - (y_size % 8); |
| 87 | |
| 88 | for (u32bit j = 0; j != blocks; j += 8) |
| 89 | carry = word8_add3(z: z + j, x: x + j, y: y + j, carry); |
| 90 | |
| 91 | for (u32bit j = blocks; j != y_size; ++j) |
| 92 | z[j] = word_add(x: x[j], y: y[j], carry: &carry); |
| 93 | |
| 94 | for (u32bit j = y_size; j != x_size; ++j) { |
| 95 | word x_j = x[j] + carry; |
| 96 | if (carry && x_j) |
| 97 | carry = 0; |
| 98 | z[j] = x_j; |
| 99 | } |
| 100 | |
| 101 | return carry; |
| 102 | } |
| 103 | |
| 104 | /************************************************* |
| 105 | * Two Operand Addition * |
| 106 | *************************************************/ |
| 107 | void bigint_add2(word x[], u32bit x_size, const word y[], u32bit y_size) |
| 108 | { |
| 109 | if (bigint_add2_nc(x, x_size, y, y_size)) |
| 110 | ++x[x_size]; |
| 111 | } |
| 112 | |
| 113 | /************************************************* |
| 114 | * Three Operand Addition * |
| 115 | *************************************************/ |
| 116 | void bigint_add3(word z[], const word x[], u32bit x_size, const word y[], u32bit y_size) |
| 117 | { |
| 118 | if (bigint_add3_nc(z, x, x_size, y, y_size)) |
| 119 | ++z[(x_size > y_size ? x_size : y_size)]; |
| 120 | } |
| 121 | |
| 122 | /************************************************* |
| 123 | * Two Operand Subtraction * |
| 124 | *************************************************/ |
| 125 | void bigint_sub2(word x[], u32bit x_size, const word y[], u32bit y_size) |
| 126 | { |
| 127 | word carry = 0; |
| 128 | |
| 129 | const u32bit blocks = y_size - (y_size % 8); |
| 130 | |
| 131 | for (u32bit j = 0; j != blocks; j += 8) |
| 132 | carry = word8_sub2(x: x + j, y: y + j, carry); |
| 133 | |
| 134 | for (u32bit j = blocks; j != y_size; ++j) |
| 135 | x[j] = word_sub(x: x[j], y: y[j], carry: &carry); |
| 136 | |
| 137 | if (!carry) |
| 138 | return; |
| 139 | |
| 140 | for (u32bit j = y_size; j != x_size; ++j) { |
| 141 | --x[j]; |
| 142 | if (x[j] != MP_WORD_MAX) |
| 143 | return; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | /************************************************* |
| 148 | * Three Operand Subtraction * |
| 149 | *************************************************/ |
| 150 | void bigint_sub3(word z[], const word x[], u32bit x_size, const word y[], u32bit y_size) |
| 151 | { |
| 152 | word carry = 0; |
| 153 | |
| 154 | const u32bit blocks = y_size - (y_size % 8); |
| 155 | |
| 156 | for (u32bit j = 0; j != blocks; j += 8) |
| 157 | carry = word8_sub3(z: z + j, x: x + j, y: y + j, carry); |
| 158 | |
| 159 | for (u32bit j = blocks; j != y_size; ++j) |
| 160 | z[j] = word_sub(x: x[j], y: y[j], carry: &carry); |
| 161 | |
| 162 | for (u32bit j = y_size; j != x_size; ++j) { |
| 163 | word x_j = x[j] - carry; |
| 164 | if (carry && x_j != MP_WORD_MAX) |
| 165 | carry = 0; |
| 166 | z[j] = x_j; |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | /************************************************* |
| 171 | * Two Operand Linear Multiply * |
| 172 | *************************************************/ |
| 173 | void bigint_linmul2(word x[], u32bit x_size, word y) |
| 174 | { |
| 175 | const u32bit blocks = x_size - (x_size % 8); |
| 176 | |
| 177 | word carry = 0; |
| 178 | |
| 179 | for (u32bit j = 0; j != blocks; j += 8) |
| 180 | carry = word8_linmul2(x: x + j, y, carry); |
| 181 | |
| 182 | for (u32bit j = blocks; j != x_size; ++j) |
| 183 | x[j] = word_madd2(a: x[j], b: y, c: carry, carry: &carry); |
| 184 | |
| 185 | x[x_size] = carry; |
| 186 | } |
| 187 | |
| 188 | /************************************************* |
| 189 | * Three Operand Linear Multiply * |
| 190 | *************************************************/ |
| 191 | void bigint_linmul3(word z[], const word x[], u32bit x_size, word y) |
| 192 | { |
| 193 | const u32bit blocks = x_size - (x_size % 8); |
| 194 | |
| 195 | word carry = 0; |
| 196 | |
| 197 | for (u32bit j = 0; j != blocks; j += 8) |
| 198 | carry = word8_linmul3(z: z + j, x: x + j, y, carry); |
| 199 | |
| 200 | for (u32bit j = blocks; j != x_size; ++j) |
| 201 | z[j] = word_madd2(a: x[j], b: y, c: carry, carry: &carry); |
| 202 | |
| 203 | z[x_size] = carry; |
| 204 | } |
| 205 | |
| 206 | /************************************************* |
| 207 | * Montgomery Reduction Algorithm * |
| 208 | *************************************************/ |
| 209 | #ifndef BOTAN_MINIMAL_BIGINT |
| 210 | void bigint_monty_redc(word z[], u32bit z_size, const word x[], u32bit x_size, word u) |
| 211 | { |
| 212 | for (u32bit j = 0; j != x_size; ++j) { |
| 213 | word *z_j = z + j; |
| 214 | |
| 215 | const word y = z_j[0] * u; |
| 216 | |
| 217 | word carry = bigint_mul_add_words(z_j, x, x_size, y); |
| 218 | |
| 219 | word z_sum = z_j[x_size] + carry; |
| 220 | carry = (z_sum < z_j[x_size]); |
| 221 | z_j[x_size] = z_sum; |
| 222 | |
| 223 | for (u32bit k = x_size + 1; carry && k != z_size - j; ++k) { |
| 224 | ++z_j[k]; |
| 225 | carry = !z_j[k]; |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | if (bigint_cmp(z + x_size, x_size + 1, x, x_size) >= 0) |
| 230 | bigint_sub2(z + x_size, x_size + 1, x, x_size); |
| 231 | } |
| 232 | #endif |
| 233 | } |
| 234 | |
| 235 | } |
| 236 | } // WRAPNS_LINE |
| 237 | |