aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stm32/modexpng_driver_sample.c475
-rw-r--r--stm32/modexpng_util.c189
-rw-r--r--stm32/modexpng_util.h30
-rw-r--r--stm32/modexpng_vector_1024.h138
-rw-r--r--stm32/modexpng_vector_2048.h254
-rw-r--r--stm32/modexpng_vector_4096.h486
6 files changed, 1572 insertions, 0 deletions
diff --git a/stm32/modexpng_driver_sample.c b/stm32/modexpng_driver_sample.c
new file mode 100644
index 0000000..1f0a767
--- /dev/null
+++ b/stm32/modexpng_driver_sample.c
@@ -0,0 +1,475 @@
+//
+// simple driver to test "modexpng" core in hardware
+//
+
+//
+// note, that the test program needs a custom bitstream where
+// the core is located at offset 0 (without the core selector)
+//
+
+// stm32 headers
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-fmc.h"
+
+// test vectors (generated by the supplied python math model)
+#include "modexpng_vector_1024.h"
+#include "modexpng_vector_2048.h"
+#include "modexpng_vector_4096.h"
+
+// reference code
+#include "modexpng_util.h"
+
+// locations of core registers
+#define CORE_ADDR_NAME0 (0x00 << 2)
+#define CORE_ADDR_NAME1 (0x01 << 2)
+#define CORE_ADDR_VERSION (0x02 << 2)
+#define CORE_ADDR_CONTROL (0x08 << 2)
+#define CORE_ADDR_STATUS (0x09 << 2)
+#define CORE_ADDR_MODE (0x10 << 2)
+#define CORE_ADDR_MODULUS_BITS (0x11 << 2)
+#define CORE_ADDR_EXPONENT_BITS (0x12 << 2)
+#define CORE_ADDR_BANK_BITS (0x13 << 2)
+#define CORE_ADDR_NUM_MULTS (0x14 << 2)
+
+// locations of data buffers
+#define CORE_ADDR_BANK_M (1 * 0x1000 + 0 * 0x200)
+#define CORE_ADDR_BANK_N (1 * 0x1000 + 1 * 0x200)
+#define CORE_ADDR_BANK_N_FACTOR (1 * 0x1000 + 2 * 0x200)
+#define CORE_ADDR_BANK_N_COEFF (1 * 0x1000 + 3 * 0x200)
+#define CORE_ADDR_BANK_X (1 * 0x1000 + 5 * 0x200)
+#define CORE_ADDR_BANK_Y (1 * 0x1000 + 6 * 0x200)
+
+#define CORE_ADDR_BANK_D (2 * 0x1000 + 0 * 0x200)
+#define CORE_ADDR_BANK_P (2 * 0x1000 + 1 * 0x200)
+#define CORE_ADDR_BANK_DP (2 * 0x1000 + 3 * 0x100)
+#define CORE_ADDR_BANK_P_FACTOR (2 * 0x1000 + 2 * 0x200)
+#define CORE_ADDR_BANK_P_COEFF (2 * 0x1000 + 3 * 0x200)
+#define CORE_ADDR_BANK_Q (2 * 0x1000 + 4 * 0x200)
+#define CORE_ADDR_BANK_DQ (2 * 0x1000 + 9 * 0x100)
+#define CORE_ADDR_BANK_Q_FACTOR (2 * 0x1000 + 5 * 0x200)
+#define CORE_ADDR_BANK_Q_COEFF (2 * 0x1000 + 6 * 0x200)
+#define CORE_ADDR_BANK_QINV (2 * 0x1000 + 7 * 0x200)
+
+#define CORE_ADDR_BANK_S (3 * 0x1000 + 0 * 0x200)
+#define CORE_ADDR_BANK_XM (3 * 0x1000 + 1 * 0x200)
+#define CORE_ADDR_BANK_YM (3 * 0x1000 + 2 * 0x200)
+
+// bit maps
+#define CORE_CONTROL_BIT_NEXT 0x00000002
+#define CORE_STATUS_BIT_VALID 0x00000002
+
+#define CORE_MODE_USING_CRT 0x00000002
+#define CORE_MODE_WITHOUT_CRT 0x00000000
+
+
+//
+// test vectors
+//
+static const uint32_t M_1024[] = M_1024_INIT;
+static const uint32_t N_1024[] = N_1024_INIT;
+static const uint32_t N_FACTOR_1024[] = N_FACTOR_1024_INIT;
+static const uint32_t N_COEFF_1024[] = N_COEFF_1024_INIT;
+static uint32_t X_1024[] = X_1024_INIT;
+static uint32_t Y_1024[] = Y_1024_INIT;
+static const uint32_t P_1024[] = P_1024_INIT;
+static const uint32_t Q_1024[] = Q_1024_INIT;
+static const uint32_t P_FACTOR_1024[] = P_FACTOR_1024_INIT;
+static const uint32_t Q_FACTOR_1024[] = Q_FACTOR_1024_INIT;
+static const uint32_t P_COEFF_1024[] = P_COEFF_1024_INIT;
+static const uint32_t Q_COEFF_1024[] = Q_COEFF_1024_INIT;
+static const uint32_t D_1024[] = D_1024_INIT;
+static const uint32_t DP_1024[] = DP_1024_INIT;
+static const uint32_t DQ_1024[] = DQ_1024_INIT;
+static const uint32_t QINV_1024[] = QINV_1024_INIT;
+static const uint32_t XM_1024[] = XM_1024_INIT;
+static const uint32_t YM_1024[] = YM_1024_INIT;
+static const uint32_t S_1024[] = S_1024_INIT;
+
+static const uint32_t M_2048[] = M_2048_INIT;
+static const uint32_t N_2048[] = N_2048_INIT;
+static const uint32_t N_FACTOR_2048[] = N_FACTOR_2048_INIT;
+static const uint32_t N_COEFF_2048[] = N_COEFF_2048_INIT;
+static uint32_t X_2048[] = X_2048_INIT;
+static uint32_t Y_2048[] = Y_2048_INIT;
+static const uint32_t P_2048[] = P_2048_INIT;
+static const uint32_t Q_2048[] = Q_2048_INIT;
+static const uint32_t P_FACTOR_2048[] = P_FACTOR_2048_INIT;
+static const uint32_t Q_FACTOR_2048[] = Q_FACTOR_2048_INIT;
+static const uint32_t P_COEFF_2048[] = P_COEFF_2048_INIT;
+static const uint32_t Q_COEFF_2048[] = Q_COEFF_2048_INIT;
+static const uint32_t D_2048[] = D_2048_INIT;
+static const uint32_t DP_2048[] = DP_2048_INIT;
+static const uint32_t DQ_2048[] = DQ_2048_INIT;
+static const uint32_t QINV_2048[] = QINV_2048_INIT;
+static const uint32_t XM_2048[] = XM_2048_INIT;
+static const uint32_t YM_2048[] = YM_2048_INIT;
+static const uint32_t S_2048[] = S_2048_INIT;
+
+static const uint32_t M_4096[] = M_4096_INIT;
+static const uint32_t N_4096[] = N_4096_INIT;
+static const uint32_t N_FACTOR_4096[] = N_FACTOR_4096_INIT;
+static const uint32_t N_COEFF_4096[] = N_COEFF_4096_INIT;
+static uint32_t X_4096[] = X_4096_INIT;
+static uint32_t Y_4096[] = Y_4096_INIT;
+static const uint32_t P_4096[] = P_4096_INIT;
+static const uint32_t Q_4096[] = Q_4096_INIT;
+static const uint32_t P_FACTOR_4096[] = P_FACTOR_4096_INIT;
+static const uint32_t Q_FACTOR_4096[] = Q_FACTOR_4096_INIT;
+static const uint32_t P_COEFF_4096[] = P_COEFF_4096_INIT;
+static const uint32_t Q_COEFF_4096[] = Q_COEFF_4096_INIT;
+static const uint32_t D_4096[] = D_4096_INIT;
+static const uint32_t DP_4096[] = DP_4096_INIT;
+static const uint32_t DQ_4096[] = DQ_4096_INIT;
+static const uint32_t QINV_4096[] = QINV_4096_INIT;
+static const uint32_t XM_4096[] = XM_4096_INIT;
+static const uint32_t YM_4096[] = YM_4096_INIT;
+static const uint32_t S_4096[] = S_4096_INIT;
+
+
+//
+// buffers
+//
+static uint32_t mod_rev[BUF_NUM_WORDS];
+static uint32_t mod_factor_rev[BUF_NUM_WORDS];
+static uint32_t mod_coeff_rev[BUF_NUM_WORDS+1];
+
+
+//
+// prototypes
+//
+void toggle_yellow_led(void);
+
+int check_montgomery_factor(uint32_t key_length, const uint32_t *mod, const uint32_t *mod_factor);
+int check_modulus_coeff(uint32_t key_length, const uint32_t *mod, const uint32_t *mod_coeff);
+
+int _sign_handler(uint32_t key_length, uint32_t use_crt, uint32_t first_run,
+ const uint32_t *m, const uint32_t *n,
+ const uint32_t *n_factor, const uint32_t *n_coeff,
+ uint32_t *x, uint32_t *y,
+ const uint32_t *p, const uint32_t *q,
+ const uint32_t *p_factor, const uint32_t *p_coeff,
+ const uint32_t *q_factor, const uint32_t *q_coeff,
+ const uint32_t *dp, const uint32_t *dq,
+ const uint32_t *d,
+ const uint32_t *qinv,
+ const uint32_t *s,
+ const uint32_t *xm, const uint32_t *ym);
+
+//
+// easier calls
+//
+#define sign_without_crt(k,f,m,n,nf,nc,x,y,d,s,xm,ym) \
+ _sign_handler (k,0,f,m,n,nf,nc,x,y,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,d,NULL,s,xm,ym)
+
+#define sign_using_crt(k,f,m,n,nf,nc,x,y,p,q,pf,pc,qf,qc,dp,dq,qinv,s,xm,ym) \
+ _sign_handler (k,1,f,m,n,nf,nc,x,y,p,q,pf,pc,qf,qc,dp,dq,NULL,qinv,s,xm,ym)
+
+
+//
+// test routine
+//
+int main()
+{
+ int ok;
+ int first_run;
+
+ // initialize
+ stm_init();
+ fmc_init();
+
+ // initialize
+ led_on(LED_GREEN);
+ led_off(LED_RED);
+ led_off(LED_YELLOW);
+ led_off(LED_BLUE);
+
+ // make sure, that ModExpNG is there
+ uint32_t core_name0;
+ uint32_t core_name1;
+ uint32_t core_version;
+
+ fmc_read_32(CORE_ADDR_NAME0, &core_name0);
+ fmc_read_32(CORE_ADDR_NAME1, &core_name1);
+ fmc_read_32(CORE_ADDR_VERSION, &core_version);
+
+ // "mode", "xpng"
+ if ((core_name0 != 0x6D6F6465) || (core_name1 != 0x78706E67))
+ { led_off(LED_GREEN);
+ led_on(LED_RED);
+ while (1);
+ }
+
+ // check, that reference code works correctly
+ ok = 1;
+
+ ok = ok && check_montgomery_factor(1024, N_1024, N_FACTOR_1024);
+ ok = ok && check_montgomery_factor( 512, P_1024, P_FACTOR_1024);
+ ok = ok && check_montgomery_factor( 512, Q_1024, Q_FACTOR_1024);
+ ok = ok && check_montgomery_factor(2048, N_2048, N_FACTOR_2048);
+ ok = ok && check_montgomery_factor(1024, P_2048, P_FACTOR_2048);
+ ok = ok && check_montgomery_factor(1024, Q_2048, Q_FACTOR_2048);
+ ok = ok && check_montgomery_factor(4096, N_4096, N_FACTOR_4096);
+ ok = ok && check_montgomery_factor(2048, P_4096, P_FACTOR_4096);
+ ok = ok && check_montgomery_factor(2048, Q_4096, Q_FACTOR_4096);
+
+ ok = ok && check_modulus_coeff(1024, N_1024, N_COEFF_1024);
+ ok = ok && check_modulus_coeff( 512, P_1024, P_COEFF_1024);
+ ok = ok && check_modulus_coeff( 512, Q_1024, Q_COEFF_1024);
+ ok = ok && check_modulus_coeff(2048, N_2048, N_COEFF_2048);
+ ok = ok && check_modulus_coeff(1024, P_2048, P_COEFF_2048);
+ ok = ok && check_modulus_coeff(1024, Q_2048, Q_COEFF_2048);
+// ok = ok && check_modulus_coeff(4096, N_4096, N_COEFF_4096); // SLOW (~20 sec)
+ ok = ok && check_modulus_coeff(2048, P_4096, P_COEFF_4096);
+ ok = ok && check_modulus_coeff(2048, Q_4096, Q_COEFF_4096);
+
+ if (!ok)
+ { led_off(LED_GREEN);
+ led_on(LED_RED);
+ while (1);
+ }
+
+ // repeat forever
+ ok = 1, first_run = 1;
+ while (1)
+ {
+ ok = ok && sign_without_crt(1024, first_run,
+ M_1024, N_1024, N_FACTOR_1024, N_COEFF_1024,
+ X_1024, Y_1024, D_1024, S_1024,
+ XM_1024, YM_1024);
+
+ ok = ok && sign_without_crt(2048, first_run,
+ M_2048, N_2048, N_FACTOR_2048, N_COEFF_2048,
+ X_2048, Y_2048, D_2048, S_2048,
+ XM_2048, YM_2048);
+
+ ok = ok && sign_without_crt(4096, first_run,
+ M_4096, N_4096, N_FACTOR_4096, N_COEFF_4096,
+ X_4096, Y_4096, D_4096, S_4096,
+ XM_4096, YM_4096);
+
+ ok = ok && sign_using_crt(1024, first_run,
+ M_1024, N_1024, N_FACTOR_1024, N_COEFF_1024,
+ X_1024, Y_1024, P_1024, Q_1024,
+ P_FACTOR_1024, P_COEFF_1024, Q_FACTOR_1024, Q_COEFF_1024,
+ DP_1024, DQ_1024, QINV_1024, S_1024,
+ XM_1024, YM_1024);
+
+ ok = ok && sign_using_crt(2048, first_run,
+ M_2048, N_2048, N_FACTOR_2048, N_COEFF_2048,
+ X_2048, Y_2048, P_2048, Q_2048,
+ P_FACTOR_2048, P_COEFF_2048, Q_FACTOR_2048, Q_COEFF_2048,
+ DP_2048, DQ_2048, QINV_2048, S_2048,
+ XM_2048, YM_2048);
+
+ ok = ok && sign_using_crt(4096, first_run,
+ M_4096, N_4096, N_FACTOR_4096, N_COEFF_4096,
+ X_4096, Y_4096, P_4096, Q_4096,
+ P_FACTOR_4096, P_COEFF_4096, Q_FACTOR_4096, Q_COEFF_4096,
+ DP_4096, DQ_4096, QINV_4096, S_4096,
+ XM_4096, YM_4096);
+
+ if (!ok)
+ { led_off(LED_GREEN);
+ led_on(LED_RED);
+ }
+
+ first_run = 0;
+
+ toggle_yellow_led();
+ }
+}
+
+int check_montgomery_factor(uint32_t key_length, const uint32_t *mod, const uint32_t *mod_factor)
+{
+ uint32_t i, j;
+ uint32_t num_words = key_length / UINT32_BITS;
+
+ // _calc_montgomery_factor() expects the least significant byte in [0],
+ // but C array initialization places it in [N-1], so we need to
+ // reverse the array before passing it to the function
+ for (i=0, j=num_words-1; i<num_words; i++, j--)
+ mod_rev[i] = mod[j];
+
+ // compute Montgomery factor
+ _calc_montgomery_factor(num_words, mod_rev, mod_factor_rev);
+
+ // we now need to compare the calculated factor to the reference value,
+ // _calc_montgomery_factor() places the least significant byte in [0],
+ // but C array initialization places the least significant byte of the
+ // reference value in [N-1], so we need to go in opposite directions
+ // when comparing
+ for (i=0, j=num_words-1; i<num_words; i++, j--)
+ if (mod_factor_rev[i] != mod_factor[j]) return 0;
+
+ // everything went just fine
+ return 1;
+}
+
+
+int check_modulus_coeff(uint32_t key_length, const uint32_t *mod, const uint32_t *mod_coeff)
+{
+ uint32_t i, j;
+ uint32_t num_words = key_length / UINT32_BITS;
+
+ // _calc_modulus_coeff() expects the least significant byte in [0],
+ // but C array initialization places it in [N-1], so we need to
+ // reverse the array before passing it to the function
+ for (i=0, j=num_words-1; i<num_words; i++, j--)
+ mod_rev[i] = mod[j];
+
+ // compute modulus-dependent speed-up coefficient
+ _calc_modulus_coeff(num_words, mod_rev, mod_coeff_rev);
+
+ // we now need to compare the calculated coefficient to the reference value,
+ // _calc_modulus_coeff() places the least significant byte in [0],
+ // but C array initialization places the least significant byte of the
+ // reference value in [N], so we need to go in opposite directions
+ // when comparing, also note, that we should process N+1 words, since the
+ // coefficient is slightly longer, than the modulus
+ for (i=0, j=num_words; i<=num_words; i++, j--)
+ if (mod_coeff_rev[i] != mod_coeff[j]) return 0;
+
+ // everything went just fine
+ return 1;
+}
+
+
+int _sign_handler(uint32_t key_length, uint32_t use_crt, uint32_t first_run,
+ const uint32_t *m, const uint32_t *n,
+ const uint32_t *n_factor, const uint32_t *n_coeff,
+ uint32_t *x, uint32_t *y,
+ const uint32_t *p, const uint32_t *q,
+ const uint32_t *p_factor, const uint32_t *p_coeff,
+ const uint32_t *q_factor, const uint32_t *q_coeff,
+ const uint32_t *dp, const uint32_t *dq,
+ const uint32_t *d,
+ const uint32_t *qinv,
+ const uint32_t *s,
+ const uint32_t *xm, const uint32_t *ym)
+{
+ uint32_t i, j, num_cyc;
+ uint32_t num_words = (key_length / sizeof(uint32_t)) >> 3;
+ uint32_t num_words_half = num_words >> 1;
+ uint32_t reg_control, reg_status;
+ uint32_t reg_mode;
+ uint32_t reg_modulus_bits, reg_exponent_bits;
+
+ // fill in all the necessary input values
+ // d is only written when CRT is not enabled (we wipe it otherwise just in case)
+ // note, that n_coeff is one word larger, than the modulus, so we need a single
+ // extra write after the word-by-word loop
+ for (i=0, j=num_words-1; i<num_words; i++, j--)
+ { fmc_write_32(CORE_ADDR_BANK_M + i * sizeof(uint32_t), m[j]);
+ fmc_write_32(CORE_ADDR_BANK_N + i * sizeof(uint32_t), n[j]);
+ fmc_write_32(CORE_ADDR_BANK_N_FACTOR + i * sizeof(uint32_t), n_factor[j]);
+ fmc_write_32(CORE_ADDR_BANK_N_COEFF + i * sizeof(uint32_t), n_coeff[j+1]); // mind the +1
+ fmc_write_32(CORE_ADDR_BANK_X + i * sizeof(uint32_t), x[j]);
+ fmc_write_32(CORE_ADDR_BANK_Y + i * sizeof(uint32_t), y[j]);
+ if (!use_crt) fmc_write_32(CORE_ADDR_BANK_D + i * sizeof(uint32_t), d[j]);
+ else fmc_write_32(CORE_ADDR_BANK_D + i * sizeof(uint32_t), 0);
+ }
+ fmc_write_32(CORE_ADDR_BANK_N_COEFF + i * sizeof(uint32_t), n_coeff[0]); // j+1 is 0 by now, i is num_words
+
+ // also fill in all the input values necessary for CRT mode
+ // again, we need to write a pair of extra words for p_coeff and q_coeff after the loop
+ if (use_crt)
+ { for (i=0, j=num_words_half-1; i<num_words_half; i++, j--)
+ { fmc_write_32(CORE_ADDR_BANK_P + i * sizeof(uint32_t), p[j]);
+ fmc_write_32(CORE_ADDR_BANK_Q + i * sizeof(uint32_t), q[j]);
+ fmc_write_32(CORE_ADDR_BANK_P_FACTOR + i * sizeof(uint32_t), p_factor[j]);
+ fmc_write_32(CORE_ADDR_BANK_P_COEFF + i * sizeof(uint32_t), p_coeff[j+1]); // mind the +1!
+ fmc_write_32(CORE_ADDR_BANK_Q_FACTOR + i * sizeof(uint32_t), q_factor[j]);
+ fmc_write_32(CORE_ADDR_BANK_Q_COEFF + i * sizeof(uint32_t), q_coeff[j+1]); // mind the +1!
+ fmc_write_32(CORE_ADDR_BANK_DP + i * sizeof(uint32_t), dp[j]);
+ fmc_write_32(CORE_ADDR_BANK_DQ + i * sizeof(uint32_t), dq[j]);
+ fmc_write_32(CORE_ADDR_BANK_QINV + i * sizeof(uint32_t), qinv[j]);
+ }
+ fmc_write_32(CORE_ADDR_BANK_P_COEFF + i * sizeof(uint32_t), p_coeff[0]); // j+1 is 0 by now, i is num_words_half
+ fmc_write_32(CORE_ADDR_BANK_Q_COEFF + i * sizeof(uint32_t), q_coeff[0]); // j+1 is 0 by now, i is num_words_half
+ }
+
+ // set parameters (there's no need to divide key length by two when CRT is enabled,
+ // the core takes care of that by itself automatically)
+ reg_mode = use_crt ? CORE_MODE_USING_CRT : CORE_MODE_WITHOUT_CRT;
+ reg_modulus_bits = key_length;
+ reg_exponent_bits = key_length;
+
+ fmc_write_32(CORE_ADDR_MODE, reg_mode);
+ fmc_write_32(CORE_ADDR_MODULUS_BITS, reg_modulus_bits);
+ fmc_write_32(CORE_ADDR_EXPONENT_BITS, reg_exponent_bits);
+
+ // clear 'next' control bit, then set 'next' control bit again to trigger new operation
+ reg_control = 0;
+ fmc_write_32(CORE_ADDR_CONTROL, reg_control);
+ reg_control = CORE_CONTROL_BIT_NEXT;
+ fmc_write_32(CORE_ADDR_CONTROL, reg_control);
+
+ // wait for 'ready' status bit to be set, also turn on the blue LED while the
+ // core is busy to allow precise measurement with a scope
+ num_cyc = 0;
+ do
+ { num_cyc++;
+ fmc_read_32(CORE_ADDR_STATUS, &reg_status);
+ }
+ while (!(reg_status & CORE_STATUS_BIT_VALID));
+
+ // read back s, xm and ym word-by-word
+ // the first time the function is called, we compare the mutated blinding
+ // factors to the known correct reference values
+ // if the very first mutation was ok, we overwrite the currently used
+ // factors with the mutated ones, so the next time we sign, the new
+ // mutated factors will be used
+ // we obviously only know the mutated pair of factors beforehand during the very first call,
+ // so we don't verify them starting from the second call, but the signature should
+ // always stay the same, so we always verify it
+ uint32_t s_word, xm_word, ym_word;
+ for (i=0, j=num_words-1; i<num_words; i++, j--)
+ { fmc_read_32(CORE_ADDR_BANK_S + i * sizeof(uint32_t), &s_word);
+ fmc_read_32(CORE_ADDR_BANK_XM + i * sizeof(uint32_t), &xm_word);
+ fmc_read_32(CORE_ADDR_BANK_YM + i * sizeof(uint32_t), &ym_word);
+
+ if (s_word != s[j]) return 0;
+
+ if (first_run)
+ { if (xm_word != xm[j]) return 0;
+ if (ym_word != ym[j]) return 0;
+ }
+ else
+ { x[j] = xm_word;
+ y[j] = ym_word;
+ }
+ }
+
+ // everything went just fine
+ return 1;
+}
+
+
+//
+// toggle the yellow led to indicate that we're not stuck somewhere
+//
+void toggle_yellow_led(void)
+{
+ static int led_state = 0;
+
+ led_state = !led_state;
+
+ if (led_state) led_on(LED_YELLOW);
+ else led_off(LED_YELLOW);
+}
+
+
+//
+// SysTick
+//
+void SysTick_Handler(void)
+{
+ HAL_IncTick();
+ HAL_SYSTICK_IRQHandler();
+}
+
+
+//
+// End-of-File
+//
diff --git a/stm32/modexpng_util.c b/stm32/modexpng_util.c
new file mode 100644
index 0000000..27afb19
--- /dev/null
+++ b/stm32/modexpng_util.c
@@ -0,0 +1,189 @@
+//
+// helper precomputation routines for the "modexpng" core
+//
+#include "modexpng_util.h"
+
+
+//
+// internal buffers
+//
+static uint32_t MOD_FACTOR_N[BUF_NUM_WORDS];
+static uint32_t MOD_NN[BUF_NUM_WORDS+1];
+static uint32_t MOD_T[BUF_NUM_WORDS+1];
+
+static void _add32(uint32_t, uint32_t, uint32_t, uint32_t *, uint32_t *);
+static void _sub32(uint32_t, uint32_t, uint32_t, uint32_t *, uint32_t *);
+static void _mul32(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t *, uint32_t *);
+
+
+//
+// calculation of the Montgomery factor
+//
+void _calc_montgomery_factor(uint32_t num_words, const uint32_t *N, uint32_t *N_FACTOR)
+{
+ // counters
+ uint32_t i, j;
+
+ // flag
+ uint32_t flag_keep;
+
+ // carry and borrow
+ uint32_t cry_in, cry_out;
+ uint32_t brw_in, brw_out;
+
+ // initially set N_FACTOR = 1
+ for (i=0; i<num_words; i++)
+ N_FACTOR[i] = i ? 0 : 1;
+
+ // do the math
+ for (i=0; i<2*(num_words * UINT32_BITS + UINT16_BITS); i++)
+ {
+ // clear carry and borrow
+ cry_in = 0, brw_in = 0;
+
+ // calculate N_FACTOR = N_FACTOR << 1, MOD_FACTOR_N = N_FACTOR - N
+ for (j=0; j<num_words; j++)
+ {
+ cry_out = N_FACTOR[j] >> (UINT32_BITS - 1); // | N_FACTOR <<= 1
+ N_FACTOR[j] <<= 1; N_FACTOR[j] |= cry_in; // |
+
+ _sub32(N_FACTOR[j], N[j], brw_in, &MOD_FACTOR_N[j], &brw_out); // MOD_FACTOR_N = N_FACTOR - N
+
+ // propagate carry & borrow
+ cry_in = cry_out, brw_in = brw_out;
+ }
+
+ // obtain flag
+ flag_keep = brw_out && !cry_out;
+
+ // now select the right value
+ for (j=0; j<num_words; j++)
+ N_FACTOR[j] = flag_keep ? N_FACTOR[j] : MOD_FACTOR_N[j];
+ }
+}
+
+
+//
+// calculation of the modulus-dependent speed-up coefficient
+//
+void _calc_modulus_coeff(uint32_t num_words, const uint32_t *N, uint32_t *N_COEFF)
+{
+ // counters
+ uint32_t i, j, k, jk;
+
+ // indices
+ uint32_t word_index, bit_index;
+
+ // flag
+ uint32_t flag_update;
+
+ // carries
+ uint32_t cry_in, cry_out;
+
+ // temporary variables
+ uint32_t mod_p, add_s, b_word;
+
+ // initially set N_COEFF to 1
+ for (i=0; i<=num_words; i++)
+ N_COEFF[i] = i ? 0 : 1;
+
+ // also set NN to ~N+1
+ // note that since N must be odd, ~N is even, so adding 1 to it doesn't need
+ // any carry propagation
+ for (i=0; i<num_words; i++) MOD_NN[i] = ~N[i];
+ MOD_NN[0] += 1;
+ MOD_NN[num_words] = 0xffffffff;
+
+ // do the math
+ for (i=1; i<(num_words * UINT32_BITS + UINT16_BITS); i++)
+ {
+ word_index = i / UINT32_BITS;
+ bit_index = i & (UINT32_BITS - 1);
+
+ // clear T
+ for (j=0; j<=num_words; j++) MOD_T[j] = 0;
+
+ // T = N_COEFF * NN mod 2 ** (modulus_length + 16)
+ /*
+ * Note, that we only need the lower half of the product T, so in
+ * the outer loop we always scan entire N_COEFF, but the inner
+ * loop only scans entire NN during the first iteration, and then
+ * keeps skipping one more word every iteration, during the last
+ * iteration we only scan one word of NN.
+ *
+ */
+ for (j=0; j<=num_words; j++)
+ { cry_in = 0;
+ for (k=0; k<=(num_words-j); k++)
+ { jk = j + k;
+ _mul32(N_COEFF[j], MOD_NN[k], MOD_T[jk], cry_in, &mod_p, &cry_out);
+ MOD_T[jk] = mod_p;
+ cry_in = cry_out;
+ if (word_index == jk)
+ flag_update = MOD_T[jk] & (1 << bit_index) ? 1 : 0;
+ }
+ }
+ if (flag_update)
+ { cry_in = 0;
+ for (j=0; j<=num_words; j++)
+ { b_word = (j == word_index) ? (1 << bit_index) : 0;
+ _add32(b_word, N_COEFF[j], cry_in, &add_s, &cry_out);
+ N_COEFF[j] = add_s;
+ cry_in = cry_out;
+ }
+ }
+ }
+}
+
+
+//
+// low-level addition w/ carry
+//
+static void _add32(uint32_t a, uint32_t b, uint32_t c_in, uint32_t *s, uint32_t *c_out)
+{
+ uint64_t t; // intermediate var
+
+ t = (uint64_t)a + (uint64_t)b; // obtain "wide" difference
+ t += (uint64_t)(c_in & 1); // take borrow into account
+
+ *s = (uint32_t)t; // return the lower part of result
+ *c_out = (uint32_t)(t >> UINT32_BITS); // return the higher part of result, ...
+ *c_out &= (uint32_t)1; // ...but truncate it to 1 bit
+}
+
+
+//
+// low-level subtraction w/ borrow
+//
+static void _sub32(uint32_t a, uint32_t b, uint32_t b_in, uint32_t *d, uint32_t *b_out)
+{
+ uint64_t t; // intermediate var
+
+ t = (uint64_t)a - (uint64_t)b; // obtain "wide" difference
+ t -= (uint64_t)(b_in & 1); // take borrow into account
+
+ *d = (uint32_t)t; // return the lower part of result
+ *b_out = (uint32_t)(t >> UINT32_BITS); // return the higher part of result, ...
+ *b_out &= (uint32_t)1; // ...but truncate it to 1 bit
+}
+
+
+//
+// low-level multiplication w/ carry and pre-adder
+//
+static void _mul32(uint32_t a, uint32_t b, uint32_t t, uint32_t c_in, uint32_t *p, uint32_t *c_out)
+{
+ uint64_t r; // intermediate result
+
+ r = (uint64_t)a * (uint64_t)b; // obtain wide product
+ r += (uint64_t)t; // handle pre-addition
+ r += (uint64_t)c_in; // take carry into account
+
+ *p = (uint32_t)r; // return the lower part of result
+ *c_out = (uint32_t)(r >> UINT32_BITS); // return the higher part of result, ...
+}
+
+
+//
+// end-of-file
+//
diff --git a/stm32/modexpng_util.h b/stm32/modexpng_util.h
new file mode 100644
index 0000000..a209f31
--- /dev/null
+++ b/stm32/modexpng_util.h
@@ -0,0 +1,30 @@
+//
+// helper precomputation routines for the "modexpng" core
+//
+
+
+//
+// headers
+//
+#include <stdint.h>
+
+
+//
+// defined values
+//
+#define UINT32_BITS (sizeof(uint32_t) << 3)
+#define UINT16_BITS (sizeof(uint16_t) << 3)
+
+#define BUF_NUM_WORDS (4096/UINT32_BITS)
+
+
+//
+// prototypes
+//
+void _calc_montgomery_factor(uint32_t, const uint32_t *, uint32_t *);
+void _calc_modulus_coeff(uint32_t, const uint32_t *, uint32_t *);
+
+
+//
+// end-of-file
+//
diff --git a/stm32/modexpng_vector_1024.h b/stm32/modexpng_vector_1024.h
new file mode 100644
index 0000000..e07b86c
--- /dev/null
+++ b/stm32/modexpng_vector_1024.h
@@ -0,0 +1,138 @@
+#define M_1024_INIT \
+ {0x002291d8, 0xcdc31041, 0x1e7ec273, 0x78a661c9, \
+ 0x35187c07, 0xe4d5636e, 0x9bc3c400, 0xb27244b8, \
+ 0xcd3a97f1, 0x1ae65107, 0x0506a68a, 0x02f0e161, \
+ 0xaf37f86c, 0xb9078738, 0xc370f07e, 0x8d3b583b, \
+ 0xad38c275, 0xf34aed05, 0x6ad6ea8e, 0xeca4192f, \
+ 0xa1feb9dc, 0x4b1ebe55, 0xe5b8f9b6, 0x80eff76c, \
+ 0x81d4e9ab, 0x304d4896, 0xf9e17fd8, 0xf0816496, \
+ 0xda087a3e, 0xbecc676a, 0xaa2c5d8c, 0xe1b3c6ac}
+#define N_1024_INIT \
+ {0xde97bb85, 0x05cae32b, 0x464817f5, 0x2ecbb15f, \
+ 0x5bc6b044, 0xe5a2bb93, 0x5f09d790, 0x25c2d4bb, \
+ 0x600fb6df, 0xc854e454, 0x17c32585, 0xdd2a44af, \
+ 0x106d9d82, 0xeeed776f, 0xef1f0436, 0x8ab3096e, \
+ 0xb1c59fab, 0x51966e1d, 0x46fd4a05, 0x9f98006b, \
+ 0xdad49a60, 0x7dce3d13, 0x0a98251a, 0x17972933, \
+ 0xaef9fda5, 0x83a33941, 0x7a10d0d1, 0x7507684c, \
+ 0x747e0580, 0x9ba95792, 0xef2df706, 0x6719997f}
+#define N_FACTOR_1024_INIT \
+ {0x42d541fb, 0xaed9b905, 0x4ee55bcf, 0xb0a0d098, \
+ 0x7b1f5cc6, 0xdafd920c, 0x9b884af9, 0x1ba098f3, \
+ 0x41a3a2cd, 0x17b7d05f, 0x749f81eb, 0x72eaf2e6, \
+ 0x276c6711, 0x3b9400d0, 0x4dd6ced0, 0x980d127e, \
+ 0x09e53d6a, 0xe6c59eb3, 0xb92857df, 0x08290d30, \
+ 0x027ff3bf, 0x0c565ecd, 0x34ede47a, 0x1e98bc21, \
+ 0xae540753, 0x029e13b8, 0xea78a046, 0xb275c37a, \
+ 0x04000838, 0x572d7a20, 0xc9974806, 0xa06a1113}
+#define N_COEFF_1024_INIT \
+ {0x00006545, 0x1d6b10db, 0x6baa4d60, 0x4fc717bd, \
+ 0xee05f26a, 0xee476d42, 0x40d342ef, 0xa127e4f3, \
+ 0xd1c67123, 0x6144156a, 0x189dc2cf, 0xc2d896f0, \
+ 0x111bd21e, 0xafa1ef25, 0xa2d0c26b, 0x9b63e6d2, \
+ 0x4fa810af, 0x950c171d, 0xbcdb1e94, 0x88bead48, \
+ 0xca16d0b9, 0x6d79c8b1, 0x8dd55dee, 0xfdcd0163, \
+ 0x62c5f506, 0x8e1bd1d6, 0xb704fb07, 0x515b0d96, \
+ 0x12665495, 0x11a3c01a, 0x268999ff, 0x9bf1c20c, \
+ 0xb383d981}
+#define X_1024_INIT \
+ {0x00f4dcf2, 0xd90e1715, 0x5cd52bbc, 0xcfabda4e, \
+ 0x409b369b, 0x0994ae28, 0xff6ea364, 0xcdb9dcfe, \
+ 0x82f35f8b, 0xef718044, 0xe609de07, 0x5d77ee51, \
+ 0xe8616ce4, 0xe2862a8f, 0x2d3c3b06, 0x2d532c22, \
+ 0x82825cff, 0x83ac8f2e, 0xfee472cb, 0x6abc86e8, \
+ 0xe8c35dca, 0x975a5cfb, 0xdbf67229, 0xf4c166b7, \
+ 0xbd76a787, 0x3f7d47ec, 0x7f8083d4, 0xcb5aa9e2, \
+ 0x74e6e776, 0x5991b9eb, 0x8eb9747c, 0xa838f053}
+#define Y_1024_INIT \
+ {0x91305f4c, 0xf19f3050, 0xf1f87f7e, 0xbb98b1f6, \
+ 0xabc2e23e, 0x9c40b33d, 0x446e04de, 0xb17d4f5d, \
+ 0x7d899cd7, 0xd044c7e2, 0x94b71191, 0x5606786a, \
+ 0xc3c1af70, 0x731977a3, 0xca5e7ac3, 0x8f2701dd, \
+ 0x31d77884, 0x121e3dac, 0x6d758eaa, 0x9fe3f32a, \
+ 0xe6ee62ca, 0x59fe5575, 0x6b8a8bf6, 0xfbbfd687, \
+ 0xa53e97db, 0xb18d9ee1, 0xa8f79f3b, 0x98c812b4, \
+ 0x1cda0da7, 0x6d55dc06, 0x04ff1664, 0x01b2730a}
+#define P_1024_INIT \
+ {0xefffa822, 0x9bc50e5d, 0x5b5300b2, 0xbc198e83, \
+ 0x433f41af, 0x563cd266, 0x958717ca, 0xebfd5f0a, \
+ 0x28b132db, 0x90c102ef, 0xef4a17fd, 0xe2ddbbc7, \
+ 0xc8d3fa09, 0x042c6647, 0x08588a44, 0x18bb0f97}
+#define Q_1024_INIT \
+ {0xed6efcd0, 0x14c86644, 0x7e267974, 0x8e5f59d6, \
+ 0xef0d4b5b, 0x20ae39c0, 0xd6779694, 0x646547e1, \
+ 0xce1d017c, 0xcce7aed3, 0xc53e71ac, 0xbfd89a48, \
+ 0x9bf274e0, 0x613815b3, 0xd81461d0, 0x25de0259}
+#define P_FACTOR_1024_INIT \
+ {0x0acdced0, 0xd390be70, 0xa53994af, 0x04d1d543, \
+ 0x5ecd6b04, 0x548960b5, 0x93388ec6, 0x51098b50, \
+ 0xc350e206, 0x48cbad9c, 0xd7c43f9e, 0x1a972b27, \
+ 0x1a697756, 0x10b70a9a, 0xbcee5381, 0x614f99ce}
+#define Q_FACTOR_1024_INIT \
+ {0x4a834535, 0x86506b4d, 0x96e41677, 0x13a3742d, \
+ 0x89af91e7, 0xb860c105, 0xed14f573, 0x2c197fcc, \
+ 0x3d59bd42, 0xba703ab1, 0xd50817dd, 0x8465f60f, \
+ 0x5a7eba92, 0x26ed5239, 0x9d729c78, 0x8a19423f}
+#define P_COEFF_1024_INIT \
+ {0x0000f994, 0x22d9c54e, 0xf7032ac2, 0x39c00ed8, \
+ 0xc3e2f78c, 0x342901dc, 0xf04a610d, 0x279bdff7, \
+ 0x5cdc4e60, 0x8c257cb0, 0x29e9942f, 0xf04eebf8, \
+ 0x023bda43, 0x99012919, 0xf0e82022, 0xde24e467, \
+ 0xb3679fd9}
+#define Q_COEFF_1024_INIT \
+ {0x0000ed75, 0x50a5dd76, 0xe10d29a8, 0xae42d654, \
+ 0x8d6a5911, 0xe9527ead, 0x331e61cb, 0x4911b74e, \
+ 0x0cf1175c, 0x95bf6eb2, 0x69beef2d, 0x2176cace, \
+ 0x56722aa8, 0x5c952a67, 0xd0b854bc, 0xa4b101fa, \
+ 0x95beda17}
+#define D_1024_INIT \
+ {0x6915229e, 0xa2e46c28, 0x32ceb818, 0xb495cecf, \
+ 0xa0c904d0, 0x11c4a85e, 0xe3400736, 0xf2ccae97, \
+ 0x22bb686e, 0xeee93cbd, 0x82564b31, 0x8dfe755c, \
+ 0x5c1a1381, 0x0b80a9a0, 0xfb371e4b, 0x0d618632, \
+ 0x8d6fde7f, 0x28eeceb0, 0x793bfff7, 0x0b2259bf, \
+ 0x845b6e48, 0x4d8a15bf, 0x362966c6, 0xb8624e9a, \
+ 0xc31450bd, 0x0e0fdec4, 0xfe6ade84, 0x3247b99f, \
+ 0x07207984, 0x3b47788f, 0xa96f72d6, 0x6d4e7831}
+#define DP_1024_INIT \
+ {0x9c2bcaa7, 0x2aa1e225, 0x11c64350, 0x0b62bdff, \
+ 0xe0848b23, 0xa384548d, 0x7883be11, 0xc7daca3b, \
+ 0x7c1b42b2, 0xe9d10f2e, 0x3e920266, 0xad780837, \
+ 0x8b119544, 0xc4b8779d, 0x856ac81e, 0x63d165e5}
+#define DQ_1024_INIT \
+ {0x99e0f684, 0x3d13ec03, 0xb3e6678c, 0xbcc0db4e, \
+ 0xcb3b487d, 0x54ded59b, 0x3ee3de79, 0x69dfa208, \
+ 0x9c367c42, 0x4fe24f91, 0xfc218e36, 0xb1574616, \
+ 0x8ccb4428, 0x2f99d3a6, 0xed01b8aa, 0xd7ffdc71}
+#define QINV_1024_INIT \
+ {0xa023ba44, 0x473d0d6d, 0xba76dc50, 0xaf54b86c, \
+ 0xe4dcd058, 0x8275500c, 0xe15b6b5e, 0x6779dd63, \
+ 0x689ee4a7, 0x8d8dfa35, 0x7538b796, 0x94667476, \
+ 0x0e876a42, 0xb61201fa, 0x4a8075a5, 0x9a2f0db2}
+#define XM_1024_INIT \
+ {0x5be48377, 0xbc796763, 0x9b9bd5a2, 0x24397651, \
+ 0xcb888210, 0xef88e7fd, 0xdc5d3b10, 0x9b648da0, \
+ 0x463701cc, 0x7d2df198, 0xd874a710, 0x1cf10b4a, \
+ 0x6c1d5e46, 0x32b237a8, 0xb29be7b6, 0x9eb98306, \
+ 0x33187c87, 0x10e7f813, 0x351d9416, 0xe43762bf, \
+ 0xc992252e, 0xb463d63d, 0x01c7289a, 0xaa1fe167, \
+ 0x3c3821a2, 0x637a9f36, 0x077bf4a3, 0x494825f4, \
+ 0xf74f1735, 0xe8044305, 0xf47b497a, 0x9b067dd2}
+#define YM_1024_INIT \
+ {0xc0376429, 0x1a93390c, 0xa57103d4, 0x2f9fd9ce, \
+ 0x1bab454e, 0x829186bb, 0xddc1b0fd, 0x9911c92d, \
+ 0xc27be96a, 0x772d786a, 0x3e4e2162, 0xe73efaa1, \
+ 0xd49567f2, 0x5539e56e, 0x654f94e8, 0x71258bb8, \
+ 0xb898d5b6, 0x2e71b229, 0x02aea3f6, 0x3974d1b2, \
+ 0xa6ddd3c9, 0x37846437, 0x3862aa1a, 0x73013f57, \
+ 0x91ef1342, 0x25c2377e, 0x66e52536, 0xf83145f4, \
+ 0x3b775d20, 0x0d4983a2, 0x6885ed1d, 0x78aba2bd}
+#define S_1024_INIT \
+ {0x66da2c5a, 0x7eec7f9d, 0xe33612c7, 0xbf3d7945, \
+ 0x0f8161fe, 0x318fc8e1, 0x842821bc, 0x1dfc9178, \
+ 0xaa40acba, 0x8e4d5e53, 0xe6dc5c88, 0xb0fcabdd, \
+ 0x5d7bb220, 0xf62193e6, 0xbcc7783c, 0x2a7e0970, \
+ 0x54758bc4, 0x035044b1, 0x3366f4f0, 0xd3704e85, \
+ 0x65e2b7a2, 0x9f331c40, 0x6da8dcd4, 0xf4807458, \
+ 0x4b572f47, 0x9184f0b5, 0x9ac7dbb0, 0x747947ce, \
+ 0x8282e4f4, 0x8758f3f6, 0xababa077, 0x8eb4aa6e}
diff --git a/stm32/modexpng_vector_2048.h b/stm32/modexpng_vector_2048.h
new file mode 100644
index 0000000..0826a41
--- /dev/null
+++ b/stm32/modexpng_vector_2048.h
@@ -0,0 +1,254 @@
+#define M_2048_INIT \
+ {0x002291d8, 0xcdc31041, 0x1e7ec273, 0x78a661c9, \
+ 0x35187c07, 0xe4d5636e, 0x9bc3c400, 0xb27244b8, \
+ 0xcd3a97f1, 0x1ae65107, 0x0506a68a, 0x02f0e161, \
+ 0xaf37f86c, 0xb9078738, 0xc370f07e, 0x8d3b583b, \
+ 0xad38c275, 0xf34aed05, 0x6ad6ea8e, 0xeca4192f, \
+ 0xa1feb9dc, 0x4b1ebe55, 0xe5b8f9b6, 0x80eff76c, \
+ 0x81d4e9ab, 0x304d4896, 0xf9e17fd8, 0xf0816496, \
+ 0xda087a3e, 0xbecc676a, 0xaa2c5d8c, 0xe1b3c6ac, \
+ 0xbc5f1670, 0xa9821bc7, 0x2985d764, 0x5e7dbb07, \
+ 0x780b4eb4, 0xd9fb9d97, 0x9464a52b, 0x2b803afb, \
+ 0x03c5338a, 0xebdc8c3b, 0x678358f3, 0xd8935a75, \
+ 0xe844a88c, 0x9bf5ba01, 0x62c8dbd2, 0xf4e2f0bd, \
+ 0x83cf2184, 0xc78f346d, 0xf30e7bde, 0x5d918d33, \
+ 0xf081697c, 0xd05b6a58, 0x00898a9f, 0xc99c5475, \
+ 0x9907cd3a, 0xa22d8c95, 0x2edc17cc, 0x8dccd9d1, \
+ 0xee4108d7, 0xf1ac1215, 0xde047303, 0xc1c1473f}
+#define N_2048_INIT \
+ {0xd82cbb4a, 0x7b6b057d, 0x93bc6e12, 0x1615956b, \
+ 0xd0b7aba7, 0x9e5ba014, 0x1cc0fc63, 0x48dd42ed, \
+ 0x3dc4904e, 0x66c6605f, 0x751bfced, 0x135c6703, \
+ 0x46c37da7, 0xc39440aa, 0xb20b6995, 0x802a2cb1, \
+ 0xf531a4b4, 0xe702a248, 0x5c9109d3, 0x9c2e41d7, \
+ 0x28832979, 0x04c89899, 0x691c4bcc, 0xf10f44a3, \
+ 0x5e35a701, 0x75d2ff00, 0x835c1945, 0x2d3ce223, \
+ 0xb894d90e, 0xebacebcc, 0x08951d2a, 0xa08d18ce, \
+ 0x24147c14, 0xfc985600, 0xf2f00a86, 0x3df554a7, \
+ 0xd0f76f0d, 0x24a27f30, 0x70ca2377, 0xc97292aa, \
+ 0xd80a02b1, 0xd3b098d2, 0xbb8e6755, 0x1bf2533b, \
+ 0xcda2b067, 0x8d0dad30, 0xf7090c5c, 0x196254e1, \
+ 0x955a8527, 0xbd29c63b, 0x10020dd5, 0x97260509, \
+ 0x0a2dd5e6, 0x4aed6113, 0x4f636d78, 0xe3c192d8, \
+ 0xe1280048, 0x3a0eb61e, 0x6a830b2d, 0xfd4e69da, \
+ 0xc850335d, 0x04886009, 0x0b1534d8, 0xf2d026d3}
+#define N_FACTOR_2048_INIT \
+ {0x814227f1, 0x17ae17f4, 0x26e65c79, 0x1abb99dc, \
+ 0x93491025, 0x8202e00c, 0x76ecd5e2, 0xd82cdc62, \
+ 0x59884542, 0x316a0981, 0x9270495d, 0xfdfdad32, \
+ 0x5dd0428e, 0x669cfd54, 0x1caf2c67, 0x85810894, \
+ 0x7ed108cb, 0x41352317, 0x0a4cb7b1, 0x0c025a58, \
+ 0x862995aa, 0xcbcb6ceb, 0x44453aed, 0x6c8aea02, \
+ 0x204b54b2, 0x3b2d5edb, 0x6a3aa436, 0x69a11f19, \
+ 0xbdcf892e, 0x20b839aa, 0x357c3932, 0x6c743160, \
+ 0xbdc410e1, 0x3eb178cb, 0x6b1b30a1, 0x87d4fa2a, \
+ 0x10ddb3b8, 0xb91b183e, 0x549ff466, 0x7f179e76, \
+ 0x0525602c, 0xbd93586f, 0x28e4c46b, 0x6729c6fa, \
+ 0x58aedc1e, 0x399382e4, 0x141c3490, 0x141d5169, \
+ 0xe93fd2b1, 0x1f4a30b7, 0x2377dba3, 0xde705b6a, \
+ 0x432efe3d, 0x62509e40, 0x718984a3, 0xdb252caa, \
+ 0x35f135f6, 0xd9bcdf56, 0x48fb1cb9, 0x9509d41a, \
+ 0xffa19a1c, 0xb4529d64, 0xfee48017, 0x20b51222}
+#define N_COEFF_2048_INIT \
+ {0x0000230e, 0x4f7c9cc3, 0xa30db1d3, 0x96866233, \
+ 0xb2c2c944, 0xd21e7b6b, 0x26270e66, 0x34e92a94, \
+ 0x6b048552, 0xb03af0f0, 0xbad6a264, 0xddd9190e, \
+ 0x2484414c, 0x18c5957f, 0x0666b1f1, 0x465142b8, \
+ 0x9bfe0bc7, 0x6aeeccde, 0x89c96f7a, 0x31f0ff9a, \
+ 0x63037214, 0x96edc3ea, 0xbd82295f, 0x9f6c0cb5, \
+ 0xc1348f9d, 0x16fd36c3, 0x70192867, 0x50ba4eeb, \
+ 0xc11124a8, 0xa7195773, 0xb72605f4, 0x28958340, \
+ 0xd0db455d, 0x3cd40c85, 0xff2a7256, 0xc96f0706, \
+ 0xe9c7b93f, 0x57836dbb, 0x1a2893cc, 0xf23a49ac, \
+ 0x6296dc27, 0xace1a4ee, 0x5ed0c317, 0x35c59908, \
+ 0x44753f60, 0x3d8f25c8, 0xcb62c5d7, 0xe95a72c9, \
+ 0x566a98f4, 0x81fa5df5, 0xc5742a96, 0x7c0fe404, \
+ 0x976646fb, 0xf6ffe021, 0x3add83ac, 0xce8c7a02, \
+ 0x27ced42c, 0x0e099d02, 0x583c94a8, 0x59ce866c, \
+ 0x45000e17, 0x700d8af5, 0xbabd9dd6, 0x9b6d6280, \
+ 0x05a4dea5}
+#define X_2048_INIT \
+ {0x00f4dcf2, 0xd90e1715, 0x5cd52bbc, 0xcfabda4e, \
+ 0x409b369b, 0x0994ae28, 0xff6ea364, 0xcdb9dcfe, \
+ 0x82f35f8b, 0xef718044, 0xe609de07, 0x5d77ee51, \
+ 0xe8616ce4, 0xe2862a8f, 0x2d3c3b06, 0x2d532c22, \
+ 0x82825cff, 0x83ac8f2e, 0xfee472cb, 0x6abc86e8, \
+ 0xe8c35dca, 0x975a5cfb, 0xdbf67229, 0xf4c166b7, \
+ 0xbd76a787, 0x3f7d47ec, 0x7f8083d4, 0xcb5aa9e2, \
+ 0x74e6e776, 0x5991b9eb, 0x8eb9747c, 0xa838f053, \
+ 0xd0b3d52a, 0xe0e89d44, 0xc5e97a4f, 0x4df5ccb4, \
+ 0xd4818f84, 0x81a69d96, 0x684fbb35, 0x7d835def, \
+ 0xaf9fe113, 0xc8d257b9, 0x02e8d030, 0xffbe1b0f, \
+ 0x93a70c45, 0x973aaee0, 0xea1bc185, 0x22da443e, \
+ 0xd335f1e1, 0x0f6ce5b7, 0xc2080e5c, 0x5c2c3fac, \
+ 0x06151df4, 0x11060aba, 0xeb055f41, 0x20d0ef28, \
+ 0xbc2f85b1, 0x0062960b, 0xcbfd3f26, 0xf8090158, \
+ 0xf09da0be, 0xbf1c4956, 0x7d074e72, 0x8dc49abd}
+#define Y_2048_INIT \
+ {0x0976f869, 0x79d2709f, 0x2bd01d0b, 0x42d1a017, \
+ 0x77584369, 0x63a84f5b, 0xe5a424fc, 0xf2496f1c, \
+ 0x03e1b01c, 0xe17822f3, 0x8489af36, 0x01b85c64, \
+ 0xc1d956a2, 0xdb4caf37, 0x7ce1bb31, 0x7d51e611, \
+ 0xfd9d0fcb, 0x93b23236, 0xce46c707, 0x6e1b794b, \
+ 0x3034317a, 0x64c24fe7, 0xae18f26b, 0x2b9e6888, \
+ 0x167e4b9b, 0x79f8b5f8, 0x2916f577, 0x1e47373b, \
+ 0xaf37ea80, 0x4fe10e7e, 0x12e37006, 0x71193164, \
+ 0xe0c57fed, 0x2c994650, 0xead7cfe5, 0xdf33ac9d, \
+ 0x9afa0038, 0x4520d430, 0x6950d11f, 0xa30fa3e3, \
+ 0xf7e7228d, 0xb04a0047, 0x784ebb6b, 0x17a95bf3, \
+ 0x222f6eab, 0x536e1add, 0x88063bf2, 0x2c9dc31e, \
+ 0xa040946d, 0xd20d52a1, 0xe8f0a185, 0x369f9d5f, \
+ 0x47c6b7ea, 0x3c6cc5bc, 0x479bdab5, 0xf4e0cfe0, \
+ 0x8fee2667, 0x5b4d6230, 0xb330ef9d, 0x7a0226dd, \
+ 0x860c71db, 0x00a02a8c, 0x01012bbf, 0xf46afc19}
+#define P_2048_INIT \
+ {0xf66e84bb, 0x03961240, 0x504cb7ab, 0x43537a51, \
+ 0xa5cca453, 0x3e6f6ca3, 0x88229106, 0x808dac6e, \
+ 0x77d38e83, 0x9e03a391, 0x34851c73, 0xc477d84e, \
+ 0x317e6eca, 0xc9951868, 0xe9687b04, 0x1767f8da, \
+ 0x4c9bd43f, 0x03138fec, 0xc09be37a, 0xd8728306, \
+ 0x37607aa5, 0x33b86dd7, 0xb7cda3f0, 0x8e6eb799, \
+ 0x536eb211, 0x4397a9cd, 0x979048b9, 0x3154815f, \
+ 0xa71652f8, 0xf76820d1, 0x8a67872d, 0x42d2dbff}
+#define Q_2048_INIT \
+ {0xe0917700, 0x4d8dcdbf, 0x8193dbe7, 0xf660571a, \
+ 0xb831f6bc, 0xbcc05683, 0xb2f698ce, 0x71d440f5, \
+ 0x36183800, 0x6cc7b568, 0xaee8f151, 0x9d05c38c, \
+ 0xf3a45bd4, 0xb8de68ca, 0x817ef26e, 0xf7196058, \
+ 0xbd56f7ff, 0x8706478f, 0x2afbb654, 0xd11d76bc, \
+ 0x995af309, 0xa60f1cd2, 0x100f8306, 0x2020a024, \
+ 0xab3f63ae, 0xbc087521, 0xd56160cb, 0xa23ba129, \
+ 0x77adb7de, 0xfa683a0c, 0xdf759183, 0xa88c852d}
+#define P_FACTOR_2048_INIT \
+ {0x1c54bc5a, 0xe6b9eff3, 0x564ba141, 0xa632f9fe, \
+ 0x229e3363, 0x37d517e9, 0xe3a6a808, 0x4060b34f, \
+ 0x6ed77bce, 0x1528c4a9, 0x25aada03, 0x7f57f409, \
+ 0xccab79ac, 0xa1c400f5, 0xc7ff33ba, 0x055a978e, \
+ 0x375ebf5c, 0xe7243913, 0x5c020cc8, 0x207d9afd, \
+ 0xaf6d61ec, 0xd923676c, 0xdf634245, 0x7bd6554f, \
+ 0xc0bd2504, 0x66a8432a, 0x1d7780c1, 0x0d43d405, \
+ 0xaae18691, 0xeb3e2beb, 0xed9931ca, 0xf5fa8c13}
+#define Q_FACTOR_2048_INIT \
+ {0x7bc1400c, 0x6a4c87ec, 0xf4a1d8e4, 0x74016ddb, \
+ 0xcaa8316c, 0x8a970417, 0xa260ee7d, 0xbe46b1b4, \
+ 0x2bd8a9b5, 0x456a2349, 0x04ec097c, 0xf7a02886, \
+ 0xd9d313c5, 0xef5bc409, 0xad5e5060, 0x759cac4a, \
+ 0x7a3b1471, 0xfdbf61e5, 0x46ce118d, 0x9507d565, \
+ 0xbd8953df, 0xf1dd3ab6, 0x441ef9d6, 0x0c8b766c, \
+ 0xa9e04c3d, 0x7dffa225, 0xdfbb7a37, 0x217b371c, \
+ 0x856ef162, 0x89ce5d48, 0xa8842c6d, 0x04cdfb94}
+#define P_COEFF_2048_INIT \
+ {0x00009818, 0x3e7a33e2, 0x30470c22, 0x3e7736d0, \
+ 0xf0f8eece, 0x9ae5300f, 0x815972f9, 0x769e65c3, \
+ 0x9542e3c3, 0x962ef159, 0x45cc27f2, 0xc38b04cc, \
+ 0xb59ace31, 0xf1aaeea1, 0x33c03fb2, 0xc78ccb58, \
+ 0x30093ad0, 0xb32b6cbc, 0x9126ef7a, 0x0e00c96e, \
+ 0x3034ca7c, 0x6ba89bac, 0x5b4ed0f1, 0x5ba23398, \
+ 0xa0561e63, 0xd1f4133b, 0xf1dffb42, 0xd819e18d, \
+ 0x99c66de5, 0x0a023ce8, 0xb816f4ab, 0xca007f24, \
+ 0xafe2dc01}
+#define Q_COEFF_2048_INIT \
+ {0x0000cb39, 0xd96d3d0f, 0x5e922f3c, 0x370e7bf2, \
+ 0xd7f5bd65, 0x6cbce9e7, 0x5caae0bd, 0xf0630aec, \
+ 0x7eb13b70, 0x3056ed56, 0xbeddd836, 0x1a931769, \
+ 0x9a8cef54, 0xc2ad0ff8, 0x369466e7, 0xc601bb9e, \
+ 0xa0158ecc, 0xdb107e31, 0xb12cc9ce, 0x0f833d91, \
+ 0xa08b5dc1, 0xfda44c9f, 0x66b9b4cf, 0x4de7053c, \
+ 0xfacaaf0c, 0x55e67842, 0x9b371879, 0x53fe780b, \
+ 0x54d074c3, 0xb410716a, 0x8a33e065, 0xa978eaff, \
+ 0xd70aed5b}
+#define D_2048_INIT \
+ {0x0e1d4591, 0x4463a575, 0x208b4208, 0x8e46947d, \
+ 0xf89fb566, 0x7951742f, 0x3bfd61bd, 0x3dc9ac8f, \
+ 0xfee371a4, 0x9cd34101, 0x9a8cdc43, 0xc26adb12, \
+ 0xfcb0d0e8, 0x7e3d94c7, 0x505eac63, 0x257e1b72, \
+ 0xf71669b1, 0xa20faaf6, 0xdc8c5fbe, 0xe048a8e5, \
+ 0xda704de9, 0xe7e50d09, 0x9f3248c4, 0xb5cc9067, \
+ 0xb643fc86, 0x7ce1ece2, 0x64b143b9, 0x1f8e0519, \
+ 0xddf861ff, 0xb66590f3, 0xbe6fb5fa, 0xcd86c8e2, \
+ 0xb5f9abb3, 0xaf1d2883, 0x445c5520, 0xe2db402d, \
+ 0x4681769d, 0xe5f1e6d3, 0x171d59ff, 0x46d98061, \
+ 0x181fe73f, 0xfa08f5d5, 0x3baf4909, 0xb85bdc89, \
+ 0x44172db2, 0x94f6a1fe, 0xa9029cf4, 0x8c504a3e, \
+ 0x883d9a76, 0x276e57e1, 0x45086a50, 0xe4c55231, \
+ 0x209916b2, 0xe0015f71, 0x7e76c6ed, 0xc3796720, \
+ 0x873efc90, 0x2e788008, 0x8267d69f, 0x8be92f90, \
+ 0xe6680f51, 0x38faa8e3, 0xb2a90e35, 0x92decb19}
+#define DP_2048_INIT \
+ {0x6fd7d905, 0xc7aae4bd, 0xabb425e7, 0xe4b68e5d, \
+ 0x601270c2, 0x17241afa, 0x5d5ed2d3, 0x50a4fc0d, \
+ 0x66f4ed49, 0x6efdd7ce, 0x9f378aa2, 0x4018e463, \
+ 0x18b37935, 0x30282adb, 0xf29328c1, 0xc29dbda3, \
+ 0xd6012363, 0x35d23b10, 0x089ab7b3, 0x9968df6e, \
+ 0x82d396d6, 0x439300c7, 0x56f44de3, 0x6fc17032, \
+ 0x765b5715, 0xdec78699, 0x78a05361, 0x39b250c5, \
+ 0x48e028e8, 0x35e15c83, 0xbd7d1f2c, 0xbb9757a1}
+#define DQ_2048_INIT \
+ {0x2d981b2b, 0x2a93d1e4, 0x41f0bd43, 0x39589216, \
+ 0xd0b3043f, 0x89ab1b65, 0x9dde4764, 0x12e45f53, \
+ 0xe9e9bce5, 0x0930fafa, 0x08192f75, 0xbc85c110, \
+ 0x4b1f61ad, 0xace32b2f, 0x825f3de5, 0x9db1bf48, \
+ 0x0519353c, 0xe2333a30, 0x2d2ff1f3, 0x028a12e3, \
+ 0x73d76d64, 0xd61c5763, 0xa6f31f4d, 0x0d14d2ae, \
+ 0xdf3dfd85, 0x2a942503, 0xfb88cbd8, 0x4c560300, \
+ 0xa255d8f1, 0x22b22aa7, 0x166f8e5d, 0xc6c8d0f9}
+#define QINV_2048_INIT \
+ {0x876b0113, 0xa6687bf5, 0xf44e9559, 0x282e85e8, \
+ 0x5d97f63a, 0x4d25bd0f, 0x789da73b, 0xf143041d, \
+ 0x8c017788, 0xa9378f83, 0x3e786540, 0x10c02935, \
+ 0xb9f9ce28, 0xaa230096, 0xbb854c5b, 0xcd4caf24, \
+ 0x6ae4579a, 0xaf7a5004, 0x09dbff62, 0x1a2552c3, \
+ 0x7912e4be, 0x16a740b9, 0x4506265d, 0x50764789, \
+ 0x81f041da, 0x6e4ef65e, 0x5e8ec3fc, 0x05b2cd9b, \
+ 0x8cdb97e8, 0x2cf48823, 0x2519090d, 0xea329077}
+#define XM_2048_INIT \
+ {0x64f582b3, 0xdcada152, 0xae173205, 0x5ed7798a, \
+ 0x2dc1f065, 0xe139a2fa, 0xb8a3007c, 0xbad1e200, \
+ 0x176a68e6, 0x597b3f3c, 0xc489b343, 0x520dbc34, \
+ 0x1973c333, 0x5085c769, 0xb78630e2, 0x95228e3b, \
+ 0x5b0db7d6, 0x952ecf74, 0x3e06abfe, 0xa72efe6f, \
+ 0x0ece731f, 0x5f7f9065, 0x7f316f00, 0x8c37cb89, \
+ 0x9215c310, 0x7a4cd2d5, 0x1d74f723, 0xddab2700, \
+ 0xb5b7aa87, 0x63bc09ef, 0x3409d43e, 0x7bae4bee, \
+ 0xb8abad58, 0x5124b079, 0xefcbca8c, 0xc7c85d5b, \
+ 0x4d42cce3, 0xbdf64c27, 0xf41ffc8b, 0xea16caa0, \
+ 0xe803b480, 0x2b8ad2b8, 0xb8fe9d93, 0x3f375b49, \
+ 0x4c5c7864, 0xea1b5678, 0xb0ef222c, 0x19312a66, \
+ 0xde874b57, 0x001907c7, 0x5519573a, 0x57b4ea26, \
+ 0x7c73fd4b, 0x8c57f388, 0xfe946879, 0x4017f2e8, \
+ 0x39b0e376, 0xb4c961b6, 0xc9f64350, 0x20a9ae9c, \
+ 0x6d673eec, 0x54ab3f2c, 0x5ca3085e, 0x6a0cea69}
+#define YM_2048_INIT \
+ {0x16428fa3, 0xf7d01e5b, 0x672ffe87, 0x2dd094b6, \
+ 0xc39b8c3a, 0x0530c011, 0xe5a2b7fc, 0xc06e2e6a, \
+ 0xa0e2cd7d, 0x81af0174, 0xc10154b0, 0x0063c708, \
+ 0x878362fc, 0x1f7f1202, 0x45726416, 0x931f2598, \
+ 0x48b00e7f, 0x59e400ed, 0x2294ef19, 0xad012566, \
+ 0x0216925f, 0x0baa3e88, 0xf2aaa297, 0x1c7371ce, \
+ 0xdc99c0b8, 0x57acf152, 0xee4463f8, 0xe2ac7831, \
+ 0x172155ae, 0x53bd0911, 0x1fcf4c83, 0x9b8a1643, \
+ 0xe483eda7, 0x8757709f, 0x485d258b, 0x27b62b73, \
+ 0x83b2817e, 0x456f92cb, 0x21903504, 0x3a75c144, \
+ 0xbd8aaab4, 0xcdfb3a8c, 0x45161486, 0x29a88ada, \
+ 0xc9d4a900, 0xc2601946, 0x6936e7a9, 0xf7f3fdaf, \
+ 0xbc8cdfb2, 0xf08393a3, 0x002620d9, 0xe5644d38, \
+ 0x04d1f8b0, 0xd6367af8, 0x158e5df4, 0x1ca45c8f, \
+ 0x6cb3fbef, 0x252e6e62, 0x17a183d7, 0x4d88dd01, \
+ 0x30fd6d20, 0xa358cb01, 0x1a75f7b1, 0x2b75a88f}
+#define S_2048_INIT \
+ {0x43307893, 0x43a70c14, 0xe4653d3f, 0x02b29340, \
+ 0x12972837, 0xb764d650, 0x23be1bb0, 0xf994111e, \
+ 0xfa709394, 0xf0b9ee43, 0x1c4d4fbf, 0xf4218a75, \
+ 0xd2087628, 0x69e19a4a, 0x8635a29e, 0x1ec99ffa, \
+ 0x2047ce24, 0x611bb37a, 0xaeb953a3, 0xd5b1588e, \
+ 0x2ed60dc4, 0x5bf6c44d, 0xc8b1317d, 0x18590f74, \
+ 0x88f813f7, 0x46e19e70, 0xe1bca2a6, 0x120cde82, \
+ 0xac2c9285, 0xdd399dbd, 0x2afb700a, 0xe367eff4, \
+ 0xd2b61bbb, 0xd54e3c73, 0x7229c502, 0x02f5a3f1, \
+ 0x561d65d0, 0xd6fd7420, 0x3838696e, 0x40d25a4a, \
+ 0xf2340eaa, 0x5b511956, 0xf63d5a71, 0x348526ad, \
+ 0x229c27c3, 0x10d4eec1, 0x48c09d20, 0xe0ccd7e8, \
+ 0x4b5e1a29, 0xef0b106b, 0x10496bc0, 0x63b3ff03, \
+ 0xc1657d2a, 0x9c8d4347, 0xce4920b8, 0xd01c7e2b, \
+ 0x4949522e, 0x5a2fc48f, 0xe2fa26cc, 0x298afd01, \
+ 0x41e7f5a0, 0xf350d7b2, 0x918306bc, 0x1dca4f8d}
diff --git a/stm32/modexpng_vector_4096.h b/stm32/modexpng_vector_4096.h
new file mode 100644
index 0000000..978bc96
--- /dev/null
+++ b/stm32/modexpng_vector_4096.h
@@ -0,0 +1,486 @@
+#define M_4096_INIT \
+ {0x002291d8, 0xcdc31041, 0x1e7ec273, 0x78a661c9, \
+ 0x35187c07, 0xe4d5636e, 0x9bc3c400, 0xb27244b8, \
+ 0xcd3a97f1, 0x1ae65107, 0x0506a68a, 0x02f0e161, \
+ 0xaf37f86c, 0xb9078738, 0xc370f07e, 0x8d3b583b, \
+ 0xad38c275, 0xf34aed05, 0x6ad6ea8e, 0xeca4192f, \
+ 0xa1feb9dc, 0x4b1ebe55, 0xe5b8f9b6, 0x80eff76c, \
+ 0x81d4e9ab, 0x304d4896, 0xf9e17fd8, 0xf0816496, \
+ 0xda087a3e, 0xbecc676a, 0xaa2c5d8c, 0xe1b3c6ac, \
+ 0xbc5f1670, 0xa9821bc7, 0x2985d764, 0x5e7dbb07, \
+ 0x780b4eb4, 0xd9fb9d97, 0x9464a52b, 0x2b803afb, \
+ 0x03c5338a, 0xebdc8c3b, 0x678358f3, 0xd8935a75, \
+ 0xe844a88c, 0x9bf5ba01, 0x62c8dbd2, 0xf4e2f0bd, \
+ 0x83cf2184, 0xc78f346d, 0xf30e7bde, 0x5d918d33, \
+ 0xf081697c, 0xd05b6a58, 0x00898a9f, 0xc99c5475, \
+ 0x9907cd3a, 0xa22d8c95, 0x2edc17cc, 0x8dccd9d1, \
+ 0xee4108d7, 0xf1ac1215, 0xde047303, 0xc1c1473f, \
+ 0x441ccc9f, 0x2f584a11, 0x2a284187, 0xf32ba845, \
+ 0xa5b64b74, 0xb3527f79, 0x1d064f62, 0x576bcb30, \
+ 0x421b40e6, 0xba82fa35, 0xf79b6ed1, 0xf9053904, \
+ 0x652509b8, 0xf52972b4, 0x81ad6d8b, 0xd538faf9, \
+ 0xa1ccb184, 0x733986a6, 0x0765ac93, 0xcd52a8a1, \
+ 0x6d0fbc4c, 0x20f736e0, 0x0c4e12db, 0x134feaf0, \
+ 0x4cbe286a, 0x90402102, 0x8fe0d909, 0x97d137f6, \
+ 0xe691752b, 0xd3dedef9, 0xc7b49f82, 0x09603358, \
+ 0x193492ac, 0xe56e9731, 0x7e1af0aa, 0x634b817f, \
+ 0x04539cdf, 0x66e64804, 0x2833db53, 0xcffc90c8, \
+ 0x22566d36, 0x44ac18d6, 0x61ee8c58, 0xeae1d6af, \
+ 0x887cc4fc, 0x883c10b9, 0x0a15222b, 0x2ae98936, \
+ 0x44c25599, 0x81d7415e, 0x56571d4a, 0x3cdef19a, \
+ 0xc7f4b7e3, 0x7d22948d, 0xc51a520a, 0x681261dd, \
+ 0xfdc925d4, 0x20571d9d, 0x96c8ed60, 0x13928c39, \
+ 0x9014f344, 0x5de44b90, 0x88ec1d75, 0xe5461bc9}
+#define N_4096_INIT \
+ {0xcd901390, 0x71b1de45, 0x979b11b2, 0xb8004722, \
+ 0x87dafc87, 0x572fa2c1, 0x56d8096f, 0xcc48fcea, \
+ 0x5551097a, 0xa6617591, 0x0e3335b7, 0x86847bd9, \
+ 0xd32fb266, 0x1a600b11, 0x1e25d649, 0x77841ca1, \
+ 0xd4559098, 0xb4064f59, 0xb42bf905, 0xeb4dee8a, \
+ 0x6ec47fc5, 0x89eddec9, 0xf2792b3a, 0xa80cc359, \
+ 0xea37dd19, 0x1f1bfd22, 0xd4f42f45, 0x9d58072c, \
+ 0xa09ececf, 0x54388736, 0xb96305b2, 0xef0369dc, \
+ 0xbc0d40aa, 0x21e2c049, 0xeec91ad6, 0x5a03ae51, \
+ 0x2f728467, 0xebef992c, 0x893ed93e, 0xcc6d9f95, \
+ 0xe872e034, 0x25e8c674, 0xd36dd9b1, 0xa6cbe8ae, \
+ 0x579d7a79, 0xf04bf57d, 0x8af9aa72, 0xbe418e5a, \
+ 0x818edba0, 0x0790fab1, 0xc03ba57d, 0xd1875437, \
+ 0xe34758bb, 0x2ac2d968, 0xde806f76, 0xd20f3fe6, \
+ 0xeaab1418, 0x96c2f4a7, 0xd00ce8aa, 0xc128199b, \
+ 0xe171e34a, 0x5b64975b, 0x6e57f417, 0xf86df596, \
+ 0x2b2a8759, 0xdf78f33a, 0xbb61c879, 0x12894d77, \
+ 0xd7340a00, 0xc2ddd19c, 0x931022d7, 0x1a5a1824, \
+ 0xc9350c94, 0x4bd02b16, 0xa5c38d4c, 0xe613b6e8, \
+ 0xb6acfa7b, 0x21481ace, 0xc7316fd2, 0xd3e48258, \
+ 0x6e01aff9, 0xcd77aaea, 0x11ad333c, 0x27480d42, \
+ 0xb6eda715, 0xe84e0320, 0xdca1d9c3, 0x70cf8d73, \
+ 0x9bd71d31, 0x1a788cd0, 0x720be8af, 0xf3d07f2c, \
+ 0xfa11840d, 0xe149cdb9, 0xbc71debb, 0x3a867aa6, \
+ 0x434341f6, 0x1f2a0619, 0x459073c7, 0xca0f6eec, \
+ 0xa0d48ca5, 0x9cda81bb, 0x53c8d319, 0x5ebc77e0, \
+ 0x8de3eba2, 0x23715243, 0x0aa3376e, 0xda3242e4, \
+ 0x5e210656, 0x97e8573d, 0x6d75f036, 0xe670341f, \
+ 0x005302ee, 0xc92ec1e9, 0xb1c9ab39, 0x7e16606a, \
+ 0x9c165221, 0x9b6bfbef, 0x1fcbd8ee, 0xb5d77b41, \
+ 0x4a7c1680, 0x9f87ecd1, 0x21a8610a, 0xb6c16108, \
+ 0x7734dfea, 0x025540dc, 0x2a56ef7e, 0x5a8793b9}
+#define N_FACTOR_4096_INIT \
+ {0x7ead8ce7, 0xe816f913, 0xce3633e6, 0x6ea71fce, \
+ 0x3c8a8178, 0xc8fd3aec, 0x8bcbea53, 0xd64e6222, \
+ 0x5fd931ea, 0xa9b402d7, 0xf0c8bca6, 0x1d1c2252, \
+ 0x6fdbfff8, 0x7f73dad2, 0x727386b2, 0x07dd174f, \
+ 0xc40652cf, 0x98c9fa9e, 0xd93f7332, 0xbe94cf9d, \
+ 0x909203c6, 0x142b5718, 0xad520cab, 0x954848c0, \
+ 0x546accd8, 0x3a70e779, 0x606ecdab, 0xb077eb94, \
+ 0x3cca5af2, 0xefc99d4a, 0xa3e7a93f, 0x2f8a5c63, \
+ 0x276babb8, 0xb5bd5f7e, 0xe3b2bb84, 0x0fc7dd44, \
+ 0xc41e1db5, 0x26f45a37, 0x3c9fb939, 0xdb34a435, \
+ 0x7bd59dc0, 0x4e67baeb, 0xa1add517, 0x0eae7d86, \
+ 0x4cf315bb, 0xe5e9f822, 0xc11155fd, 0xcbd28e82, \
+ 0x3ac4ff73, 0x424b461a, 0xafbe7982, 0x068ee7f1, \
+ 0x31e8b2df, 0x9cdae1b7, 0x85601c4b, 0x92e44cc1, \
+ 0x58c3487a, 0x72935484, 0xd6ca301d, 0x917e4b7b, \
+ 0xb0650588, 0x439b4c59, 0xdc7a8d88, 0x1430cf9e, \
+ 0x3e816071, 0x2a31625f, 0x5f81f45c, 0x3c9d2588, \
+ 0x6c452e58, 0x97a30fed, 0x170ec965, 0x8312d655, \
+ 0x4fe06d89, 0xb91d54b7, 0x93455a5a, 0x6a6afd97, \
+ 0xe91c289e, 0xa7d6e689, 0xfdd547a9, 0x85bcdeac, \
+ 0xf2bce0f2, 0x5a845ff2, 0xe9b6b572, 0x29bddd95, \
+ 0x68278e1b, 0x0c3e983b, 0x1b8bca31, 0xc0ae1167, \
+ 0xf51d2764, 0x59132422, 0x05c8fd04, 0x481e8ef3, \
+ 0xfc505dca, 0x13946ce5, 0xe677121c, 0x47db729b, \
+ 0xc27f6da7, 0x3f583da3, 0x7e891af7, 0xb6791c5c, \
+ 0x6cc62b2a, 0x7e3aa912, 0x8b5d3630, 0xa2fc7edb, \
+ 0x87ad57a0, 0x8eb615a0, 0x8db99a96, 0x1264b7c7, \
+ 0x04df8ccf, 0xbd4a156d, 0xf176f3c6, 0x781854c9, \
+ 0x84581f28, 0x39cad145, 0x5ca59c9d, 0x88f408d4, \
+ 0xdb3ea81c, 0xd66f2bc1, 0xb3dcac29, 0x4860b839, \
+ 0xdc33778e, 0x7aa6216b, 0x589b9072, 0xc49f39a7, \
+ 0x07ad082b, 0x5e1d3823, 0xe354c566, 0xb92eb968}
+#define N_COEFF_4096_INIT \
+ {0x0000ad7e, 0xd0b04406, 0xa961298e, 0x7ccf17cf, \
+ 0xa66da916, 0x8f52f3e9, 0x6df37efb, 0x4041b686, \
+ 0x9a3c5974, 0x14aac6ad, 0xee32f0b7, 0x47dd3f97, \
+ 0x62bdd582, 0x52adbcbc, 0x83777003, 0x91b0332d, \
+ 0x93f26749, 0xdcac12eb, 0xc5eaef7f, 0xa79444e1, \
+ 0xbd7307ae, 0x32975b87, 0xa5900cf0, 0x71659afe, \
+ 0xea5f8a90, 0x1a732470, 0x662c3afb, 0x6ce5c0d9, \
+ 0x83b0edea, 0xe93de188, 0xb23f6e5b, 0x2093fefa, \
+ 0xafbc21fa, 0xa9370804, 0xb4e5befd, 0x5b760403, \
+ 0xf34cbaa9, 0x544ff8f9, 0xa782c5d4, 0xc00dba0d, \
+ 0xb509045c, 0x28bca972, 0x7e4d66cf, 0xd6a7eb67, \
+ 0x5b2f02f7, 0x70d9b2ec, 0xf0e89774, 0x1632bcb5, \
+ 0x52198355, 0xcdbc0381, 0xe4b4c10f, 0xb661951e, \
+ 0x48bf4ea9, 0x239967e4, 0x24c660c1, 0x14212d38, \
+ 0x7ec1268d, 0x4e6549df, 0x4773494b, 0xba2ef032, \
+ 0xafc7a5f9, 0x076f9ecf, 0x3cb845dc, 0x2d1b6b45, \
+ 0xbf8a84f5, 0x76bec23b, 0x4671cbea, 0x7bb3241e, \
+ 0x67c93063, 0x60b3db1b, 0x8f7b3ebf, 0x0adeb500, \
+ 0xc370a73f, 0xadca31c7, 0x10d3bf0e, 0xdbb1ac92, \
+ 0xe7829fbf, 0xfe33a0a3, 0xc2ac3a06, 0x3a3dc993, \
+ 0x1f654364, 0xdc9257a2, 0x415e9c3a, 0xdc7be426, \
+ 0x99937c17, 0xd2b3fc03, 0xa7ff2fd2, 0x9703ee84, \
+ 0x23174c51, 0xf389dfdb, 0xf988182c, 0x6551ff06, \
+ 0xc47dddcc, 0x6dfad344, 0x130798c0, 0x51d077d1, \
+ 0x047d7df0, 0xf537bc14, 0xc008935c, 0x907b2f04, \
+ 0xae8cc546, 0xcbb25e07, 0x024cbe44, 0xa04b5409, \
+ 0xe383f2d3, 0x045205cc, 0xad7dcc85, 0xde141bca, \
+ 0x9cbe85c2, 0xdbec31c8, 0xc0138098, 0xaed26c5d, \
+ 0x5a021cc6, 0x978e29cd, 0xcafedf77, 0x757e237a, \
+ 0x495efcb6, 0x17a00cfa, 0x2a07a73b, 0x7755a4c7, \
+ 0x8965a879, 0x264b734a, 0x19336eba, 0x543b7906, \
+ 0x929be01a, 0x9945c76b, 0xb8ac63e7, 0xc3bc15f3, \
+ 0x95217d77}
+#define X_4096_INIT \
+ {0x00f4dcf2, 0xd90e1715, 0x5cd52bbc, 0xcfabda4e, \
+ 0x409b369b, 0x0994ae28, 0xff6ea364, 0xcdb9dcfe, \
+ 0x82f35f8b, 0xef718044, 0xe609de07, 0x5d77ee51, \
+ 0xe8616ce4, 0xe2862a8f, 0x2d3c3b06, 0x2d532c22, \
+ 0x82825cff, 0x83ac8f2e, 0xfee472cb, 0x6abc86e8, \
+ 0xe8c35dca, 0x975a5cfb, 0xdbf67229, 0xf4c166b7, \
+ 0xbd76a787, 0x3f7d47ec, 0x7f8083d4, 0xcb5aa9e2, \
+ 0x74e6e776, 0x5991b9eb, 0x8eb9747c, 0xa838f053, \
+ 0xd0b3d52a, 0xe0e89d44, 0xc5e97a4f, 0x4df5ccb4, \
+ 0xd4818f84, 0x81a69d96, 0x684fbb35, 0x7d835def, \
+ 0xaf9fe113, 0xc8d257b9, 0x02e8d030, 0xffbe1b0f, \
+ 0x93a70c45, 0x973aaee0, 0xea1bc185, 0x22da443e, \
+ 0xd335f1e1, 0x0f6ce5b7, 0xc2080e5c, 0x5c2c3fac, \
+ 0x06151df4, 0x11060aba, 0xeb055f41, 0x20d0ef28, \
+ 0xbc2f85b1, 0x0062960b, 0xcbfd3f26, 0xf8090158, \
+ 0xf09da0be, 0xbf1c4956, 0x7d074e72, 0x8dc49abd, \
+ 0x0be643c1, 0x66dc9fb4, 0x2779f539, 0x17a9af50, \
+ 0xd61a0672, 0xc9dff220, 0x8495c764, 0x7c835324, \
+ 0xdff55742, 0x439bf86b, 0xa704b38e, 0xf523ab0e, \
+ 0x40082129, 0x2b1874a2, 0x3b82eafb, 0xb5ef08fe, \
+ 0x3f3bb671, 0x12401497, 0x3a9fcacc, 0x9fb55c41, \
+ 0xaf6c4786, 0xc0012609, 0x6268291c, 0x83b9163d, \
+ 0x1a19052e, 0xc03b1a37, 0x0685ab76, 0x744f89a4, \
+ 0x6136afe8, 0xc2f635ba, 0xce6f6c82, 0x0594970d, \
+ 0xe16bed86, 0x942eeb18, 0xa9cd7a5d, 0x0484f5eb, \
+ 0x1e9c5d4a, 0xb0fbee5f, 0x4e04dfaf, 0x69191a4e, \
+ 0x32d7c6ac, 0xd304cf73, 0x0f69a37c, 0x7635e396, \
+ 0x9d120148, 0x065f4eef, 0xb91338c1, 0x7d311d92, \
+ 0x5f64b776, 0x23c05865, 0xe31f411f, 0x1f149dd9, \
+ 0x55a464f5, 0x36b11a06, 0x9ea878c6, 0x0bb9b47f, \
+ 0x4a5bf575, 0x24cc5f44, 0x7b86dd7a, 0xb8f4bacd, \
+ 0x6bee7dd6, 0xae4b653b, 0x287d9842, 0x8c6db2ad}
+#define Y_4096_INIT \
+ {0x6219b803, 0x1659aa11, 0x7054e9a6, 0x8927edda, \
+ 0x828b3ac0, 0x41a5d730, 0xbbe7f273, 0x48f43b84, \
+ 0xf26c8f0e, 0x27a33b97, 0x9d067a95, 0x11528990, \
+ 0xfdeb5a25, 0x15cbbea5, 0xa1cda0bb, 0x3c30344f, \
+ 0xe39ec33c, 0xb461ab5d, 0xf419e4c5, 0xacd624e9, \
+ 0x81325742, 0xac940fba, 0xee96959d, 0x4d909de2, \
+ 0xe6ab66c6, 0xb951a295, 0x0ccd11f3, 0x39a86ab2, \
+ 0xea17cbc2, 0x37d674b3, 0xfba0d78c, 0xa4cb00e4, \
+ 0x3b0c0a89, 0x7f5b3336, 0xb027161b, 0x584c74b3, \
+ 0xc180fc59, 0x0aa6fed3, 0xa7f4205e, 0xf99e60cc, \
+ 0xd8539cc4, 0x24d34bfe, 0xfaf8ae70, 0x695ea1db, \
+ 0xfcbe3329, 0x71da81f4, 0x88124a12, 0x5259bca8, \
+ 0xfbdd1571, 0xf09aba1d, 0x41a42043, 0xe5ec51ea, \
+ 0x8bf5a521, 0x15dc0b58, 0x37e95d37, 0x7d2f6613, \
+ 0x4975a60b, 0x1431378e, 0xf39d94e0, 0xb2c5b74c, \
+ 0x94c131e3, 0x21f4e03a, 0x194aa07f, 0x352cc39b, \
+ 0x3346b671, 0xa93cd904, 0x4e02d587, 0xa18e3f8e, \
+ 0x511fc9c6, 0x8487a751, 0x48fbc7a6, 0x68884d52, \
+ 0xc0e4a6b3, 0xee735950, 0x6d56e403, 0x0d98647d, \
+ 0x29a4cd66, 0xadc976e0, 0xe6d79a1a, 0x4c769295, \
+ 0x8d2fdf4e, 0x6f7f52d9, 0xd49479c4, 0x7c2fe324, \
+ 0x217de70a, 0xd3a4dcde, 0x47dc33f4, 0xd197ea2a, \
+ 0x7d439cc9, 0x3cf381ae, 0xf84f186b, 0xd17b9c5d, \
+ 0xf5ffc3c6, 0x0f75be16, 0xb18bd3d9, 0x0e15b2a7, \
+ 0xf5ff07d8, 0x46e11959, 0xcf47d2bd, 0xf00c1667, \
+ 0x1b744635, 0x33396abf, 0xf9006e4c, 0xcb7656c9, \
+ 0x872b4338, 0xd259c9ab, 0xcacd568c, 0x737e7e9b, \
+ 0x1bcec0a9, 0x755ec2d9, 0x0c84ddec, 0xfac2f9fb, \
+ 0x3139f520, 0xef319d60, 0xd348fa8a, 0x5188f37f, \
+ 0x39a9a79b, 0xf29c960f, 0x5ef8652c, 0x8a73d074, \
+ 0xb7282dc9, 0x226319ce, 0x13c2f406, 0xf95b1a99, \
+ 0xd12c061a, 0xe5465d50, 0x2f20ea1b, 0xfbcd8483}
+#define P_4096_INIT \
+ {0xfef4e3fb, 0x37b1bc5c, 0x98a67bd9, 0xe55cf0b7, \
+ 0x34d751b2, 0x828c4bd3, 0xd0ed62fc, 0x921faacb, \
+ 0x44df64f9, 0xbf700412, 0xa15338f6, 0x070bb89f, \
+ 0x7a373a4d, 0x490b64e8, 0x7d2b64d3, 0xfe607142, \
+ 0x10deb01c, 0x0c89f03b, 0x906ea60b, 0xfcb64387, \
+ 0x758e8c30, 0xb8a1869f, 0x71a983f2, 0x81c2187b, \
+ 0x8d6e8d0e, 0xdd36afb7, 0x0f36fd10, 0x2c84661d, \
+ 0x798bfb2e, 0x2b0223da, 0x5f9f964d, 0x4acba423, \
+ 0x3fb0b303, 0xcdaec6b3, 0xab6bbb91, 0xd870315a, \
+ 0x6737f70f, 0x2924cb49, 0xb07f60dc, 0x717bd901, \
+ 0xd393eda6, 0x3d82752e, 0xce1ba3b3, 0x9b4f0f00, \
+ 0xd4bc6d42, 0xcf6bcfc7, 0x250c82cd, 0xfdb70730, \
+ 0xb8027b72, 0xb73b7bc4, 0x5668264f, 0x4c3b8407, \
+ 0x5e8361b7, 0x9d4d09b3, 0x83b91211, 0x4dafb1f1, \
+ 0xd608a99d, 0x8b58fef0, 0x76128ed3, 0x357e531a, \
+ 0xedb0d8da, 0xddfee8ee, 0x7f2bb456, 0x78630d33}
+#define Q_4096_INIT \
+ {0xce677009, 0x76ef9cea, 0xaa9321d0, 0x2438d6aa, \
+ 0x7480ae64, 0x58fe3a7d, 0xa13acfea, 0x612c12a5, \
+ 0x8cd11b5a, 0xf83ade1c, 0x3ad7242f, 0x549ba901, \
+ 0xd5e15209, 0xb970013b, 0x68e6e145, 0xbfa2de87, \
+ 0x14660974, 0xd805df3d, 0xbf2dab6d, 0x2808c06a, \
+ 0x01c5daa0, 0x0bada01d, 0x738f8e13, 0xa9d4a55c, \
+ 0x666b7e0e, 0x28312f62, 0x0577e3b8, 0x158ffdbb, \
+ 0xc255ea01, 0x3239e327, 0x71cb821b, 0x30877cf7, \
+ 0xfab70d27, 0x0e8e73e0, 0x73308930, 0xa96ba5e2, \
+ 0x3f3687ec, 0xd2fb92a4, 0xc9acb639, 0xbbd8e2e0, \
+ 0x418d99bf, 0xa63878d6, 0x3f6cb7b5, 0xedca9757, \
+ 0xdd15333d, 0x2a43351d, 0xf1b7c40b, 0x12a03dea, \
+ 0x30e144ec, 0x97deade2, 0xbb0582ee, 0x2ad94cbd, \
+ 0xeb68e881, 0x98f8cb38, 0xbafce42d, 0xa1675285, \
+ 0x63bb82c3, 0x5151deea, 0x3e265673, 0x1fda745c, \
+ 0xe442c6d8, 0xecee6a4f, 0x8bff8b7d, 0xa5e6a363}
+#define P_FACTOR_4096_INIT \
+ {0x805f4fb5, 0xeb61385e, 0x5b90b31e, 0x2048b4fe, \
+ 0x95a2a80a, 0x2a358baf, 0x2886a5d5, 0x1cb94ba6, \
+ 0xb208d35c, 0x526def58, 0xc2759a84, 0x998dd52c, \
+ 0x5e45413a, 0xad324dd3, 0x0c4b545e, 0xa1c26b41, \
+ 0x4cc88cfd, 0xe1436827, 0x86b8ff37, 0xb169978c, \
+ 0xec39f8ed, 0x1600e196, 0xa28cf6c3, 0xa4482067, \
+ 0xcc4127b9, 0xf967ff18, 0x7cc757d7, 0x68be1af9, \
+ 0xa89dbb87, 0xe1445b27, 0x371b4067, 0x82740b49, \
+ 0x21c14aa6, 0xba8cf577, 0xc7800606, 0xafee2148, \
+ 0x3a2ea48e, 0x7c802658, 0xe9759ecd, 0x7ee4c04e, \
+ 0xb7c5b4f3, 0x4843ef53, 0x338f1c01, 0x3767298d, \
+ 0x25aac99d, 0x6be3848c, 0x27ca7b27, 0xbca04298, \
+ 0xf4b3d910, 0x9992dfa6, 0xfa0b936a, 0x1cfc322d, \
+ 0x1c693299, 0xc374effb, 0x886bb835, 0x6761edd2, \
+ 0x4b11b52b, 0x87c5e54a, 0xbdd4fbeb, 0xe5a0b886, \
+ 0x3a8ce792, 0xd8c677be, 0x8f7a8727, 0x8535e3f4}
+#define Q_FACTOR_4096_INIT \
+ {0x50cf757f, 0x34c55771, 0xf32ea09e, 0xe145eed6, \
+ 0x6880b33b, 0xce0b73d1, 0xbef683e8, 0x52097ce5, \
+ 0x412fa7dc, 0x37852325, 0xf144c1fa, 0xd17a83ab, \
+ 0xd46887e5, 0xa4c2a47b, 0x3767bebf, 0x5872249c, \
+ 0xf3c08cf3, 0x79a79249, 0xd2bc6568, 0xeab5a613, \
+ 0x81bfa020, 0xdc0407d9, 0x5c758821, 0xf2e234be, \
+ 0xdbf3053c, 0x7d367027, 0x319d1cf2, 0x547250cc, \
+ 0xa4b50fc5, 0x23b330db, 0x56da493d, 0xbe60b69a, \
+ 0x9aa3e4c8, 0xae750145, 0xaa2319ee, 0x1ca34afb, \
+ 0xb59fbd97, 0xbeea80ef, 0x8c951c20, 0x9dfe8fa8, \
+ 0xbf163c63, 0x4d3e7ce4, 0x2c475421, 0x9b5f16ed, \
+ 0x29247f76, 0x3fbce686, 0x372cb6a1, 0x39985f15, \
+ 0x7465c0e0, 0x3a0b042d, 0x838736e2, 0xbdfeb886, \
+ 0xc6bfa2eb, 0x41cda5a1, 0xfb89fcf7, 0x5d49bc8d, \
+ 0x64524619, 0x08692d91, 0x57f1eddb, 0xbfbd23f1, \
+ 0xd813f4c0, 0x506511c5, 0x639064c9, 0xf9ace9aa}
+#define P_COEFF_4096_INIT \
+ {0x0000f2fb, 0xedccd410, 0x3e57b95c, 0xe7c02645, \
+ 0x5ca7921a, 0x483d1989, 0xc765793f, 0xbd0cdd74, \
+ 0x60e8a8e9, 0xa21fdbe4, 0xf5e0e15a, 0xfea809bc, \
+ 0xae540dd4, 0x5fec4c3b, 0x037c3380, 0xf73f0369, \
+ 0x000b47bb, 0x234d705b, 0xc4151bbc, 0xe1cd1b2e, \
+ 0x218b5b19, 0x4aba357a, 0x88eabd2e, 0xb81b8e1f, \
+ 0xfe9e3368, 0xe360e4c6, 0x505624a8, 0xc7fd31ed, \
+ 0x207684bb, 0xfca40c8b, 0x48889f24, 0xd2949cf5, \
+ 0x14dc5c26, 0xe50467a6, 0x9a81ddeb, 0x3360d843, \
+ 0x2a7960e4, 0x7737a3fd, 0x3fef5974, 0xaf1a93f2, \
+ 0xf90518e9, 0xeffba557, 0x5eb01260, 0x899bc3de, \
+ 0x1b4e573b, 0xde627be0, 0x0ae59221, 0x44a86b34, \
+ 0x3a68f53a, 0xadad6e3a, 0x28ff351d, 0xe4fbf462, \
+ 0xcd627abb, 0x14f1cce6, 0xc142d4ae, 0xe33461e8, \
+ 0xed7c016b, 0x82a06a16, 0x9ac4b6e0, 0xf82688b6, \
+ 0x71930f9b, 0xbc5e815a, 0x5ff0fc80, 0xc2b00736, \
+ 0x6ac04a05}
+#define Q_COEFF_4096_INIT \
+ {0x00005489, 0x82cc1d64, 0x630e3186, 0x14aeef86, \
+ 0x71d3f94a, 0x3fcbdcc8, 0x027b7081, 0xd46941aa, \
+ 0xf5f4aaba, 0xd6118f3c, 0xd62b7413, 0xb2552515, \
+ 0x84c22bde, 0x556cc1e5, 0xec3a36e7, 0x8476aa02, \
+ 0xa7622bd5, 0x9a40fd6a, 0xe5cf759f, 0x69f0db3d, \
+ 0x9b4c08b1, 0x76f6fe33, 0x5772174b, 0x26d1e2e0, \
+ 0x56345fc8, 0xbc99509d, 0x7ecd8f7b, 0x30053f53, \
+ 0x5c60ad43, 0x9250f36f, 0x05e63a15, 0x1b5d6e05, \
+ 0x88963682, 0x5a0994b6, 0x1fb54902, 0x9a57fb21, \
+ 0xfc90e3a3, 0x441681e3, 0x3d338164, 0xf02e1cd8, \
+ 0x58d1019c, 0xedb48c6c, 0x5773b199, 0xccbae528, \
+ 0x0f03c6f9, 0xad258d0d, 0x708f1f5b, 0x4f9a1699, \
+ 0x31e7a089, 0x0810cbea, 0x84ca3c80, 0x53193513, \
+ 0x427ee21f, 0xfa428428, 0x29ac6532, 0x9b1b31de, \
+ 0x654b10bb, 0xaf8d8993, 0xa918a0b6, 0x2fcae803, \
+ 0x3b88d209, 0xdccf68c8, 0x8f385352, 0xf824eed6, \
+ 0xb61009b5}
+#define D_4096_INIT \
+ {0x186feb53, 0x7da0a68a, 0xe16606e9, 0x97243950, \
+ 0xaa93e6f7, 0x73eeeecb, 0x4b36ad90, 0x83d99d6f, \
+ 0x822afb14, 0x80990f6f, 0xea1f3e60, 0x8df64bfe, \
+ 0xee333a63, 0x16f999f7, 0x33fd4d87, 0x3855154e, \
+ 0x4bbecc4c, 0xcb020106, 0xe9fb5c44, 0x4edfd9de, \
+ 0xcd22410a, 0x4bc66278, 0xe1817419, 0x2a073266, \
+ 0x0b090f18, 0xc071045b, 0xd2b320b7, 0x86e8031a, \
+ 0x5411ed06, 0x0abe199c, 0xf0d70bc3, 0x64d4a40e, \
+ 0x20b0f6a2, 0x031b40be, 0xc94b510c, 0x70710595, \
+ 0x132deafd, 0xabb7b51e, 0xed45f26f, 0x9bbfe07b, \
+ 0xe2c15d53, 0xf5b9c175, 0xfbf8902b, 0xa5679246, \
+ 0xbf95b20c, 0xb2fb64b8, 0xc2ffc13a, 0x98d19449, \
+ 0xc0232a8a, 0xd0bb7482, 0x1317442a, 0x3bf1799a, \
+ 0x97435112, 0x171848de, 0x45ad4113, 0x000fde09, \
+ 0xe695e5f2, 0xb26184d2, 0x3a527e8a, 0x66220d41, \
+ 0x51c0c743, 0x7cafedaa, 0x69e8bcd4, 0xe8acb1c8, \
+ 0x2c8aa9e1, 0x93c7ddbe, 0x6ae76387, 0x6f49fc03, \
+ 0xc0f9ea97, 0xcaef4501, 0x2e6d4441, 0xe972b467, \
+ 0xb6a22446, 0x1ea77c0e, 0x4a1212fe, 0x705f4698, \
+ 0x1162cde1, 0x2f64288a, 0x33ef0f77, 0xb8592838, \
+ 0x8e6e2061, 0x026725d8, 0x36c9e8fc, 0xd4dd53a5, \
+ 0x3c094cf1, 0xab40ce14, 0x78421594, 0xb398f85d, \
+ 0x49d03508, 0xfc241a72, 0xb4ffad43, 0xe70634bd, \
+ 0x74db9668, 0x5f8c7fb6, 0x37937b9a, 0x34aeb713, \
+ 0x673f2923, 0xefd5d4b0, 0x049c7cc6, 0x84f9d52b, \
+ 0x8f79f85f, 0xd502abe4, 0xdb6ddd90, 0x079c8c65, \
+ 0xc9175af1, 0x2aa5d52e, 0xe55aff13, 0x06bc0548, \
+ 0x3978cae3, 0x83b5cecb, 0x3fab2936, 0x45907b41, \
+ 0xa24390c7, 0x1bbd3d08, 0x96a5b97a, 0xab9e8ce4, \
+ 0x1b6b71bb, 0x37e31c3a, 0x246604a7, 0xded9dc85, \
+ 0x530d7a20, 0xc27aa31f, 0xba8cc94a, 0xe4459a13, \
+ 0xef015dcf, 0xd4305fb8, 0x2f7e7308, 0xaad6b49d}
+#define DP_4096_INIT \
+ {0x422570fc, 0x9d5f7c7a, 0x1d949bef, 0x55457ea2, \
+ 0x59903f7e, 0xebc5d06a, 0x7cfb09c2, 0x737ac9ca, \
+ 0x00ed607a, 0x3743ad9a, 0xd3c60eb2, 0x2df3c98b, \
+ 0x7e9ed37e, 0x77a40023, 0x1d4e63d3, 0x685cc725, \
+ 0x97d0dea9, 0xf84ad54b, 0xeed5f638, 0x87f115a6, \
+ 0x1046d272, 0x55847ab3, 0xe53e50a0, 0x5b2feb40, \
+ 0x2ada72b8, 0x578637a2, 0x6bcd1d6c, 0xd3cfe9da, \
+ 0x5dcd8676, 0x5cec2a37, 0x1eb5fdbd, 0xc1d90195, \
+ 0xaf917d70, 0x502db719, 0xa830c432, 0x3b90280d, \
+ 0xc757cabe, 0x61334d96, 0xa9b6f27f, 0x5ee5fdd0, \
+ 0x2e7f6399, 0xccbd8aff, 0x80b3c50d, 0xf50e56db, \
+ 0x25565996, 0x8acff2d1, 0x3cf878fb, 0x4e86ecd3, \
+ 0xa3f9e8e3, 0x434ca878, 0xb0de468a, 0x2e4206a8, \
+ 0x0eca5150, 0xdcfbbeb7, 0x97462dbc, 0xd585eec9, \
+ 0xca78e6e0, 0x9be59406, 0xf8eb29a8, 0xfc68f0d0, \
+ 0xbcb8341a, 0xdc9ba4fd, 0x337b3847, 0x72e667e7}
+#define DQ_4096_INIT \
+ {0xc7dc0af5, 0x6f3037ae, 0x56fadf1b, 0xef67061d, \
+ 0xc96faced, 0xc7ea6bf2, 0xa8030dbe, 0x72d73d3b, \
+ 0x066e9861, 0x6ec979b6, 0xb6170a97, 0xb6028015, \
+ 0x21e7eb0b, 0x357f4a02, 0x1fe2a831, 0x648dad91, \
+ 0xf8e390b6, 0x8e52a946, 0xddeeb7f6, 0x9b7455f4, \
+ 0x8fc0e8a0, 0x5e8e81e2, 0xe2ba17a5, 0xdca5e674, \
+ 0xe14ba6a4, 0xc8b04fa4, 0x478d3e78, 0x4a90c1ed, \
+ 0x6410d2e4, 0xd3a08fde, 0xeae65716, 0x42d87ede, \
+ 0x93eb5a15, 0xfe975b86, 0xf3a304c4, 0x94d882a8, \
+ 0xdff2ca8d, 0x3c02938d, 0x732704d0, 0x449f8f97, \
+ 0xfc81c365, 0x7aeb65be, 0x776dab39, 0xc3868f23, \
+ 0x6a151427, 0x5edbf2fc, 0x0ac9994f, 0xeb7a3459, \
+ 0xa77909c7, 0x5a8b29ae, 0xc8cf5e67, 0x8620219a, \
+ 0x28efcd6b, 0x68174898, 0xa71f2747, 0x33e99b53, \
+ 0x442e1641, 0x5065c946, 0xe2653702, 0x84ce802c, \
+ 0x4e6e86a3, 0x185107a9, 0xfcf2b63c, 0x353f6de7}
+#define QINV_4096_INIT \
+ {0xbddb95d3, 0x98297c22, 0xa0b00bc5, 0xa3fe9626, \
+ 0xd51f0289, 0xedca3df5, 0xba25c529, 0x65961a25, \
+ 0x2696e0b6, 0x759a9776, 0x60d7ad63, 0x12277bed, \
+ 0x2a2021f7, 0xc0ce22ed, 0xd23419fa, 0x84e51549, \
+ 0xeba3fdec, 0x114a0809, 0x29faa2f1, 0x2b1bd340, \
+ 0x8b0a56fe, 0xc5e9574e, 0xf6ed4956, 0x13d07508, \
+ 0x5dd9d2a1, 0x07b5063c, 0x91c58920, 0x2c1d0182, \
+ 0x2ca5f674, 0x2d8df9c5, 0x54ec2cec, 0x3303d8ee, \
+ 0x24cc705c, 0x94c0938f, 0x824476b4, 0x0d12b4ff, \
+ 0x90edfb30, 0x916495e2, 0x3e5f55a5, 0x7e8e5725, \
+ 0x983527ee, 0x8253aa3c, 0xcdb0d9d7, 0x8bbf6a64, \
+ 0xcd5abe3f, 0x2ea84d5d, 0xcb40ada9, 0x20f8f2e8, \
+ 0x9bfe8e26, 0xd92806ca, 0x4170c9a7, 0x4768638e, \
+ 0x4d5946c8, 0x08d53f16, 0x932d86e7, 0x023cad13, \
+ 0xf54c1e61, 0xc750ef0c, 0x1c47d3a7, 0x20771a27, \
+ 0x266ab3c6, 0xebd96384, 0x670eae29, 0x51aec124}
+#define XM_4096_INIT \
+ {0x8a8ac00a, 0xc1223da2, 0xed7420a7, 0xcc2eff54, \
+ 0xca243efa, 0x1d08a69e, 0x8201a97b, 0xbbcaaee5, \
+ 0xd6db0398, 0x999a5bf8, 0x4bdb22ed, 0x89d1817e, \
+ 0x477dafdc, 0x088ddc03, 0x9c732b4b, 0x5d3fbb6e, \
+ 0xb2df0771, 0x884371ba, 0x1955e688, 0xe550056d, \
+ 0x0ccd7614, 0xc31a669b, 0x2a429c3e, 0x73d080d7, \
+ 0x7fb45717, 0x2cb4ee52, 0xd4547d88, 0x62b4b25f, \
+ 0x423312de, 0x72ac2e51, 0x0273149e, 0xe0582c65, \
+ 0x7395c57f, 0x171fb220, 0x12bf378d, 0xe3099f6f, \
+ 0xf1e348b3, 0x7573330a, 0xe8caef0f, 0xa2bc1f7e, \
+ 0x545be95e, 0xc22ca342, 0x8a806af0, 0x214d6534, \
+ 0x419fcbab, 0x38f6e454, 0x44d03e82, 0x3787580d, \
+ 0xd186f7f4, 0x92068495, 0xbdc6188f, 0xa1383890, \
+ 0x3fccad18, 0x6ecbd119, 0xd247dbd8, 0xeda0ef73, \
+ 0x269ced04, 0xd7fc045c, 0xb29effcf, 0x85b863a3, \
+ 0x43a81d30, 0x1a3d119d, 0xf6ff12b5, 0x4ba624a7, \
+ 0xf89491e6, 0x53829006, 0x6d55f2d7, 0x5f374121, \
+ 0x2ea5365e, 0x3a287cd9, 0xc7a1d6bb, 0xfdaa6556, \
+ 0x443c5bd0, 0x39a9ac8b, 0xfb66b6c8, 0xa9657d9c, \
+ 0x726a70e5, 0x1f93581b, 0xda332f23, 0xbc248646, \
+ 0xaa5f5a5a, 0xc357adad, 0xe8d3c737, 0xfbea82ac, \
+ 0x4b50f4c9, 0xc4102533, 0x01d6e8fa, 0xd4cfccb3, \
+ 0xf9243edb, 0x88f1e200, 0x1775831e, 0xfb011f8b, \
+ 0x7fbf38c1, 0x9ee2edca, 0x35b3bbfe, 0x80fe7f1f, \
+ 0x6aebbdf1, 0x4d4a479c, 0x5f063b87, 0x1fe7d9e7, \
+ 0x1e5da6c1, 0xc3fe00dc, 0x826b4d2d, 0x739d7235, \
+ 0x1c15fcd3, 0xa81a079a, 0xdea04249, 0x2704e046, \
+ 0xd00880f8, 0x99113ea2, 0x1d6821f8, 0x6270bdbd, \
+ 0xb8c9564f, 0x728afaed, 0x75f436c9, 0xd2bcd731, \
+ 0xb5a1ea40, 0xdb9b3cb7, 0x557149b3, 0x172b9969, \
+ 0x992fcef8, 0xbcf87117, 0xc1d42775, 0x6d0bf91b, \
+ 0xfedd166b, 0xbe3525dd, 0x6643adf0, 0x31bfa295}
+#define YM_4096_INIT \
+ {0xbbfc19eb, 0x1f599505, 0x892675e4, 0xef69939f, \
+ 0xfb6c6ee2, 0x13fa672e, 0x3e2fd943, 0x97dade64, \
+ 0xf8d84f09, 0x5125e0e4, 0x98816a6e, 0x32c6d1a9, \
+ 0x5a1e226d, 0x37b907e4, 0xb85fc79e, 0xac4d43ff, \
+ 0x9fd75ab9, 0x901fb8e9, 0x3ee58150, 0xb3556977, \
+ 0xa8b8d546, 0x80f00f77, 0x4e694c0c, 0xe2391906, \
+ 0xb5832342, 0x6d4c0dd6, 0xe15ef11f, 0x1a826c19, \
+ 0x24162bad, 0x04b4df6c, 0x68c31f0f, 0xf3f14637, \
+ 0x900f68ed, 0x914badc3, 0xdd750246, 0xd906063d, \
+ 0xaccb4d4e, 0xb095a9b5, 0x0224ac9f, 0x91ae6ab8, \
+ 0x2d558890, 0x81b9c281, 0x526245df, 0x3b28c459, \
+ 0x7e099a20, 0x69982084, 0xd748d836, 0x1a94deb4, \
+ 0xfe6f0df4, 0xb91cf1e8, 0x9f594c56, 0xeaabaade, \
+ 0x22c3c0bd, 0x6d0737b3, 0xa4ebf0d5, 0x0c14c46e, \
+ 0xb68622a5, 0xee5960d0, 0x9097e3bd, 0x9d5fe72d, \
+ 0xe6ebd799, 0x9003eff6, 0xaab8e310, 0x224dca9f, \
+ 0x47cd647b, 0x3a39b2b0, 0xfb302bd3, 0xca4c29c1, \
+ 0x76ce8e24, 0xac388043, 0xe9f93ab8, 0x44b2385a, \
+ 0x2bc61bdd, 0xe2cb4dcd, 0x6b197d03, 0x286920a6, \
+ 0x6bd8eb71, 0xbd838883, 0x07699980, 0x5ab4a8f4, \
+ 0x37f24665, 0xd0c4b921, 0x78502103, 0x3e13eb0e, \
+ 0x36867b28, 0x11d8ba0a, 0xdc98e170, 0x84968da9, \
+ 0x768c8204, 0x4460da53, 0x46afe7f4, 0x100955d6, \
+ 0x2575ba2c, 0xec6e2f73, 0x4a1f0675, 0x165e2916, \
+ 0x3e6d158e, 0x6588881f, 0x4be1a2a7, 0x3d05fa40, \
+ 0xe03ea0c6, 0xbdd6667a, 0x7e917214, 0x4eb04016, \
+ 0xe6d5f991, 0x8f7dd39a, 0x033a120f, 0x958ef886, \
+ 0x7a1724c3, 0x17ac67a4, 0x43a4d4f8, 0x6102e9e5, \
+ 0x58ccded6, 0xa2b7b911, 0x80568305, 0xe84ff59e, \
+ 0x9cf66a5f, 0x4be539c1, 0x46a5f3d0, 0x8a21e5b1, \
+ 0x3414d415, 0xcfdb2a14, 0xb64a7a2e, 0x44ccf5c9, \
+ 0x3420e975, 0x837922af, 0xbf3c038b, 0x30a12a70}
+#define S_4096_INIT \
+ {0x3c9f198a, 0xf90c5822, 0x18aa0d98, 0x94d3b71d, \
+ 0xc7fa6082, 0xb56e2225, 0x6022cce4, 0x48cf8b63, \
+ 0x274076d2, 0xa789f811, 0xbaf9da57, 0x604a6c65, \
+ 0xb3a60697, 0xf70d2d26, 0xe74756fc, 0x141225f0, \
+ 0xf1c96fdc, 0x8642668e, 0xc30656e9, 0x1f82a02f, \
+ 0x60808b86, 0x2d5bc6ad, 0xeeaf60a5, 0x7c80ea03, \
+ 0xd5de8c23, 0xe7b97924, 0xd3593390, 0x7eb36591, \
+ 0x71f664bd, 0x0482afd9, 0x5bf39c95, 0x8eed0f10, \
+ 0x201ddb5a, 0x0429c4e1, 0x251ff020, 0x873323c6, \
+ 0xc6869b6b, 0xc32e8b27, 0x963c753f, 0xd08722f0, \
+ 0x5fa85a79, 0xfc0abe23, 0x2e4f16f1, 0x3cbf7eb7, \
+ 0x3a7fc0f9, 0x269a70ed, 0x3b37da19, 0xe2020751, \
+ 0x4181a813, 0x431e5325, 0xafa6c220, 0xc2693225, \
+ 0xcc545969, 0x12233b1a, 0x764fad70, 0x36b17f81, \
+ 0xabd38be5, 0x4ff6115d, 0x62019b91, 0x6bdc94a6, \
+ 0x64f65f7e, 0x99583fe7, 0xfb59c85b, 0x8a5b35c8, \
+ 0x72aa9fc2, 0x7e29349f, 0x4ce13360, 0x47c38309, \
+ 0x58538f8d, 0x418caf80, 0x6ab40196, 0x344e52ff, \
+ 0x25e1cfe8, 0x59c5b2a7, 0x5f36cf03, 0x210ca65c, \
+ 0xa45f7330, 0x4167afb5, 0x9c1e1adc, 0xeb45139a, \
+ 0x08b0027d, 0x06026d48, 0xa2f3f90b, 0xc064ccb3, \
+ 0xffcffe03, 0x9f2734ae, 0xf1893112, 0x16aff83a, \
+ 0x8ced71c3, 0x5589c81a, 0x86b9f999, 0xca400d52, \
+ 0x01585407, 0x6ec066f1, 0x50f882fa, 0x4cedb6b5, \
+ 0xeb7c4151, 0x77d4b226, 0x7278248c, 0x68808cc2, \
+ 0xb57b3aeb, 0xafb3a595, 0xa3748512, 0x3c3251cb, \
+ 0x9db3599e, 0x44b25cf7, 0x2db96416, 0x4ac3e562, \
+ 0xf34ba0d9, 0xc0a4172b, 0xed48353e, 0xd1a1e232, \
+ 0x402f7bde, 0xf4471904, 0x883af949, 0xa76510ab, \
+ 0x6202d73c, 0xbb3f8393, 0x89570131, 0x40410fda, \
+ 0x034ad261, 0xa3fd2f35, 0x312dbb63, 0xcb33786e, \
+ 0x51ffe05a, 0xb12b18b6, 0xefa080ba, 0x722402c3}