[Cryptech-Commits] [user/shatov/modexpng_fpga_model] 01/02: - Switched to default key length of 512 for faster simulation - Added an option to dump vectors as C array initializers for easy import into the STM32 sample driver - Added an option to dump entire core memory to assist debugging in hardware - Reading from bank now returns a copy of its contents, not a link - Reworked how carry propagation works (no more in-place overwrites) - Implemented "caching" of bank contents to match how things actually work in hardware (eg. after switch [...]

git at cryptech.is git at cryptech.is
Wed Oct 23 16:20:02 UTC 2019


This is an automated email from the git hooks/post-receive script.

meisterpaul1 at yandex.ru pushed a commit to branch master
in repository user/shatov/modexpng_fpga_model.

commit 9a3c126dc09d7e128919886554ec6ce5d1fb88d7
Author: Pavel V. Shatov (Meister) <meisterpaul1 at yandex.ru>
AuthorDate: Thu Oct 17 21:11:55 2019 +0300

     - Switched to default key length of 512 for faster simulation
     - Added an option to dump vectors as C array initializers for easy import into
       the STM32 sample driver
     - Added an option to dump entire core memory to assist debugging in hardware
     - Reading from bank now returns a copy of its contents, not a link
     - Reworked how carry propagation works (no more in-place overwrites)
     - Implemented "caching" of bank contents to match how things actually work in
       hardware (eg. after switching to twice smaller modulus before doing the CRT
       ladder, the upper half of the larger modulus stays in place)
     - Optimized microcode
     - Various cosmetic fixes
---
 modexpng_fpga_model.py      | 450 ++++++++++++++++++++++++++++++++++----------
 vector/README.md            |   4 +-
 vector/vector_format.py     |   2 +-
 vector/vector_regenerate.py |   2 +-
 4 files changed, 357 insertions(+), 101 deletions(-)

diff --git a/modexpng_fpga_model.py b/modexpng_fpga_model.py
index 325f544..41acbff 100644
--- a/modexpng_fpga_model.py
+++ b/modexpng_fpga_model.py
@@ -49,7 +49,7 @@ from enum import Enum, auto
 # --------------
 
 # length of public key
-KEY_LENGTH = 1024
+KEY_LENGTH = 512
 
 # how many parallel multipliers to use
 NUM_MULTS  = 8
@@ -80,7 +80,7 @@ _VECTOR_CLASS = "Vector"
 # ------------------
 # Debugging Settings
 # ------------------
-DUMP_LADDER_INDEX      = -1     # at which ladder step to print debug vector
+DUMP_LADDER_INDEX      = -1     # at which ladder step to print intermediate debug vector (-1 doesn't print internals)
 DUMP_VECTORS           = False  # print entire debug vector components
 DUMP_INDICES           = False  # print indices of words at MAC inputs
 DUMP_MACS_INPUTS       = False  # print MAC input words
@@ -89,8 +89,12 @@ DUMP_MACS_ACCUMULATION = False  # print MAC accumulators contents
 DUMP_MULT_PARTS        = False  # print multiplication output parts
 DUMP_RECOMBINATION     = False  # print recombination internals
 DUMP_REDUCTION         = False  # print reduction internals
+DUMP_EXPONENTS         = False  # dump secret exponents
 FORCE_OVERFLOW         = False  # force rarely seen internal overflow situation to verify how its handler works
 DUMP_PROGRESS_FACTOR   = 16     # once per how many ladder steps to update progress indicator
+DUMP_FORMAT_BUS        = True   # False: dump 18-bit words, True: dump 32-bit words
+DUMP_FORMAT_C_ARRAY    = False   # False: dump in Verilog format, True: dump as C array initializer
+
 
 #
 # Multi-Precision Integer
@@ -115,14 +119,50 @@ class ModExpNG_Operand():
 
             self._init_from_words(words, length)
 
-    def format_verilog_concat(self, name):
+    def copy(self):
+        return ModExpNG_Operand(None, len(self.words), self.words)
 
-        for i in range(len(self.words)):
-            if i > 0:
-                if (i % 4) == 0: print("")
-                else:            print(" ", end='')
-            print("%s[%3d] = 18'h%05x;" % (name, i, self.words[i]), end='')
+    def _format_verilog(self, name):
+
+        if not DUMP_FORMAT_BUS:
+            for i in range(len(self.words)):
+                if i > 0:
+                    if (i % 4) == 0: print("")
+                    else:            print(" ", end='')
+                print("%s[%3d] = 18'h%05x;" % (name, i, self.words[i]), end='')
+        else:
+        
+            _words = list(self.words)
+            num_words = len(_words)
+            
+            if num_words % 2 > 0:
+                _words.append(0)
+                num_words += 1
+                
+            for i in range(num_words // 2):
+                if i > 0:
+                    if (i % 4) == 0: print("")
+                    else:            print(" ", end='')
+                print("%s[%3d] = 32'h%04x%04x;" % (name, i, _words[2*i+1], _words[2*i]), end='')
         print("")
+        
+    def _format_c_array(self, name):
+        words = list(reversed(self.words))
+        if len(words) % 2 > 0: words.insert(0, 0)
+        
+        print("#define %s_%d_INIT \\\n\t{" % (name, KEY_LENGTH), end='')
+        for i in range(0, len(words), 2):
+            print("0x%04x%04x" % (words[i], words[i+1]), end='')
+            if (i + 2) < len(words):
+                print(", ", end='')
+                if ((i + 2) % 8) == 0: print("\\\n\t ", end='')
+            else: print("}")
+        
+    def format(self, name):
+        if not DUMP_FORMAT_C_ARRAY:
+            self._format_verilog(name)
+        else:
+            self._format_c_array(name)
 
     def _init_from_words(self, words, count):
 
@@ -235,6 +275,8 @@ class ModExpNG_NarrowBankEnum(Enum):
     D       = auto()
     E       = auto()
     N_COEFF = auto()
+    Q       = auto()
+    EXT     = auto()
     I       = auto()
 
 class ModExpNG_CoreInputEnum(Enum):
@@ -273,6 +315,15 @@ class ModExpNG_WideBank():
         self.n = None
         self.l = None
         self.h = None
+        
+        self.a_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.b_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.c_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.d_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.e_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.n_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.l_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.h_cache = ModExpNG_Operand(0, KEY_LENGTH)
 
     def _get_value(self, sel):
         if   sel == ModExpNG_WideBankEnum.A:   return self.a
@@ -285,16 +336,46 @@ class ModExpNG_WideBank():
         elif sel == ModExpNG_WideBankEnum.H:   return self.h
         else: raise Exception("ModExpNG_WideBank._get_value(): Invalid selector!")
 
+    def _get_value_cache(self, sel):
+        if   sel == ModExpNG_WideBankEnum.A:   return self.a_cache
+        elif sel == ModExpNG_WideBankEnum.B:   return self.b_cache
+        elif sel == ModExpNG_WideBankEnum.C:   return self.c_cache
+        elif sel == ModExpNG_WideBankEnum.D:   return self.d_cache
+        elif sel == ModExpNG_WideBankEnum.E:   return self.e_cache
+        elif sel == ModExpNG_WideBankEnum.N:   return self.n_cache
+        elif sel == ModExpNG_WideBankEnum.L:   return self.l_cache
+        elif sel == ModExpNG_WideBankEnum.H:   return self.h_cache
+        else: raise Exception("ModExpNG_WideBank._get_value(): Invalid selector!")
+
     def _set_value(self, sel, value):
-        if   sel == ModExpNG_WideBankEnum.A:   self.a   = value
-        elif sel == ModExpNG_WideBankEnum.B:   self.b   = value
-        elif sel == ModExpNG_WideBankEnum.C:   self.c   = value
-        elif sel == ModExpNG_WideBankEnum.D:   self.d   = value
-        elif sel == ModExpNG_WideBankEnum.E:   self.e   = value
-        elif sel == ModExpNG_WideBankEnum.N:   self.n   = value
-        elif sel == ModExpNG_WideBankEnum.L:   self.l   = value
-        elif sel == ModExpNG_WideBankEnum.H:   self.h   = value
+    
+        if   sel == ModExpNG_WideBankEnum.A: self.a = value.copy()
+        elif sel == ModExpNG_WideBankEnum.B: self.b = value.copy()
+        elif sel == ModExpNG_WideBankEnum.C: self.c = value.copy()
+        elif sel == ModExpNG_WideBankEnum.D: self.d = value.copy()
+        elif sel == ModExpNG_WideBankEnum.E: self.e = value.copy()
+        elif sel == ModExpNG_WideBankEnum.N: self.n = value.copy()
+        elif sel == ModExpNG_WideBankEnum.L: self.l = value.copy()
+        elif sel == ModExpNG_WideBankEnum.H: self.h = value.copy()
         else: raise Exception("ModExpNG_WideBank._set_value(): Invalid selector!")
+        
+        if   sel == ModExpNG_WideBankEnum.A:
+            for i in range(len(value.words)): self.a_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.B:
+            for i in range(len(value.words)): self.b_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.C:
+            for i in range(len(value.words)): self.c_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.D:
+            for i in range(len(value.words)): self.d_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.E:
+            for i in range(len(value.words)): self.e_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.N:
+            for i in range(len(value.words)): self.n_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.L:
+            for i in range(len(value.words)): self.l_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_WideBankEnum.H:
+            for i in range(len(value.words)): self.h_cache.words[i] = value.words[i]
+        
 
 class ModExpNG_NarrowBank():
 
@@ -305,7 +386,17 @@ class ModExpNG_NarrowBank():
         self.d       = None
         self.e       = None
         self.n_coeff = None
+        self.q       = None
+        self.ext     = ModExpNG_Operand(0, 2*_WORD_WIDTH)
         self.i       = i
+        
+        self.a_cache       = ModExpNG_Operand(0, KEY_LENGTH)
+        self.b_cache       = ModExpNG_Operand(0, KEY_LENGTH)
+        self.c_cache       = ModExpNG_Operand(0, KEY_LENGTH)
+        self.d_cache       = ModExpNG_Operand(0, KEY_LENGTH)
+        self.e_cache       = ModExpNG_Operand(0, KEY_LENGTH)
+        self.n_coeff_cache = ModExpNG_Operand(0, KEY_LENGTH)
+        self.q_cache       = ModExpNG_Operand(0, KEY_LENGTH)
 
     def _get_value(self, sel):
         if   sel == ModExpNG_NarrowBankEnum.A:       return self.a
@@ -314,18 +405,50 @@ class ModExpNG_NarrowBank():
         elif sel == ModExpNG_NarrowBankEnum.D:       return self.d
         elif sel == ModExpNG_NarrowBankEnum.E:       return self.e
         elif sel == ModExpNG_NarrowBankEnum.N_COEFF: return self.n_coeff
+        elif sel == ModExpNG_NarrowBankEnum.Q:       return self.q
+        elif sel == ModExpNG_NarrowBankEnum.EXT:     return self.ext
         elif sel == ModExpNG_NarrowBankEnum.I:       return self.i
         else: raise Exception("ModExpNG_NarrowBank._get_value(): Invalid selector!")
 
+    def _get_value_cache(self, sel):
+        if   sel == ModExpNG_NarrowBankEnum.A:       return self.a_cache
+        elif sel == ModExpNG_NarrowBankEnum.B:       return self.b_cache
+        elif sel == ModExpNG_NarrowBankEnum.C:       return self.c_cache
+        elif sel == ModExpNG_NarrowBankEnum.D:       return self.d_cache
+        elif sel == ModExpNG_NarrowBankEnum.E:       return self.e_cache
+        elif sel == ModExpNG_NarrowBankEnum.N_COEFF: return self.n_coeff_cache
+        elif sel == ModExpNG_NarrowBankEnum.Q:       return self.q_cache
+        else: raise Exception("ModExpNG_NarrowBank._get_value(): Invalid selector!")
+
     def _set_value(self, sel, value):
-        if   sel == ModExpNG_NarrowBankEnum.A:       self.a       = value
-        elif sel == ModExpNG_NarrowBankEnum.B:       self.b       = value
-        elif sel == ModExpNG_NarrowBankEnum.C:       self.c       = value
-        elif sel == ModExpNG_NarrowBankEnum.D:       self.d       = value
-        elif sel == ModExpNG_NarrowBankEnum.E:       self.e       = value
-        elif sel == ModExpNG_NarrowBankEnum.N_COEFF: self.n_coeff = value
+        if   sel == ModExpNG_NarrowBankEnum.A: self.a = value.copy()
+        elif sel == ModExpNG_NarrowBankEnum.B: self.b = value.copy()
+        elif sel == ModExpNG_NarrowBankEnum.C: self.c = value.copy()
+        elif sel == ModExpNG_NarrowBankEnum.D: self.d = value.copy()
+        elif sel == ModExpNG_NarrowBankEnum.E: self.e = value.copy()
+        elif sel == ModExpNG_NarrowBankEnum.N_COEFF:
+            self.n_coeff = ModExpNG_Operand(None, len(value.words)-1, value.words[:-1])
+            self.ext.words[0] = value.words[-1]
+        elif sel == ModExpNG_NarrowBankEnum.Q:
+            self.q = ModExpNG_Operand(None, len(value.words)-1, value.words[:-1])
+            self.ext.words[1] = value.words[-1]            
         else: raise Exception("ModExpNG_NarrowBank._set_value(): Invalid selector!")
 
+        if   sel == ModExpNG_NarrowBankEnum.A:
+            for i in range(len(value.words)): self.a_cache.words[i]       = value.words[i]
+        elif sel == ModExpNG_NarrowBankEnum.B:
+            for i in range(len(value.words)): self.b_cache.words[i]       = value.words[i]
+        elif sel == ModExpNG_NarrowBankEnum.C:
+            for i in range(len(value.words)): self.c_cache.words[i]       = value.words[i]
+        elif sel == ModExpNG_NarrowBankEnum.D:
+            for i in range(len(value.words)): self.d_cache.words[i]       = value.words[i]
+        elif sel == ModExpNG_NarrowBankEnum.E:
+            for i in range(len(value.words)): self.e_cache.words[i]       = value.words[i]
+        elif sel == ModExpNG_NarrowBankEnum.N_COEFF:
+            for i in range(len(value.words)-1): self.n_coeff_cache.words[i] = value.words[i]
+        elif sel == ModExpNG_NarrowBankEnum.Q:
+            for i in range(len(value.words)-1): self.q_cache.words[i]       = value.words[i]
+
 class ModExpNG_CoreInput():
 
     def __init__(self):
@@ -423,6 +546,12 @@ class ModExpNG_BanksPair():
     def _get_narrow(self, sel):
         return self.narrow._get_value(sel)
 
+    def _get_wide_cache(self, sel):
+        return self.wide._get_value_cache(sel)
+
+    def _get_narrow_cache(self, sel):
+        return self.narrow._get_value_cache(sel)
+
     def _set_wide(self, sel, value):
         self.wide._set_value(sel, value)
 
@@ -958,7 +1087,7 @@ class ModExpNG_Worker():
             c_in = c_out
         return ModExpNG_Operand(None, 2*ab_num_words, ab)
 
-    def multipurpose_multiply(self, a, b, n, n_coeff, ab_num_words, reduce_only=False, multiply_only=False, dump=False, dump_crt="", dump_ladder=""):
+    def multipurpose_multiply(self, a, b, n, n_coeff, ab_num_words, bnk, reduce_only=False, multiply_only=False, dump=False, dump_crt="", dump_ladder=""):
 
         #
         # 1. AB = A * B
@@ -975,6 +1104,10 @@ class ModExpNG_Worker():
         if dump and DUMP_VECTORS:
             ab.format_verilog_concat("%s_%s_AB" % (dump_crt, dump_ladder))
 
+        if not bnk is None:
+            bnk._set_wide(ModExpNG_WideBankEnum.L, ab.lower_half())
+            bnk._set_wide(ModExpNG_WideBankEnum.H, ab.upper_half())
+
         if multiply_only:
             return ModExpNG_Operand(None, 2*ab_num_words, ab_words)
 
@@ -990,6 +1123,12 @@ class ModExpNG_Worker():
         if dump and DUMP_VECTORS:
             q.format_verilog_concat("%s_%s_Q" % (dump_crt, dump_ladder))
 
+        if not bnk is None:
+            bnk._set_narrow(ModExpNG_NarrowBankEnum.Q, q)
+            q_words = list(bnk._get_narrow(ModExpNG_NarrowBankEnum.Q).words)
+            q_words.append(bnk._get_narrow(ModExpNG_NarrowBankEnum.EXT).words[1])
+            q = ModExpNG_Operand(None, len(q_words), q_words)
+
         #
         # 3. M = Q * N
         #
@@ -1066,7 +1205,6 @@ class ModExpNG_Worker():
             a.words[x] += carry
             carry = a.words[x] >> _WORD_WIDTH
             a.words[x] &= _WORD_MASK
-        return carry
 
 class ModExpNG_Core():
 
@@ -1076,6 +1214,70 @@ class ModExpNG_Core():
         self.inp = ModExpNG_CoreInput()
         self.out = ModExpNG_CoreOutput()
 
+    def _dump_bank_indices(self, n):
+        print("                  ", end='')
+        for i in range(64): print("[ %3d ] " % i, end='')
+        print("");
+
+    def _dump_bank_seps(self, n):
+        print("                  ", end='')
+        for i in range(64): print(" ------ ", end='')
+        print("");
+        
+    def _dump_bank_entry_narrow(self, name, op, val, n):
+        print("%s.NARROW.%s " % (name, op), end='')
+        for i in range(n):
+            if i < len(val.words) and not val is None:
+                print("0x%05x " % val.words[i], end='')
+                continue
+            print("0xxxxxx ", end='')
+        print("")
+        
+    def _dump_bank_entry_wide(self, name, op, val, n):
+        print("%s.WIDE.%s " % (name, op), end='')
+        for i in range(n):
+            if i < len(val.words) and not val is None:
+                print("0x%05x " % val.words[i], end='')
+            else:
+                print("0xxxxxx ", end='')
+        print("")
+
+    def _dump_bank(self, name, banks_pair):
+        
+        n = KEY_LENGTH // _WORD_WIDTH
+        
+        self._dump_bank_indices(n)
+        
+        self._dump_bank_entry_wide(name, "A:      ", banks_pair._get_wide_cache(W.A), n)
+        self._dump_bank_entry_wide(name, "B:      ", banks_pair._get_wide_cache(W.B), n)
+        self._dump_bank_entry_wide(name, "C:      ", banks_pair._get_wide_cache(W.C), n)
+        self._dump_bank_entry_wide(name, "D:      ", banks_pair._get_wide_cache(W.D), n)
+        self._dump_bank_entry_wide(name, "E:      ", banks_pair._get_wide_cache(W.E), n)
+        self._dump_bank_entry_wide(name, "N:      ", banks_pair._get_wide_cache(W.N), n)
+        self._dump_bank_entry_wide(name, "L:      ", banks_pair._get_wide_cache(W.L), n)
+        self._dump_bank_entry_wide(name, "H:      ", banks_pair._get_wide_cache(W.H), n)
+                
+        self._dump_bank_seps(n)
+        
+        self._dump_bank_entry_narrow(name, "A:    ", banks_pair._get_narrow_cache(N.A),       n)
+        self._dump_bank_entry_narrow(name, "B:    ", banks_pair._get_narrow_cache(N.B),       n)
+        self._dump_bank_entry_narrow(name, "C:    ", banks_pair._get_narrow_cache(N.C),       n)
+        self._dump_bank_entry_narrow(name, "D:    ", banks_pair._get_narrow_cache(N.D),       n)
+        self._dump_bank_entry_narrow(name, "E:    ", banks_pair._get_narrow_cache(N.E),       n)
+        self._dump_bank_entry_narrow(name, "COEFF:", banks_pair._get_narrow_cache(N.N_COEFF), n)
+        self._dump_bank_entry_narrow(name, "Q:    ", banks_pair._get_narrow_cache(N.Q),       n)
+        self._dump_bank_entry_narrow(name, "EXT:  ", banks_pair._get_narrow(N.EXT),           n)
+
+    def dump_banks(self):
+    
+        print("OPCODE == STOP: BANKS DUMP FOLLOWS")
+        self._dump_bank("X.X", self.bnk.crt_x.ladder_x)
+        self._dump_bank("X.Y", self.bnk.crt_x.ladder_y)
+        self._dump_bank("Y.X", self.bnk.crt_y.ladder_x)
+        self._dump_bank("Y.Y", self.bnk.crt_y.ladder_y)
+        sys.exit()
+        
+
     #
     # CRT_(X|Y) means either CRT_X or CRT_Y
     # LADDER_{X,Y} means both LADDER_X and LADDER_Y
@@ -1084,9 +1286,15 @@ class ModExpNG_Core():
     #
     # copy from CRT_(X|Y).LADDER_X.NARROW to OUTPUT
     #
-    def set_output_from_narrow(self, sel_output, bank_crt, sel_narrow):
+    def set_output_from_narrow_x(self, sel_output, bank_crt, sel_narrow):
         self.out._set_value(sel_output, bank_crt.ladder_x._get_narrow(sel_narrow))
 
+    #
+    # copy from CRT_(X|Y).LADDER_Y.NARROW to OUTPUT
+    #
+    def set_output_from_narrow_y(self, sel_output, bank_crt, sel_narrow):
+        self.out._set_value(sel_output, bank_crt.ladder_y._get_narrow(sel_narrow))
+
     #
     # copy from INPUT to CRT_(X|Y).LADDER_{X,Y}.NARROW
     #
@@ -1123,17 +1331,6 @@ class ModExpNG_Core():
         self.bnk.crt_x.ladder_y._set_narrow(sel_narrow_out, self.bnk.crt_x.ladder_x._get_narrow(sel_narrow_in))
         self.bnk.crt_y.ladder_y._set_narrow(sel_narrow_out, self.bnk.crt_y.ladder_x._get_narrow(sel_narrow_in))
 
-    #
-    # copy from CRT_{X,Y}.LADDER_Y.{WIDE,NARROW} to CRT_{X,Y}.LADDER_X.{WIDE,NARROW}
-    #
-    def copy_ladders_y2x(self, sel_wide_in, sel_narrow_in, sel_wide_out, sel_narrow_out):
-
-        self.bnk.crt_x.ladder_x._set_wide(sel_wide_out, self.bnk.crt_x.ladder_y._get_wide(sel_wide_in))
-        self.bnk.crt_y.ladder_x._set_wide(sel_wide_out, self.bnk.crt_y.ladder_y._get_wide(sel_wide_in))
-
-        self.bnk.crt_x.ladder_x._set_narrow(sel_narrow_out, self.bnk.crt_x.ladder_y._get_narrow(sel_narrow_in))
-        self.bnk.crt_y.ladder_x._set_narrow(sel_narrow_out, self.bnk.crt_y.ladder_y._get_narrow(sel_narrow_in))
-
     #
     # copy from CRT_{X,Y}.LADDER_X.{WIDE,NARROW} to CRT_{Y,X}.LADDER_Y.{WIDE,NARROW}
     #
@@ -1157,8 +1354,14 @@ class ModExpNG_Core():
         xn       = self.bnk.crt_x.ladder_x._get_wide(ModExpNG_WideBankEnum.N)
         yn       = self.bnk.crt_y.ladder_x._get_wide(ModExpNG_WideBankEnum.N)
 
-        xn_coeff = self.bnk.crt_x.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF)
-        yn_coeff = self.bnk.crt_y.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF)
+        xn_coeff_words = list(self.bnk.crt_x.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF).words)
+        yn_coeff_words = list(self.bnk.crt_y.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF).words)
+        
+        xn_coeff_words.append(self.bnk.crt_x.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.EXT).words[0])
+        yn_coeff_words.append(self.bnk.crt_y.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.EXT).words[0])
+
+        xn_coeff = ModExpNG_Operand(None, len(xn_coeff_words), xn_coeff_words)
+        yn_coeff = ModExpNG_Operand(None, len(yn_coeff_words), yn_coeff_words)
 
         xxa       = self.bnk.crt_x.ladder_x._get_wide(sel_wide_in)
         xya       = self.bnk.crt_x.ladder_y._get_wide(sel_wide_in)
