/* * Lowest Level MPI Algorithms * (C) 1999-2010 Jack Lloyd * 2006 Luca Piccarreta * * Botan is released under the Simplified BSD License (see license.txt) */ #include #include #include #include #include namespace Botan { /* * Two Operand Addition, No Carry */ word bigint_add2_nc(word x[], size_t x_size, const word y[], size_t y_size) { word carry = 0; BOTAN_ASSERT(x_size >= y_size, "Expected sizes"); const size_t blocks = y_size - (y_size % 8); for(size_t i = 0; i != blocks; i += 8) carry = word8_add2(x + i, y + i, carry); for(size_t i = blocks; i != y_size; ++i) x[i] = word_add(x[i], y[i], &carry); for(size_t i = y_size; i != x_size; ++i) x[i] = word_add(x[i], 0, &carry); return carry; } /* * Three Operand Addition, No Carry */ word bigint_add3_nc(word z[], const word x[], size_t x_size, const word y[], size_t y_size) { if(x_size < y_size) { return bigint_add3_nc(z, y, y_size, x, x_size); } word carry = 0; const size_t blocks = y_size - (y_size % 8); for(size_t i = 0; i != blocks; i += 8) carry = word8_add3(z + i, x + i, y + i, carry); for(size_t i = blocks; i != y_size; ++i) z[i] = word_add(x[i], y[i], &carry); for(size_t i = y_size; i != x_size; ++i) z[i] = word_add(x[i], 0, &carry); return carry; } /* * Two Operand Addition */ void bigint_add2(word x[], size_t x_size, const word y[], size_t y_size) { if(bigint_add2_nc(x, x_size, y, y_size)) x[x_size] += 1; } /* * Three Operand Addition */ void bigint_add3(word z[], const word x[], size_t x_size, const word y[], size_t y_size) { z[(x_size > y_size ? x_size : y_size)] += bigint_add3_nc(z, x, x_size, y, y_size); } /* * Two Operand Subtraction */ word bigint_sub2(word x[], size_t x_size, const word y[], size_t y_size) { word borrow = 0; BOTAN_ASSERT(x_size >= y_size, "Expected sizes"); const size_t blocks = y_size - (y_size % 8); for(size_t i = 0; i != blocks; i += 8) borrow = word8_sub2(x + i, y + i, borrow); for(size_t i = blocks; i != y_size; ++i) x[i] = word_sub(x[i], y[i], &borrow); for(size_t i = y_size; i != x_size; ++i) x[i] = word_sub(x[i], 0, &borrow); return borrow; } /* * Two Operand Subtraction x = y - x */ void bigint_sub2_rev(word x[], const word y[], size_t y_size) { word borrow = 0; const size_t blocks = y_size - (y_size % 8); for(size_t i = 0; i != blocks; i += 8) borrow = word8_sub2_rev(x + i, y + i, borrow); for(size_t i = blocks; i != y_size; ++i) x[i] = word_sub(y[i], x[i], &borrow); BOTAN_ASSERT(!borrow, "y must be greater than x"); } /* * Three Operand Subtraction */ word bigint_sub3(word z[], const word x[], size_t x_size, const word y[], size_t y_size) { word borrow = 0; BOTAN_ASSERT(x_size >= y_size, "Expected sizes"); const size_t blocks = y_size - (y_size % 8); for(size_t i = 0; i != blocks; i += 8) borrow = word8_sub3(z + i, x + i, y + i, borrow); for(size_t i = blocks; i != y_size; ++i) z[i] = word_sub(x[i], y[i], &borrow); for(size_t i = y_size; i != x_size; ++i) z[i] = word_sub(x[i], 0, &borrow); return borrow; } /* * Two Operand Linear Multiply */ void bigint_linmul2(word x[], size_t x_size, word y) { const size_t blocks = x_size - (x_size % 8); word carry = 0; for(size_t i = 0; i != blocks; i += 8) carry = word8_linmul2(x + i, y, carry); for(size_t i = blocks; i != x_size; ++i) x[i] = word_madd2(x[i], y, &carry); x[x_size] = carry; } /* * Three Operand Linear Multiply */ void bigint_linmul3(word z[], const word x[], size_t x_size, word y) { const size_t blocks = x_size - (x_size % 8); word carry = 0; for(size_t i = 0; i != blocks; i += 8) carry = word8_linmul3(z + i, x + i, y, carry); for(size_t i = blocks; i != x_size; ++i) z[i] = word_madd2(x[i], y, &carry); z[x_size] = carry; } }