@@ -1178,11 +1381,11 @@ class ModExpNG_Core():
         if not mode[1]: yb = yxb
         else:           yb = yyb
 
-        xxp = self.wrk.multipurpose_multiply(xxa, xb, xn, xn_coeff, num_words, dump=d, dump_crt="X", dump_ladder="X")
-        xyp = self.wrk.multipurpose_multiply(xya, xb, xn, xn_coeff, num_words, dump=d, dump_crt="X", dump_ladder="Y")
+        xxp = self.wrk.multipurpose_multiply(xxa, xb, xn, xn_coeff, num_words, self.bnk.crt_x.ladder_x, dump=d, dump_crt="X", dump_ladder="X")
+        xyp = self.wrk.multipurpose_multiply(xya, xb, xn, xn_coeff, num_words, self.bnk.crt_x.ladder_y, dump=d, dump_crt="X", dump_ladder="Y")
 
-        yxp = self.wrk.multipurpose_multiply(yxa, yb, yn, yn_coeff, num_words, dump=d, dump_crt="Y", dump_ladder="X")
-        yyp = self.wrk.multipurpose_multiply(yya, yb, yn, yn_coeff, num_words, dump=d, dump_crt="Y", dump_ladder="Y")
+        yxp = self.wrk.multipurpose_multiply(yxa, yb, yn, yn_coeff, num_words, self.bnk.crt_y.ladder_x, dump=d, dump_crt="Y", dump_ladder="X")
+        yyp = self.wrk.multipurpose_multiply(yya, yb, yn, yn_coeff, num_words, self.bnk.crt_y.ladder_y, dump=d, dump_crt="Y", dump_ladder="Y")
 
         self.bnk.crt_x.ladder_x._set_wide(sel_wide_out, xxp)
         self.bnk.crt_x.ladder_y._set_wide(sel_wide_out, xyp)
@@ -1212,10 +1415,14 @@ class ModExpNG_Core():
         yd = self.wrk.serial_subtract_modular(ya, yb, yn, num_words)
 
         self.bnk.crt_x.ladder_x._set_narrow(sel_narrow_out, xd)
+        self.bnk.crt_x.ladder_y._set_narrow(sel_narrow_out, xd)
         self.bnk.crt_y.ladder_x._set_narrow(sel_narrow_out, yd)
+        self.bnk.crt_y.ladder_y._set_narrow(sel_narrow_out, yd)
 
         self.bnk.crt_x.ladder_x._set_wide(sel_wide_out, xd)
+        self.bnk.crt_x.ladder_y._set_wide(sel_wide_out, xd)
         self.bnk.crt_y.ladder_x._set_wide(sel_wide_out, yd)
+        self.bnk.crt_y.ladder_y._set_wide(sel_wide_out, yd)
     
     #
     # modular reduce sel_narrow_in
@@ -1226,34 +1433,56 @@ class ModExpNG_Core():
         xn       = self.bnk.crt_x.ladder_x._get_wide(ModExpNG_WideBankEnum.N)
         yn       = self.bnk.crt_y.ladder_x._get_wide(ModExpNG_WideBankEnum.N)
 
-        xn_coeff = self.bnk.crt_x.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF)
-        yn_coeff = self.bnk.crt_y.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF)
+        xn_coeff_words = list(self.bnk.crt_x.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF).words)
+        yn_coeff_words = list(self.bnk.crt_y.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.N_COEFF).words)
+        
+        xn_coeff_words.append(self.bnk.crt_x.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.EXT).words[0])
+        yn_coeff_words.append(self.bnk.crt_y.ladder_x._get_narrow(ModExpNG_NarrowBankEnum.EXT).words[0])
 
-        xb       = self.bnk.crt_x.ladder_x._get_narrow(sel_narrow_in)
-        yb       = self.bnk.crt_y.ladder_x._get_narrow(sel_narrow_in)
+        xn_coeff = ModExpNG_Operand(None, len(xn_coeff_words), xn_coeff_words)
+        yn_coeff = ModExpNG_Operand(None, len(yn_coeff_words), yn_coeff_words)
+        
+        xxb = self.bnk.crt_x.ladder_x._get_narrow(sel_narrow_in)
+        xyb = self.bnk.crt_x.ladder_y._get_narrow(sel_narrow_in)
+        yxb = self.bnk.crt_y.ladder_x._get_narrow(sel_narrow_in)
+        yyb = self.bnk.crt_y.ladder_y._get_narrow(sel_narrow_in)
 
-        xp = self.wrk.multipurpose_multiply(None, xb, xn, xn_coeff, num_words, reduce_only=True)
-        yp = self.wrk.multipurpose_multiply(None, yb, yn, yn_coeff, num_words, reduce_only=True)
+        xxp = self.wrk.multipurpose_multiply(None, xxb, xn, xn_coeff, num_words, self.bnk.crt_x.ladder_x, reduce_only=True)
+        xyp = self.wrk.multipurpose_multiply(None, xyb, xn, xn_coeff, num_words, self.bnk.crt_x.ladder_y, reduce_only=True)
+        yxp = self.wrk.multipurpose_multiply(None, yxb, yn, yn_coeff, num_words, self.bnk.crt_y.ladder_x, reduce_only=True)
+        yyp = self.wrk.multipurpose_multiply(None, yyb, yn, yn_coeff, num_words, self.bnk.crt_y.ladder_y, reduce_only=True)
 
-        self.bnk.crt_x.ladder_x._set_wide(sel_wide_out, xp)
-        self.bnk.crt_x.ladder_y._set_wide(sel_wide_out, xp)
-        self.bnk.crt_y.ladder_x._set_wide(sel_wide_out, yp)
-        self.bnk.crt_y.ladder_y._set_wide(sel_wide_out, yp)
+        self.bnk.crt_x.ladder_x._set_wide(sel_wide_out, xxp)
+        self.bnk.crt_x.ladder_y._set_wide(sel_wide_out, xyp)
+        self.bnk.crt_y.ladder_x._set_wide(sel_wide_out, yxp)
+        self.bnk.crt_y.ladder_y._set_wide(sel_wide_out, yyp)
 
-        self.bnk.crt_x.ladder_x._set_narrow(sel_narrow_out, xp)
-        self.bnk.crt_x.ladder_y._set_narrow(sel_narrow_out, xp)
-        self.bnk.crt_y.ladder_x._set_narrow(sel_narrow_out, yp)
-        self.bnk.crt_y.ladder_y._set_narrow(sel_narrow_out, yp)
+        self.bnk.crt_x.ladder_x._set_narrow(sel_narrow_out, xxp)
+        self.bnk.crt_x.ladder_y._set_narrow(sel_narrow_out, xyp)
+        self.bnk.crt_y.ladder_x._set_narrow(sel_narrow_out, yxp)
+        self.bnk.crt_y.ladder_y._set_narrow(sel_narrow_out, yyp)
 
     #
     # propagate carries (convert to non-redundant representation) content in sel_narrow
     # overwrites input value
     #
     def propagate_carries(self, sel_narrow, num_words):
-        self.wrk.convert_nonredundant(self.bnk.crt_x.ladder_x._get_narrow(sel_narrow), num_words)
-        self.wrk.convert_nonredundant(self.bnk.crt_x.ladder_y._get_narrow(sel_narrow), num_words)
-        self.wrk.convert_nonredundant(self.bnk.crt_y.ladder_x._get_narrow(sel_narrow), num_words)
-        self.wrk.convert_nonredundant(self.bnk.crt_y.ladder_y._get_narrow(sel_narrow), num_words)
+        
+        xx = self.bnk.crt_x.ladder_x._get_narrow(sel_narrow)
+        xy = self.bnk.crt_x.ladder_y._get_narrow(sel_narrow)
+        yx = self.bnk.crt_y.ladder_x._get_narrow(sel_narrow)
+        yy = self.bnk.crt_y.ladder_y._get_narrow(sel_narrow)
+        
+        self.wrk.convert_nonredundant(xx, num_words)
+        self.wrk.convert_nonredundant(xy, num_words)
+        self.wrk.convert_nonredundant(yx, num_words)
+        self.wrk.convert_nonredundant(yy, num_words)
+        
+        self.bnk.crt_x.ladder_x._set_narrow(sel_narrow, xx)
+        self.bnk.crt_x.ladder_y._set_narrow(sel_narrow, xy)
+        self.bnk.crt_y.ladder_x._set_narrow(sel_narrow, yx)
+        self.bnk.crt_y.ladder_y._set_narrow(sel_narrow, yy)
+        
 
     #
     # copy from CRT_{X,Y}.LADDER_{X,Y}.WIDE.{H,L} to CRT_{X,Y}.LADDER_{X,Y}.NARROW
@@ -1300,11 +1529,11 @@ class ModExpNG_Core():
         xb       = self.bnk.crt_x.ladder_x._get_narrow(sel_narrow_in)
         yb       = self.bnk.crt_y.ladder_x._get_narrow(sel_narrow_in)
 
-        xxp = self.wrk.multipurpose_multiply(xxa, xb, None, None, num_words, multiply_only=True)
-        xyp = self.wrk.multipurpose_multiply(xya, xb, None, None, num_words, multiply_only=True)
+        xxp = self.wrk.multipurpose_multiply(xxa, xb, None, None, num_words, None, multiply_only=True)
+        xyp = self.wrk.multipurpose_multiply(xya, xb, None, None, num_words, None, multiply_only=True)
 
-        yxp = self.wrk.multipurpose_multiply(yxa, yb, None, None, num_words, multiply_only=True)
-        yyp = self.wrk.multipurpose_multiply(yya, yb, None, None, num_words, multiply_only=True)
+        yxp = self.wrk.multipurpose_multiply(yxa, yb, None, None, num_words, None, multiply_only=True)
+        yyp = self.wrk.multipurpose_multiply(yya, yb, None, None, num_words, None, multiply_only=True)
 
         xxp_lsb = xxp.lower_half()
         xxp_msb = xxp.upper_half()
@@ -1475,7 +1704,6 @@ def sign_using_crt():
     v  = vector
     n  = n_num_words
     pq = pq_num_words
-
     ff = (False, False)
                                                                    #
                                                                    # A / B => different content in banks (A in WIDE, B in NARROW)
@@ -1499,19 +1727,19 @@ def sign_using_crt():
     c.set_narrow_from_input (c.bnk.crt_y, N.A,       I.N_FACTOR)   # | [XY] / N_FACTOR        |  ?    |  ?               |  ?      | M  / ?    |
     c.set_narrow_from_input (c.bnk.crt_x, N.E,       I.M)          # | [XY] / N_FACTOR        |  ?    |  ?               |  ?      | M  / ..   |
     c.set_narrow_from_input (c.bnk.crt_y, N.E,       I.M)          # | [XY] / N_FACTOR        |  ?    |  ?               |  ?      | M         |
-                                                                   # +------------------------+-------+------------------+---------+-----------+
+                                                                   # +------------------------+-------+------------------+---------+-----------+        
     c.modular_multiply(W.A, N.A, W.B, N.B, n)                      # | [XY] / N_FACTOR        | [XY]F |  ?               |  ?      | M         | [XY]F = [XY] * N_FACTOR
-    c.modular_multiply(W.B, N.B, W.C, N.C, n, mode=ff)             # | [XY] / N_FACTOR        | [XY]F | [XY]YM           |  ?      | M         | [XY]MF = [XY]F * [XY]F
+    c.modular_multiply(W.B, N.B, W.C, N.C, n)                      # | [XY] / N_FACTOR        | [XY]F | [XY]YM           |  ?      | M         | [XY]MF = [XY]F * [XY]F
     c.modular_multiply(W.C, N.I, W.D, N.D, n)                      # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         | [XY]M = [XY]MF * 1
+                                                                   # +------------------------+-------+------------------+---------+-----------+    
+    c.propagate_carries(N.D, n)                                    # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.propagate_carries(N.D, n_num_words)                          # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         |
-                                                                   # +------------------------+-------+------------------+---------+-----------+
-    c.set_output_from_narrow(O.XM, c.bnk.crt_x, N.D)               # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         |
-    c.set_output_from_narrow(O.YM, c.bnk.crt_y, N.D)               # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         |
+    c.set_output_from_narrow_x(O.XM, c.bnk.crt_x, N.D)             # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         |
+    c.set_output_from_narrow_x(O.YM, c.bnk.crt_y, N.D)             # | [XY] / N_FACTOR        | [XY]F | [XY]YM           | [XY]M   | M         |
                                                                    # +------------------------+-------+------------------+---------+-----------+
     c.modular_multiply(W.E, N.B, W.C, N.C, n)                      # | [XY] / N_FACTOR        | [XY]F | [XY]MB           | [XY]M   | M         | [XY]MB = M * [XY]F
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.propagate_carries(N.C, n_num_words)                          # | [XY] / N_FACTOR        | [XY]F | [XY]MB           | [XY]M   | M         |
+    c.propagate_carries(N.C, n)                                    # | [XY] / N_FACTOR        | [XY]F | [XY]MB           | [XY]M   | M         |
                                                                    # +------------------------+-------+------------------+---------+-----------+
     c.copy_crt_y2x(W.C, N.C)                                       # | [XY] / N_FACTOR        | [XY]F |  YMB             | [XY]M   | M         |
                                                                    # +------------------------+-------+------------------+---------+-----------+
@@ -1519,17 +1747,16 @@ def sign_using_crt():
     c.set_wide_from_input  (c.bnk.crt_y, W.N,       I.Q)           # | [XY] / N_FACTOR        | [XY]F |  YMB             | [XY]M   | M         |
     c.set_wide_from_input  (c.bnk.crt_x, W.A,       I.P_FACTOR)    # | ...         / N_FACTOR | [XY]F |  YMB             | [XY]M   | M         |
     c.set_wide_from_input  (c.bnk.crt_y, W.A,       I.Q_FACTOR)    # | [PQ]_FACTOR / N_FACTOR | [XY]F |  YMB             | [XY]M   | M         |
-    c.set_wide_from_input  (c.bnk.crt_x, W.E,       I.QINV)        # | [PQ]_FACTOR / N_FACTOR | [XY]F |  YMB             | [XY]M   | ..        |
     c.set_wide_from_input  (c.bnk.crt_x, W.E,       I.QINV)        # | [PQ]_FACTOR / N_FACTOR | [XY]F |  YMB             | [XY]M   | QINV / M  |
                                                                    # +------------------------+-------+------------------+---------+-----------+
     c.set_narrow_from_input(c.bnk.crt_x, N.N_COEFF, I.P_COEFF)     # | [PQ]_FACTOR / N_FACTOR | [XY]F |  YMB             | [XY]M   | QINV / M  |
     c.set_narrow_from_input(c.bnk.crt_y, N.N_COEFF, I.Q_COEFF)     # | [PQ]_FACTOR / N_FACTOR | [XY]F |  YMB             | [XY]M   | QINV / M  |
     c.set_narrow_from_input(c.bnk.crt_x, N.A,       I.P_FACTOR)    # | [PQ]_FACTOR / ...      | [XY]F |  YMB             | [XY]M   | QINV / M  |
     c.set_narrow_from_input(c.bnk.crt_y, N.A,       I.Q_FACTOR)    # | [PQ]_FACTOR            | [XY]F |  YMB             | [XY]M   | QINV / M  |
-    c.set_narrow_from_input(c.bnk.crt_x, N.E,       I.QINV)        # | [PQ]_FACTOR            | [XY]F |  YMB             | [XY]M   | QINV / .. |
     c.set_narrow_from_input(c.bnk.crt_x, N.E,       I.QINV)        # | [PQ]_FACTOR            | [XY]F |  YMB             | [XY]M   | QINV      |
-                                                                   # +------------------------+-------+------------------+---------+-----------+
+                                                                   # +------------------------+-------+------------------+---------+-----------+                                                                  
     c.modular_reduce(N.C, W.D, N.D, pq)                            # | [PQ]_FACTOR            | [XY]F |  YMB             | [PQ]MBZ | QINV      | [PQ]MBZ = YMB mod [PQ]
+                                                                   # +------------------------+-------+------------------+---------+-----------+
     c.modular_multiply(W.D, N.A, W.C, N.C, pq)                     # | [PQ]_FACTOR            | [XY]F | [PQ]MB           | [PQ]MBZ | QINV      | [PQ]MB = [PQ]MBZ * [PQ]_FACTOR
     c.modular_multiply(W.C, N.A, W.D, N.D, pq)                     # | [PQ]_FACTOR            | [XY]F | [PQ]MB           | [PQ]MBF | QINV      | [PQ]MBF = [PQ]MB * [PQ]_FACTOR
     c.modular_multiply(W.A, N.I, W.C, N.C, pq)                     # | [PQ]_FACTOR            | [XY]F | [PQ]IF           | [PQ]MBF | QINV      | [PQ]IF = 1 * [PQ]_FACTOR
@@ -1541,7 +1768,6 @@ def sign_using_crt():
     ###########################                                    # |                        |       |                  |         |           |
                                                                    # |                        |       |                  |         |           |
     for bit in range(_WORD_WIDTH * pq - 1, -1, -1):                # |                        |       |                  |         |           |
-                                                                   # |                        |       |                  |         |           |
         m  = get_ladder_mode_using_crt(v, bit)                     # |                        |       |                  |         |           |
         dbg = bit == DUMP_LADDER_INDEX                             # |                        |       |                  |         |           |
                                                                    # |                        |       |                  |         |           |
@@ -1569,21 +1795,19 @@ def sign_using_crt():
     c.modular_multiply(W.C, N.E, W.C, N.C, pq)                     # | [PQ]_FACTOR            | [XY]F |  RSBIZ           | [PQ]SB* | QINV      | RSBIZ = RSB * QINV
     c.modular_multiply(W.C, N.A, W.C, N.C, pq)                     # | [PQ]_FACTOR            | [XY]F |  RSBI            | [PQ]SB* | QINV      | RSBI = RSBIZ * P_FACTOR
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.set_wide_from_input  (c.bnk.crt_x, W.E, I.Q)                 # | [PQ]_FACTOR / N_FACTOR | [XY]F |  RSBI            | [PQ]SB* | ..        |
-    c.set_wide_from_input  (c.bnk.crt_x, W.E, I.Q)                 # | [PQ]_FACTOR / N_FACTOR | [XY]F |  RSBI            | [PQ]SB* | Q / QINV  |
+    c.set_wide_from_input  (c.bnk.crt_x, W.E, I.Q)                 # | [PQ]_FACTOR / N_FACTOR | [XY]F |  RSBI            | [PQ]SB* |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.set_narrow_from_input(c.bnk.crt_x, N.E, I.Q)                 # | [PQ]_FACTOR            | [XY]F |  RSBI            | [PQ]SB* | Q / ..    |
-    c.set_narrow_from_input(c.bnk.crt_x, N.E, I.Q)                 # | [PQ]_FACTOR            | [XY]F |  RSBI            | [PQ]SB* | Q         |
+    c.set_narrow_from_input(c.bnk.crt_x, N.E, I.Q)                 # | [PQ]_FACTOR            | [XY]F |  RSBI            | [PQ]SB* |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.regular_multiply(W.E, N.C, pq)                               # | [PQ]_FACTOR            | [XY]F |  RSBI            | [PQ]SB* | Q         | = RSBI * Q
+    c.regular_multiply(W.E, N.C, pq)                               # | [PQ]_FACTOR            | [XY]F |  RSBI            | [PQ]SB* |           | = RSBI * Q
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.merge_lha(N.A, pq)                                           # | [PQ]_FACTOR / QRSBI    | [XY]F |  RSBI            | [PQ]SB* | Q         |
+    c.merge_lha(N.A, pq)                                           # | [PQ]_FACTOR / QRSBI    | [XY]F |  RSBI            | [PQ]SB* |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.propagate_carries(N.A, n)                                    # | [PQ]_FACTOR / QRSBI    | [XY]F |  RSBI            | [PQ]SB* | Q         |
+    c.propagate_carries(N.A, n)                                    # | [PQ]_FACTOR / QRSBI    | [XY]F |  RSBI            | [PQ]SB* |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.copy_crt_y2x(W.D, N.D)                                       # | [PQ]_FACTOR / QRSBI    | [XY]F |  RSBI            |  QSB*   | Q         |
+    c.copy_crt_y2x(W.D, N.D)                                       # | [PQ]_FACTOR / QRSBI    | [XY]F |  RSBI            |  QSB*   |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.regular_add(N.D, N.A, N.C, pq)                               # | [PQ]_FACTOR / QRSBI    | [XY]F |  SB              |  QSB*   | Q         | SB = QSB + RSBI
+    c.regular_add(N.D, N.A, N.C, pq)                               # | [PQ]_FACTOR / QRSBI    | [XY]F |  SB              |  QSB*   |           | SB = QSB + RSBI
                                                                    # +------------------------+-------+------------------+---------+-----------+
     c.set_wide_from_input  (c.bnk.crt_x, W.N, I.N)                 # |                        |       |                  |         |           |
     c.set_wide_from_input  (c.bnk.crt_y, W.N, I.N)                 # |                        |       |                  |         |           |
@@ -1595,8 +1819,10 @@ def sign_using_crt():
                                                                    # +------------------------+-------+------------------+---------+-----------+
     c.propagate_carries(N.A, n)                                    # |  S                     |       |                  |         |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
-    c.set_output_from_narrow(O.S, c.bnk.crt_x, N.A)                # |  S                     |       |                  |         |           |
+    c.set_output_from_narrow_x(O.S, c.bnk.crt_x, N.A)              # |  S                     |       |                  |         |           |
                                                                    # +------------------------+-------+------------------+---------+-----------+
+    #c.dump_banks()
+
 
 #
 # try to exponentiate using only half of the quad-multiplier (one dual-ladder core)
@@ -1623,19 +1849,17 @@ def sign_without_crt():
     c.set_narrow_from_input (c.bnk.crt_x, N.E,       I.M)
     c.set_narrow_from_input (c.bnk.crt_y, N.E,       I.M)
 
-    c.modular_multiply(W.A, N.A, W.B, N.B, n)           # [XY]F = [XY] * N_FACTOR
-    c.modular_multiply(W.B, N.B, W.C, N.C, n, mode=ff)  # [XY]MF = [XY]F * [XY]F
-    c.modular_multiply(W.C, N.I, W.D, N.D, n)           # [XY]M = [XY]MF * 1
+    c.modular_multiply(W.A, N.A, W.B, N.B, n) # [XY]F = [XY] * N_FACTOR
+    c.modular_multiply(W.B, N.B, W.C, N.C, n) # [XY]MF = [XY]F * [XY]F
+    c.modular_multiply(W.C, N.I, W.D, N.D, n) # [XY]M = [XY]MF * 1
 
     c.propagate_carries(N.D, n)
 
-    c.set_output_from_narrow(O.XM, c.bnk.crt_x, N.D)
-    c.set_output_from_narrow(O.YM, c.bnk.crt_y, N.D)
+    c.set_output_from_narrow_x(O.XM, c.bnk.crt_x, N.D)
+    c.set_output_from_narrow_x(O.YM, c.bnk.crt_y, N.D)
 
     c.modular_multiply(W.E, N.B, W.C, N.C, n)   # [XY]MB = M * [XY]F
 
-    XF = c.bnk.crt_x.ladder_x._get_narrow(N.B)
-
     c.set_wide_from_input(c.bnk.crt_x, W.A, I.N_FACTOR)
     c.set_wide_from_input(c.bnk.crt_y, W.A, I.N_FACTOR)
 
@@ -1670,13 +1894,12 @@ def sign_without_crt():
 
     c.modular_multiply(W.C, N.I, W.D, N.D, n)           # SB = SBF * 1    
     c.modular_multiply(W.B, N.D, W.A, N.A, n, mode=ff)  # S = XF * SB
-
-    c.copy_ladders_y2x(W.A, N.A, W.B, N.B)
     
-    c.propagate_carries(N.B, n)
+    c.propagate_carries(N.A, n)
     
-    c.set_output_from_narrow(O.S, c.bnk.crt_y, N.B)
+    c.set_output_from_narrow_y(O.S, c.bnk.crt_y, N.A)
 
+    #c.dump_banks()
 
 #
 # main()
@@ -1729,6 +1952,39 @@ if __name__ == "__main__":
     xm_known = pow(vector.x.number(), 2, vector.n.number())
     ym_known = pow(vector.y.number(), 2, vector.n.number())
 
+    if DUMP_VECTORS:
+        vector.m.format("M")
+        vector.n.format("N")
+        vector.n_factor.format("N_FACTOR")
+        vector.n_coeff.format("N_COEFF")
+        vector.x.format("X")
+        vector.y.format("Y")
+        
+        vector.p.format("P")
+        vector.q.format("Q")
+        
+        vector.p_factor.format("P_FACTOR")
+        vector.q_factor.format("Q_FACTOR")
+
+        vector.p_coeff.format("P_COEFF")
+        vector.q_coeff.format("Q_COEFF")
+
+        vector.d.format("D")
+
+        vector.dp.format("DP")
+        vector.dq.format("DQ")
+        
+        vector.qinv.format("QINV")
+
+        xm_known_operand = ModExpNG_Operand(xm_known, KEY_LENGTH)
+        ym_known_operand = ModExpNG_Operand(ym_known, KEY_LENGTH)
+        s_known_operand  = ModExpNG_Operand(s_known,  KEY_LENGTH)
+        
+        xm_known_operand.format("XM")
+        ym_known_operand.format("YM")
+        s_known_operand.format("S")
+        
+
     # sign using CRT and check
     print("Signing using CRT...")
     sign_using_crt()
diff --git a/vector/README.md b/vector/README.md
index 3bd1853..977f207 100644
--- a/vector/README.md
+++ b/vector/README.md
@@ -1,5 +1,5 @@
-ModExpNG
-========
+modexpng_fpga_model / vector
+============================
 
 Ranzomized test vector generation scripts for ModExpNG core model.
 
diff --git a/vector/vector_format.py b/vector/vector_format.py
index a3e7e81..7f11689 100644
--- a/vector/vector_format.py
+++ b/vector/vector_format.py
@@ -39,7 +39,7 @@ import vector_util
 
 SCRIPT_USAGE = "USAGE: vector_format.py [openssl_binary]"
 
-KEY_LENGTH = 1024
+KEY_LENGTH = 512
 
 RNG_SEED_MESSAGE = 1
 RNG_SEED_BLINDING = 2
diff --git a/vector/vector_regenerate.py b/vector/vector_regenerate.py
index 34c6384..b8a9373 100644
--- a/vector/vector_regenerate.py
+++ b/vector/vector_regenerate.py
@@ -38,7 +38,7 @@ import vector_util
 
 SCRIPT_USAGE = "USAGE: vector_regenerate.py [openssl_binary]"
 
-KEY_LENGTH = 1024
+KEY_LENGTH = 512
 
 if __name__ == "__main__":
 



More information about the Commits mailing list