figure a
figure b

1 Introduction

Bit-accurate non-linear integer computations are infamously hard to verify. Conventional bit-accurate techniques such as bit blasting do not work well for non-linear computations. Approximation techniques through floating-point computation on the other hand are inaccurate. Non-linear integer computation nonetheless is essential to computer cryptography. Analyzing complex non-linear computation in cryptographic libraries is still one of the most challenging problems of the utmost importance today.

In this paper, we address the verification problem through algebraic abstraction. In algebraic abstraction, abstract programs are represented by polynomial equations. Non-linear computation about abstract polynomial programs is analyzed algebraically and hence more efficiently through techniques from commutative algebra. Algebraic abstraction however is unsound due to overflow in bounded integer computation. We characterize soundness conditions with queries using the Quantifier-Free Bit-Vector (QF_BV) logic from Satisfiability Modulo Theories (SMT) [2]. SMT solvers are then used to check soundness conditions before applying algebraic abstraction.

Our hybrid technique takes advantages of both algebraic and bit-accurate analyses. Non-linear algebraic properties are verified algebraically. Polynomials are computed and analyzed by algorithms from commutative algebra. Coefficients, variables and arithmetic functions are atomic in such algorithms. Our algebraic analysis is hence very efficient for non-linear computation. Soundness conditions, on the other hand, require bit-accurate analysis. Our technique applies SMT QF_BV solvers to check soundness conditions. By combining algebraic with bit-accurate analyses, algebraic abstraction successfully verifies non-linear computation in real-world cryptographic programs.

Cryptographic programs undoubtedly are widely deployed critical software. Errors in their verification need to be minimized. To this end, we use the proof assistant Coq  [4] to verify the soundness theorem for algebraic abstraction. To ensure the correctness of external algebraic and bit-accurate analysis tools, results from external tools are certified in our technique as well. With verified abstraction and certified external results, verification of bit-accurate non-linear integer computation through algebraic abstraction is certified. We explain how to certify our hybrid verification technique.

We evaluate our certified technique with cryptographic programs from security libraries in Bitcoin  [27], boringSSL  [8, 12], nss  [20], OpenSSL  [23] and PQCrypto-SIDH  [18]. These programs compute field and group operations in elliptic curve cryptography. We also verify Number-Theoretic Transform (NTT) programs from the post-quantum cryptosystem Kyber  [6]. In lattice-based post-quantum cryptography, computation in polynomial rings is needed. NTT is a discrete variant of the Fast Fourier Transform used for polynomial multiplication in Kyber. Our certified algebraic abstraction technique verifies cryptographic programs from elliptic curve and post-quantum cryptography successfully. Our contributions are summarized as follows.

  • We detail algebraic abstraction for checking non-linear modular equations with multiple moduli;

  • We certify algebraic abstraction and its verification;

  • We report certified verification results for 39 real-world cryptographic programs in elliptic curve and post-quantum cryptography.

Related Work. gfverif employs an ad hoc technique to verify non-linear computation in cryptographic programs with a computer algebra system [3]. CryptoLine  [9, 24, 29] is a tool designed for the specification and verification of cryptographic assembly codes. Its verification algorithm utilizes computer algebra systems in addition to SMT solvers. CryptoLine is also leveraged to verify cryptographic C programs [9, 17]. The optimized Kyber NTT program for avx2 is verified in [15], but the underlying verification algorithm is left unexplained. None of these works certified their verification results. Users had to trust these verification tools. bvCryptoLine certifies algebraic abstraction but not soundness conditions [29]. It does not allow multiple moduli in modular equations either. Particularly, it cannot concisely specify NTT by the Chinese remainder theorem over polynomial rings. Compared with these works, our technique admits modular equations with multiple moduli in assumptions and assertions, and is fully certified. To explicate our advantages, consider the specification of multiplication in the field \(\mathbb {Z}_{p434}/\langle x^2 + 1\rangle \) where p434 is a prime number. An element in the field is of the form \(u_0 + u_1 x\) where \(x^2 + 1 = 0\). To specify \(r_0 + r_1 x\) is the product of \(u_0 + u_1 x\) and \(v_0 + v_1 x\), one can write two modular equations with one modulo: \(r_0 \equiv u_0 v_0 - u_1 v_1 \bmod [p434]\) and \(r_1 \equiv u_0 v_1 + u_1 v_0 \bmod [p434]\). With multiple moduli, we write \(r_0 + r_1 x \equiv (u_0 + u_1x)(v_0 + v_1x) \bmod [p434, x^2 + 1]\) succinctly. Our simple specifications are most useful for complicated fields such as \(\mathbb {Z}_{p381}/\langle x^2 + 1, y^3 - x - 1, z^2 - y \rangle \). Each element of the complex field is of the form \(\sum u_{i,j,k} x^i y^j z^k\) with \(0 \le i, k < 2\) and \(0 \le j < 3\). Twelve modular equations are needed previously. One modular equation with multiple moduli suffices to specify its field multiplication in this work. Furthermore, our technique is verified in Coq. The correctness of our abstraction algorithm and soundness theorem are formally proven in Coq. We also show how to certify results from external tools. In summary, the correctness of algebraic abstraction algorithm is verified and answers from external tools are certified. Verification results are therefore fully certified. We believe this is the best guarantee a model checker can offer. Our verified model checker is sufficiently practical to verify industrial cryptographic programs too!

Analysis of linear polynomial programs was discussed, for instance, in [21, 22]. The reduction from the root entailment problem to the ideal membership problem is discussed in [14]. In this work, the computer algebra system Singular  [13] is employed to compute standard bases of ideals and certificates. The certified SMT QF_BV solver CoqQFBV  [26] is adopted to certify soundness conditions.

The paper is organized as follows. Section 2 gives the needed backgrounds. It is followed by the syntax and semantics of the language ToyLang. An implementation of the unsigned Montgomery reduction is given as a running example (Sect. 3). Section 4 presents algebraic abstraction and its verification algorithms. We briefly describe certified verification of algebraic abstraction in Sect. 5. Section 6 shows experimental results of real-world cryptographic programs. We conclude in Sect. 7.

2 Preliminaries

Let \(\mathbb {N}\) and \(\mathbb {Z}\) denote the set of non-negative and all integers respectively. Fix a set of variables \(\overline{\textbf{x}}\). We write \(\mathbb {Z}[\overline{\textbf{x}}]\) for the set of polynomials in variables \(\overline{\textbf{x}}\) with coefficients in \(\mathbb {Z}\). A polynomial equation is of the form \(e = e'\) with \(e, e' \in \mathbb {Z}[\overline{\textbf{x}}]\); a polynomial modular equation is of the form \(e \equiv e' \bmod [f_0, f_1, \ldots , f_m]\) with \(e, e', f_0, f_1, \ldots , f_m \in \mathbb {Z}[\overline{\textbf{x}}]\). A valuation \(\rho \) of \(\overline{\textbf{x}}\) is a mapping from \(\overline{\textbf{x}}\) to \(\mathbb {Z}\). Given a valuation \(\rho \), a polynomial e evaluates to the integer \(e[\rho ]\) by replacing every variable x with \(\rho (x)\). A valuation \(\rho \) is a root of the equation \(e = e'\) if \((e - e')[\rho ] = 0\). A valuation \(\rho \) is a root of the modular equation \(e \equiv e' \bmod [f_0, f_1, \ldots , f_m]\) if \((e - e')[\rho ] = z_0f_0[\rho ] + z_1f_1[\rho ] + \cdots + z_mf_m[\rho ]\) for some \(z_0, z_1, \ldots , z_m \in \mathbb {Z}\). A (modular) equation is an equation or a modular equation. A system of (modular) equations is a set of (modular) equations. A root of a system of (modular) equations is a common root of every (modular) equation in the system. Let \(\varPhi \) be a system of (modular) equations and \(\phi \) a (modular) equation, roots of \(\varPhi \) entail roots of \(\phi \) (written \(\forall \overline{\textbf{x}}.\varPhi \implies \phi \)) if all roots of \(\varPhi \) are also roots of \(\phi \). Given \(\varPhi \) and \(\phi \), the root entailment problem is to decide whether \(\forall \overline{\textbf{x}}. \varPhi \implies \phi \).

An ideal in \(\mathbb {Z}[\overline{\textbf{x}}]\) generated by \(f_0, f_1, \ldots , f_m \in \mathbb {Z}[\overline{\textbf{x}}]\) is defined by \( \langle f_0, f_1, \ldots , f_m \rangle = \{ f_0h_0 + f_1h_1 + \cdots + f_mh_m | h_0, h_1, \ldots , h_m \in \mathbb {Z}[\overline{\textbf{x}}] \}. \) If \(\langle f_0, f_1\), \(\ldots \), \(f_m \rangle \) and \(\langle g_0,\) \(g_1, \ldots ,\) \(g_n \rangle \) are ideals, define their sum \( \langle f_0, f_1, \ldots , f_m \rangle + \langle g_0, g_1, \ldots , g_n \rangle = \langle f_0, f_1, \ldots , f_m\), \(g_0\), \(g_1, \ldots \), \(g_n \rangle . \) For instance, \(\langle x \rangle = \{ xf | f \in \mathbb {Z}[\overline{\textbf{x}}] \}\) and \(\langle 6 \rangle + \langle 10 \rangle = \langle 2 \rangle \). Given \(f \in \mathbb {Z}[\overline{\textbf{x}}]\) and an ideal I, the ideal membership problem is to decide whether \(f \in I\).

A bit-vector is a bit sequence of a width w. A bit-vector denotes an integer between 0 and \(2^w-1\) inclusively using the most-significant-bit-first representation. The SMT QF_BV logic defines bit-vector functions. Assume \(bv_0\) and \(bv_1\) are bit-vectors of width w. The addition \((\textit{bvadd}\ {bv_0}\ {bv_1}) \) and subtraction \((\textit{bvsub}\ {bv_0}\ {bv_1}) \) functions return bit-vectors of width w representing the sum and difference respectively. The multiplication function \((\textit{bvmul}\ {bv_0}\ {bv_1}) \) returns the least significant w bits of the product. The left shift function \((\textit{bvshl}\ {bv_0}\ {n}) \) shifts \(bv_0\) to the left by n bits; the logical right shift function \((\textit{bvlshr}\ {bv_0}\ {n}) \) shifts \(bv_0\) to the right by n bits. The zero extension function \((\textit{zero}\_\textit{extend}\ {bv_0}\ {n}) \) appends n most significant 0’s to \(bv_0\). The extraction function \((\textit{bvextract}\ {h}\ {l}\ {bv_0}) \) extracts bits indexed h to l from \(bv_0\) (\(w > h \ge l \ge 0\)). An SMT QF_BV expression is constructed from bit-vector values, variables, and functions. An SMT QF_BV assertion is of the form \((\textit{assert}\ {\bot }) \), \((\textit{assert}\ {(=\ {be}\ {be'})}) \), or \((\textit{assert}\ {(\textit{not}\ {(=\ {be}\ {be'})})}) \) with SMT QF_BV expressions be and \(be'\). An SMT QF_BV query is a set of SMT QF_BV assertions. A store is a mapping from bit-vector variables to bit-vector values. An SMT QF_BV expression evaluates to a bit-vector value on a store. An SMT QF_BV assertion \((\textit{assert}\ {(=\ be\ be')}) \) is satisfied by a store if be and \(be'\) evaluate to the same bit-vector value on the store, and otherwise \((\textit{assert}\ {(\textit{not}\ {(=\ {be}\ {be'})})}) \) is satisfied. The SMT QF_BV assertion \((\textit{assert}\ {\bot }) \) is never satisfied. An SMT QF_BV query is satisfiable if all assertions are satisfied by a store.

3 ToyLang

We consider a register transfer language called ToyLang to illustrate algebraic abstraction. For clarity, many programming constructs are removed from ToyLang. The language nevertheless is sufficiently expressive to implement Montgomery reduction [19], an indispensable algorithm found in real-world cryptographic programs.

3.1 Syntax and Semantics

The syntax of ToyLang is shown in Fig. 1. For simplicity, we assume all numbers are unsigned and all variables are of widths 1 or w. Variables of width 1 are also called bit variables. An atom is a number or a variable.

Fig. 1.
figure 1

ToyLang – Syntax

ToyLang supports several arithmetic instructions: addition (\(\textsc {add} \)), carrying addition (\(\textsc {adds} \)), addition-with-carry (\(\textsc {adc} \)), carrying addition-with-carry (\(\textsc {adcs} \)), subtraction (\(\textsc {sub} \)), borrowing subtraction (\(\textsc {subs} \)), half- (\(\textsc {mul} \)) and full-multiplication (\(\textsc {mull} \)). Moreover, logical left shift (\(\textsc {shl} \)) and logical right shift (\(\textsc {shr} \)) instructions are allowed. In addition to assignments, (modular) equations can be specified in assumption (\(\textsc {assume} \)) or assertion (\(\textsc {assert} \)) instructions. A program is a sequence of instructions. We assume \(\textsc {assert} \) instructions can only appear at the end of programs. They specify a (modular) equation to be verified and thus are emphasized with a framed box.

Fig. 2.
figure 2

ToyLang – Semantics

Let \(\sigma \) be a store. We write \(\sigma [v \mapsto bv]\) for the store obtained by mapping v to the bit-vector bv and other variables u to \(\sigma (u)\). \([\![{v}]\!]_{{\sigma }}\) represents the bit-vector \(\sigma (v)\) for any variable v; otherwise, \([\![{n}]\!]_{{\sigma }}\) is the bit-vector representing the number n of width w.

The semantics of ToyLang is defined with SMT QF_BV bit-vector functions (Fig. 2). In the figure, \({(\!|}{\sigma , s, \sigma '}{|\!)}\) denotes that the store \(\sigma '\) is obtained after executing the instruction s on the store \(\sigma \). The addition instruction \(\textsc {add} \) corresponds to the bit-vector addition function. For the addition with carry instruction, the carry bit is extended with \(w-1\) zeros and added to the sum of the first two operands. The two carrying addition instructions compute the bit-vector sums of width \(w+1\). The most significant bit is stored in the output carry bit. Subtraction instructions are similar; their semantics are defined with the bit-vector subtraction function \(\textit{bvsub} \) instead. The semantics of \(\textsc {shl} \) and \(\textsc {shr} \) instructions are defined by corresponding bit-vector functions \(\textit{bvshl} \) and \(\textit{bvlshr} \) respectively. The semantics of half-multiplication instruction \(\textsc {mul} \) uses the bit-vector multiplication function \(\textit{bvmul} \). For full-multiplication, both operands are extended to width 2w before computing their product.

Fig. 3.
figure 3

Semantics of (Modular) Equations

The \(\textsc {assume} \) instruction filters computations by (modular) equations. Figure 3 defines when a store satisfies a (modular) equation. A number n denotes a non-negative integer. A variable denotes the integer \(\textsf {toZ} ({[\![{v}]\!]_{{\sigma }}}) \) represented by the corresponding bit-vector \([\![{v}]\!]_{{\sigma }}\) in the store. Arithmetic operations denote corresponding integer operations. Particularly, the integer \(\{|{e}|\}_{{\sigma }}\) is exact and not necessarily less than \(2^w\). Equality denotes integer equality. \(\sigma \) satisfies \(e_0 \equiv e_1 \bmod [ f_0, f_1, \ldots , f_m ]\) if \(\{|{e_0}|\}_{{\sigma }} - \{|{e_1}|\}_{{\sigma }}\) is in the ideal generated by \(\{|{f_0}|\}_{{\sigma }}, \{|{f_1}|\}_{{\sigma }}, \ldots , \{|{f_m}|\}_{{\sigma }}\). The \(\textsc {assert} \) instruction checks if the current store satisfies the given (modular) equation. The computation resumes if it succeeds. It is an error if the \(\textsc {assert} \) instruction fails.

Fig. 4.
figure 4

Simplified Montgomery Reduction

Montgomery reduction algorithm is widely used to compute remainders without division [19]. Figure 4a shows a simplified unsigned Montgomery reduction algorithm.Footnote 1 Suppose we want to compute the remainder of a number \(0 \le T < R^2\) modulo N on 64-bit architectures with \(R = 2^{64}\). Montgomery reduction algorithm needs another number \(N'\) with \(NN' + 1 \equiv 0 \bmod R\) as an input. It first computes \(m = ((T \bmod R)N') \bmod R\) and then \(t = (T + mN)/R\). Observe that the remainder and quotient divided by \(R = 2^{64}\) amount to bit masking and shifting respectively. Arithmetic division is never used. To prove \(t R \equiv T \bmod N\), we first show \(T + mN \equiv 0 \bmod R\). Observe \(T + mN =T + (((T \bmod R)N') \bmod R)N \equiv T + TN'N \equiv T(1+N'N) \equiv 0 \bmod R\). Therefore, \(T + mN\) is a multiple of R and \(t = (T + mN)/R\) is an integer. Hence \(tR = T + mN \equiv T \bmod N\).

In the ToyLang implementation (Fig. 4b), we represent T by two 64-bit variables \(T_H\) and \(T_L\) with \(T = 2^{64}T_H + T_L\). Hence \(T_L = T \bmod 2^{64}\). m is computed by the half-multiplication instruction \(\textsc {mul} \). The full-multiplication computes the product mN of m and N. The following two addition instructions compute the sum of T and the product mN. After adding T, the least significant 64 bits (\(t_L\)) should be zeros. We hence assert \(t_L \equiv 0 \bmod [2^{64}]\). If the assertion succeeds, \(t_L\) is in fact 0 since it is a 64-bit variable. We thus assume \(t_L = 0\). The last assertion checks that the result \(2^{64}(2^{64}c + t_H)\) is indeed congruent to T modulo N.

4 Algebraic Abstraction

Algebraic abstraction is a technique to lift computation to an algebraic domain. In the abstract algebraic domain, program instructions are transformed to polynomial equations. Computation in turn is characterized by the roots of systems of polynomial equations. Algebraic abstraction hence allows us to apply algebraic tools from commutative algebra. The abstraction technique requires programs in the static single assignment form. We hence assume input programs are in the static single assignment form.

Fig. 5.
figure 5

Algebraic Abstraction

Figure 5 lifts ToyLang instructions to polynomial equations. Intuitively, we would like the semantics of each instruction characterized by roots of corresponding polynomial equations. For instance, \(v \leftarrow \textsc {add}\ a_0\ a_1\) is lifted to \(v = a_0 + a_1\). The \(\textsc {adc} \) instruction is similar. The carrying addition instruction \(c : v \leftarrow \textsc {adds}\ a_0\ a_1\) is lifted to two equations: \(c \cdot (c-1) = 0\) and \(c \cdot 2^w + v = a_0 + a_1\). Since c is a carry, it must be 0 or 1, and hence a root of \(c \cdot (c-1) = 0\). The carrying addition-with-carry instruction \(\textsc {adcs} \) is similar, as well as subtraction instructions \(\textsc {sub} \) and \(\textsc {subs} \).

The half-multiplication instruction \(v \leftarrow \textsc {mul}\ a_0\ a_1\) is lifted to \(v = a_0 \cdot a_1\); the full-multiplication instruction \(v_H : v_L \leftarrow \textsc {mull}\ a_0\ a_1\) corresponds to \(v_H \cdot 2^w + v_L = a_0 \cdot a_1\). The logical left shift instruction \(v \leftarrow \textsc {shl}\ a\ n\) corresponds to \(v = a \cdot 2^n\); the logical right shift instruction \(v \leftarrow \textsc {shr}\ a\ n\) is lifted to \(v \cdot 2^n = a\). The \(\textsc {assume}\ q\) instruction is lifted to the (modular) equation q. All computations thus must satisfy q. A ToyLang program is lifted to the system of (modular) equations from its instructions. The system of (modular) equations is called the abstract polynomial program. Figure 6 shows the abstract polynomial program for the Montgomery reduction program.

Fig. 6.
figure 6

Abstract Montgomery Reduction

4.1 Soundness Conditions

Algebraic abstraction in Fig. 5 however is unsound. The ToyLang semantics is defined over bounded integers of bit width w. Polynomial equations in algebraic abstraction are interpreted over integers. When overflow occurs in ToyLang instructions, for instance, its computation is not captured by corresponding polynomial equations. Consider the instruction \(v \leftarrow \textsc {add}\ 2^{w-1}\ 2^{w-1}\). By the ToyLang semantics, v has the bit-vector value \(\textit{bvadd}\ {[\![{2^{w-1}}]\!]_{{\sigma }}} {[\![{2^{w-1}}]\!]_{{\sigma }}} = {0}\) after execution. Clearly, 0 is not a root of the equation \(v = 2^{w-1} + 2^{w-1}\). The abstraction is unsound.

In order to check soundness for algebraic abstraction, we define soundness conditions for ToyLang instructions to ensure that all computations are captured by corresponding polynomial equations. Intuitively, we give an SMT QF_BV query for each instruction in a ToyLang program such that the query is satisfiable if and only if the computation at the instruction can overflow.

To this end, we first use SMT QF_BV logic to characterize computations in ToyLang programs. Recall ToyLang programs are in the static single assignment form. Figure 7 defines an SMT QF_BV query \(\lfloor P \rceil \) for any ToyLang program P. Except the \(\textsc {assume} \) instruction, the figure follows the semantics of ToyLang. For instance, \(\lfloor v \leftarrow \textsc {adc}\ a_0\ a_1\ d \rceil \) asserts v equal to the bit-vector sum of \(a_0\) and \(a_1\) with d extended by \(w - 1\) zeros in the SMT QF_BV query. Others are similar. It is not hard to see that all computations of a ToyLang program satisfy the corresponding SMT QF_BV query.

Lemma 1

Let P be a ToyLang program without \(\textsc {assert} \) instructions and \(\sigma , \sigma '\) stores with \({(\!|}{\sigma , P, \sigma '}{|\!)}\). Then the SMT QF_BV query \(\lfloor P \rceil \) is satisfied by the store \(\sigma '\).

Fig. 7.
figure 7

Soundness Conditions I

Our next task is to define SMT QF_BV queries for instructions such that their algebraic abstraction is unsound if and only if the corresponding SMT QF_BV query is satisfiable (Fig. 8). The instruction \(v \leftarrow \textsc {add}\ a_0\ a_1\) is lifted to \(v = a_0 + a_1\). The abstraction is unsound when there is carry. That is, \((\textit{bvextract}\ w\ w\ (\textit{bvadd} \) \({(\textit{zero}\_\textit{extend}\ {a_0}\ {1})}\) \({(\textit{zero}\_\textit{extend}\ {a_1}\ {1})}))\) is 1. The instructions \(\textsc {adc} \) and \(\textsc {sub} \) are similar. Algebraic abstraction for the instructions \(\textsc {adds} \), \(\textsc {adcs} \) and \(\textsc {subs} \) is always sound. Their corresponding SMT QF_BV queries are not satisfiable \((\textit{assert}\ {\bot }) \). For the half-multiplication \(v \leftarrow \textsc {mul}\ a_0\ a_1\), its abstraction \(v = a_0 \cdot a_1\) is unsound when the most significant w bits of the product of \(a_0\) and \(a_1\) are not all zeros. The corresponding SMT QF_BV query is hence \((\textit{assert}\ {(\textit{not}\ {(=\ {0}\ {(\textit{bvextract}\ {(2w-1)}\ {w}\ {bvx})})})}) \) where bvx is the bit-vector product of \(a_0\) and \(a_1\). The abstraction for full-multiplication instruction is never unsound. For the \(v \leftarrow \textsc {shl}\ a_0\ n\) instruction, its algebraic abstraction is unsound if the most significant n bits of \(a_0\) are not zeros. The algebraic abstraction of the \(v \leftarrow \textsc {shr}\ a_0\ n\) instruction is unsound when the least significant n bits of \(a_0\) are not zeros. Relevant bits are obtained by \(\textit{bvextract} \) respectively. The abstraction for \(\textsc {assume} \) is always sound.

Fig. 8.
figure 8

Soundness Conditions II

To check soundness of the algebraic abstraction \(\lceil s \rceil \) for the instruction s in the ToyLang program \(P\ s\), we apply Lemma 1 to obtain a computation of P through \(\lfloor P \rceil \) and check if \(\lfloor s \rfloor \) for s is unsatisfiable. We say the soundness condition for the instruction s in the ToyLang program \(P\ s\) holds if \(\lfloor P\ s \rfloor \) is unsatisfiable. In order to ensure the soundness of the abstract polynomial program \(\lceil P \rceil \) for the ToyLang program P, soundness conditions for all instructions in P must hold. That is, soundness conditions for s in all prefixes \(P'\ s\) of P must hold. Define the valuation \(\rho _\sigma \) of the store \(\sigma \) by \(\rho _\sigma (v) = \textsf {toZ} ({[\![{v}]\!]_{{\sigma }}}) \) for every \(v \in \overline{\textbf{x}}\). The next theorem gives the soundness condition.

Proposition 1 (Soundness)

Let P be a ToyLang program without \(\textsc {assert} \) instructions and \(\sigma , \sigma '\) stores with \({(\!|}{\sigma , P, \sigma '}{|\!)}\). \(\rho _{\sigma '}\) is a root of the system of (modular) equations \(\lceil P \rceil \) if soundness conditions for s in every prefix \(P'\ s\) of P hold.

We say that the soundness condition for P holds if soundness conditions for s in all prefixes \(P'\ s\) of P hold. Let us take a closer look at the abstract Montgomery reduction program (Fig. 6). The half-multiplication instruction \(m \leftarrow \textsc {mul}\ T_L\ N'\) is lifted to \(m = T_L \cdot N'\). However, the soundness condition for the instruction requires the most significant 64 bits of the product to be zeros (Fig. 8). Since \(T_L\) is arbitrary, the soundness condition does not hold in general. To obtain a sound algebraic abstraction for Montgomery reduction, we modify the ToyLang program slightly (Fig. 9).

In the revised program, the first full-multiplication instruction is used to compute the least significant 64 bits of the product of \(T_L\) and \(N'\) (marked by \(\surd \)). The most significant 64 bits of the product are stored in the variable dc (for don’t care). Note that the soundness condition of the revised program holds trivially. The algebraic abstraction for the revised Montgomery reduction program is sound by Proposition 1.

Fig. 9.
figure 9

Abstract Montgomery Reduction (Revised)

4.2 Polynomial Program Verification

Let P be a ToyLang program without assert instructions. Our goal is to verify with algebraic abstraction. Consider the system of (modular) equations \(\varPhi = \lceil P \rceil \). For any stores \(\sigma \) and \(\sigma '\) with \({(\!|}{\sigma , P, \sigma '}{|\!)}\), \(\rho _{\sigma '}\) is a root of \(\varPhi \) if the soundness condition for P holds by Proposition 1. To verify \(\textsc {assert}\ \phi \) on \(\sigma '\), we need to check if \(\rho _{\sigma '}\) is also a root of the (modular) equation \(\phi \). That is, we want to show if \(\forall \overline{\textbf{x}}. \varPhi \implies \phi \).

Proposition 2

Let P be a ToyLang program without assert instructions and \(\phi \) a (modular) equation. Suppose the soundness condition for P holds. The assertion in succeeds if \(\forall \overline{\textbf{x}}. \lceil P \rceil \implies \phi \).

We extend [14] to check the root entailment problem. Recall that \(\varPhi \) is a system of (modular) equations. We first simplify it to a system of equations. This is best seen by an example. Consider \(\forall x\ y\ u\ v. x \equiv y \bmod [3u^2, u+v] \implies 0=0\). We have

$$\begin{aligned}{} & {} \qquad \forall x\ y\ u\ v. x \equiv y \bmod [3u^2, u+v] \implies 0=0\\{} & {} \text {iff} \forall x\ y\ u\ v. [\exists k_0\ k_1 (x - y = 3u^2 \cdot k_0 + (u+v) \cdot k_1)] \implies 0=0\\{} & {} \text {iff} \forall x\ y\ u\ v\ k_0\ k_1 . x - y = 3u^2 \cdot k_0 + (u+v) \cdot k_1 \implies 0=0. \end{aligned}$$

Therefore, it suffices to consider the problem of checking \(\forall \overline{\textbf{x}}. \varPsi \implies \phi \) where \(\varPsi \) is a system of equations and \(\phi \) is a (modular) equation. We solve the simplified problem by constructing instances of the ideal membership problem.

Let \(\varPsi = \{ e_0 = e'_0, e_1 = e'_1, \ldots , e_n = e'_n \}\). Consider the ideal \(I = \langle e_0 - e'_0, e_1 - e'_1, \ldots , e_n - e'_n \rangle \) generated by the polynomial equations in \(\varPsi \). Suppose the polynomial \(e - e' \in I\). We claim \(\forall \overline{\textbf{x}}. \varPsi \implies e = e'\). Indeed, \(e - e' = (e_0 - e'_0) \cdot h_0 + (e_1 - e'_1) \cdot h_1 + \cdots + (e_n - e'_n) \cdot h_n\) for some \(h_0, h_1, \ldots , h_n \in \mathbb {Z}[\overline{\textbf{x}}]\) since \(e - e' \in I\). For any root \(\rho \) of \(\varPsi \), \((e_0 - e'_0)[\rho ] = (e_1 - e'_1)[\rho ] = \cdots = (e_n - e'_n)[\rho ] = 0\). Hence \((e - e')[\rho ] = ((e_0 - e'_0)\cdot h_0) [\rho ] + ((e_1 - e'_1)\cdot h_1)[\rho ] + \cdots + ((e_n - e'_n)\cdot h_n) [\rho ] = 0\). \(\rho \) is also a root of \(e - e' = 0\) and thus \(\forall \overline{\textbf{x}}. \varPsi \implies e = e'\).

Now suppose the polynomial \(e - e' \in I + \langle f_0, f_1, \ldots , f_m \rangle \). We claim \(\forall \overline{\textbf{x}}. \varPsi \implies e \equiv e' \bmod [ f_0, f_1, \ldots , f_m ]\). Since \(e - e' \in I + \langle f_0, f_1, \ldots , f_m \rangle \), \(e - e' = (e_0 - e'_0) \cdot h_0 + (e_1 - e'_1) \cdot h_1 + \cdots + (e_n - e'_n) \cdot h_n + f_0 \cdot k_0 + f_1 \cdot k_1 + \cdots + f_m \cdot k_m\) for some \(h_0, h_1, \ldots , h_n, k_0, k_1, \ldots , k_m \in \mathbb {Z}[\overline{\textbf{x}}]\). For any root \(\rho \) of \(\varPsi \), \((e - e')[\rho ] = ((e_0 - e'_0) \cdot h_0)[\rho ] + ((e_1 - e'_1) \cdot h_1)[\rho ] + \cdots + ((e_n - e'_n) \cdot h_n)[\rho ] + f_0\cdot k_0[\rho ] + f_1 \cdot k_1[\rho ] + \cdots + f_m \cdot k_m [\rho ] = 0 + f_0[\rho ]k_0[\rho ] + f_1[\rho ] k_1[\rho ] + \cdots + f_m[\rho ] k_m[\rho ]\). We again have \(\forall \overline{\textbf{x}}. \varPsi \implies e \equiv e' \bmod [ f_0, f_1, \ldots , f_m ]\) as required.

Fig. 10.
figure 10

Polynomial Programs to Ideals

Our discussion is summarized as follows.

Proposition 3

Let P be a ToyLang program without assert instructions and I the ideal with \(\lceil P \rceil \rightsquigarrow I\) (Fig. 10). Then

  1. 1.

    \(\forall \overline{\textbf{x}}. \lceil P \rceil \implies e = e'\) if \(e - e' \in I\);

  2. 2.

    \(\forall \overline{\textbf{x}}. \lceil P \rceil \implies e \equiv e' \bmod [ f_0, f_1, \ldots , f_m ]\) if \(e - e' \in I + \langle f_0, f_1, \ldots , f_m \rangle \).

In order to verify (modular) equations with algebraic abstraction, Proposition 1 is applied to ensure the soundness of abstraction. Proposition 3 then checks whether (modular) equations indeed are satisfied for abstract polynomial programs. The main theorem summarizes our theoretical developments.

Theorem 1

Let P be a ToyLang program without assert instructions, \(\sigma , \sigma '\) stores with \({(\!|}{\sigma , P, \sigma '}{|\!)}\) and I the ideal with \(\lceil P \rceil \rightsquigarrow I\). If the soundness condition for P holds,

  1. 1.

    the assertion in succeeds provided \(e - e' \in I\);

  2. 2.

    the assertion in succeeds provided \(e - e' \in I + \langle f_0, f_1, \ldots , f_m \rangle \).

The ideal membership problem can be solved by computing Gröbner bases for ideals [7]. Many computer algebra systems compute Gröbner bases for ideals with simple commands. For instance, the groebner command in Singular  [13] computes a Gröbner basis for any ideal by a user-specified monomial ordering. The reduce command then checks if a polynomial belongs to the ideal via its Gröbner basis.

Fig. 11.
figure 11

Instances of Ideal Membership Problem

Recall the abstract polynomial program for revised Montgomery reduction in Fig. 9. Figure 11a shows the ideal for the abstract polynomial program before \(\textsc {assume} \) \(t_L = 0\). To verify the two assert instructions, Figs. 11b and 11c show the instances of the ideal membership problem corresponding to the two assertions. Observe the ideal \(\langle t_L \rangle \) corresponds to \(\textsc {assume}\ t_L = 0\) in Fig. 11c. Since the soundness condition for the abstract polynomial program holds trivially (Sect. 4.1), it remains to check the ideal membership problem. Both instances are verified immediately.

5 Certified Verification

In ToyLang, we only highlight necessary instructions to verify unsigned Montgomery reduction. For real-world programs performing non-linear computation, more instructions are needed and the signed representation of bit-vectors is also used. In order to verify real-world cryptographic programs, we extend algebraic abstraction with these features found in CryptoLine  [9, 29]. For such complicated languages, algebraic abstraction can be tedious to implement. Its verification algorithm moreover relies on complex algorithms from computer algebra systems and SMT QF_BV solvers. It is unclear whether these external tools function correctly on given instances. In order to improve the quality of verification results, we have verified algebraic abstraction with the proof assistant Coq, and certified results from external tools with Coq and a verified certificate checker. We briefly describe how to verify our algorithms and certify results from external tools. Please see the technical report [28] for details.

5.1 Verified Abstraction Algorithm

The proof assistant Coq with the SSReflect library [4, 11] is used to verify our algebraic abstraction technique. We define the ToyLang syntax as a Coq data type (Fig. 1). The coq-nbits theory [26] is adopted to formalize the semantics of ToyLang (Fig. 2). The Coq binary integer theory \(\textsf {Z} \) is used to formalize the semantics of (modular) equations (Fig. 3). We formalize polynomial expressions with integral coefficients by the Coq polynomial expression theory PExpr Z.

To see how our algebraic abstraction algorithm is verified, consider Proposition 2. Let program be the Coq data type for ToyLang programs and meqn the data type for (modular) equations. We define the predicate algsnd : program \(\rightarrow \) Prop for the soundness condition for a given program (Figs. 7 and 8). Similarly, we define the function algabs : program \(\rightarrow \) seq meqn for our algebraic abstraction algorithm where seq meqn is the Coq data type for sequences of meqn (Fig. 5). To write down the formal statement for Proposition 2, it remains to formalize the root entailment. Let exp and valuation be the data types for expressions and valuations respectively. Define the function eval_exp : exp \(\rightarrow \) valuation \(\rightarrow \) Z which evaluates an expression to an integer on a valuation; and eval_exps : seq exp \(\rightarrow \) valuation \(\rightarrow \) seq Z evaluates expressions to integers on a valuation. Consider the predicate eval_bexp : meqn \(\rightarrow \) valuation \(\rightarrow \) Prop defined by

$$\begin{aligned}{} & {} \qquad \quad \textsf {eval\_bexp (e = e') rho} \textsf {:=} \textsf {eval\_exp e rho = eval\_exp e' rho} \\{} & {} \textsf {eval\_bexp (e = e' mod fs) rho} \textsf {:=} \exists \textsf {ks, (eval\_exp e rho) - (eval\_exp e' rho) =} \\{} & {} \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \textsf {zadds (zmuls ks (eval\_exps fs rho))} \end{aligned}$$

where zadds zs := foldl Z.add 0 zs and zmuls xs ys := map2 Z.mul xs ys. The predicate eval_bexp (e = e’) rho checks if the expressions e and e’ evaluate to the same integer on the valuation rho; eval_bexp (e = e’ mod fs) rho checks if the difference of eval_exp e rho and eval_exp e’ rho is equal to a linear combination of the integers eval_exps fs rho. The predicate eval_bexp meq rho thus checks if rho is a root of the (modular) equation meq.

We are ready to formalize the root entailment. Consider the predicate entails (Phi : seq meqn) (psi : meqn) : Prop defined by

$$ \forall \textsf {rho}, (\forall \textsf {phi}, \textsf {phi} \in \textsf {Phi} \rightarrow \textsf {eval\_bexp phi rho}) \rightarrow \textsf {eval\_bexp psi rho}. $$

That is, every common root of the system Phi is also a root of psi. The following proposition formalizes Proposition 2 and is proved in Coq.

Proposition 4

Let P : program be without assert instructions and psi : meqn. If algsnd P and entails (algabs P) psi, then the assertion in succeeds.

To apply this proposition to a given program P and a (modular) equation psi, one needs to show algsnd P and entails (algabs P) psi in Coq. In principle, both predicates algsnd P and entails (algabs P) psi could be proved manually in Coq. However, it would be impractical even for programs of moderate sizes. To address this problem, we establish these predicates through certificates computed by external tools.

5.2 Verification through Certification

To show algsnd P for an arbitrary program P, we follow the certified verification technique developed in the SMT QF_BV solver CoqQFBV  [26]. More concretely, we specify our bit-blasting algorithm for soundness conditions in Coq (Figs. 7 and 8). The algorithm converts soundness conditions to Boolean formulae in the conjunctive normal form. We then formally verify that soundness conditions hold if and only if the corresponding Boolean formulae are unsatisfiable in Coq. The constructed Boolean formulae are sent to the SAT solver Kissat  [5]. For each Boolean formula, Kissat checks its satisfiability with a certificate. We then use the verified certificate checker gratchk  [16] to validate these certificates.

Our next goal is to show entails (algabs P) psi. More generally, we show entails Phi psi with arbitrary Phi : seq meqn and psi : meqn via the Coq polynomial ring theory and the computer algebra system Singular  [13]. To this end, we first formulate the root entailment of polynomial expressions in the Coq polynomial ring theory. Recall PExpr Z is the Coq data type for polynomial expressions with integral coefficients. Given integers, the function zpeval : PExpr Z \(\rightarrow \) seq Z \(\rightarrow \) Z evaluates a polynomial expression to an integer. We formalize the root entailment of polynomial expressions by the predicate zpentails (Pi : seq (PExpr Z)) (tau : PExpr Z):

$$ \forall \textsf {zs}, (\forall \textsf {pi}, \textsf {pi} \in \textsf {Pi} \rightarrow \textsf { zpeval pi zs = 0}) \rightarrow \textsf { zpeval tau zs = 0}. $$

We proceed to connect the root entailment of (modular) equations to the root entailment of polynomial expressions. Let the functions zpexprs_of_exprs : seq expr \(\rightarrow \) seq (PExpr Z) and zpexprs_of_meqns : seq meqn \(\rightarrow \) seq (PExpr Z) convert expressions and (modular) equations to polynomial expressions respectively (Fig. 10). When the consequence of root entailment is a modular equation, recall that moduli in the consequence become ideal generators (Proposition 3). To extract moduli from consequences, define zpexpr_of_conseq : meqn \(\rightarrow \) PExpr Z \(\times \) seq (PExpr Z) by

$$\begin{aligned}{} & {} \qquad \textsf {zpexpr\_of\_conseq (e = e')} \textsf {:=} \textsf {(e - e', [::])} \\{} & {} \textsf {zpexpr\_of\_conseq (e = e' mod fs)} \textsf {:=} \textsf {(e - e', zpexprs\_of\_exprs fs)} \end{aligned}$$

The following Coq lemma shows how to check the root entailment of (modular) equations through the root entailment of polynomial expressions:

Lemma 2

\(\forall \) (Phi : seq meqn) (psi : meqn), zpentails (Pi ++ zpexprs_of_meqns Phi) tau implies entails Phi psi where (tau, Pi) = zpexpr_of_conseq psi.

Note that moduli in the consequence psi are added to the antecedents Phi.

Our last step is to show zpentails (Pi ++ zpexprs_of_meqns Phi) tau. Again, we establish the generalized form zpentails Pi tau for polynomial expressions Pi and a polynomial expression tau. We prove the predicate by showing that tau can be expressed as a combination of expressions in Pi. Consider the predicate validate_zpentails (Xi : seq (PExpr Z)) (Pi : seq (PExpr Z)) (tau : PExpr Z) defined by

$$ \begin{array}{l} \textsf {size Xi = size Pi } \wedge \\ \textsf {ZPeq (ZPnorm tau) (ZPnorm (foldl ZPadd 0 (map2 ZPmul Xi Pi)))}. \end{array} $$

The predicate validate_zpentails checks if the Xi and Pi are of the same size. It then normalizes the polynomials tau and foldl ZPadd 0 (map2 ZPmul Xi Pi) using ZPnorm. If normalized polynomials are equal (ZPeq), the predicate is true. In foldl ZPadd 0 (map2 ZPmul Xi Pi), ZPadd and ZPmul are the constructors for polynomial expression addition and multiplication respectively. The expression map2 ZPmul Xi Pi hence returns products of elements in Xi with corresponding elements in Pi. The expression foldl ZPadd 0 (map2 ZPmul Xi Pi) then computes the sum of these products. The predicate validate_zpentails Xi Pi tau therefore checks if tau is equal to a polynomial combination of expressions in Pi. In other words, tau belongs to the ideal generated by Pi. Using Lemma 2, we prove the following variant of Proposition 3 in Coq:

Proposition 5

\(\forall \) Phi psi Xi, validate_zpentails Xi (Pi ++ zpexprs_of_meqns Phi) tau implies entails Phi psi where (tau, Pi) = zpexpr_of_conseq psi.

The main difference between Propositions 3 and 5 lies in certifiability. There are many ways to establish ideal membership. Proposition 5 asks for witnesses Xi to justify ideal membership explicitly. Most importantly, such Xi need not be constructed manually. They are in fact computed by external tools. Precisely, these polynomial expressions are computed by the lift command in the computer algebra system Singular  [13]. The lift command computes polynomial expressions representing tau in the ideal generated by Pi ++ zpexprs_of_meqns Phi. After Singular computes these polynomial expressions, we convert them to polynomial expressions Xi in Coq. The predicate validate_zpentails Xi (Pi ++ zpexprs_of_meqns Phi) tau checks if tau is indeed represented by Xi using the Coq polynomial ring theory. If the check succeeds, we obtain entails Phi psi by Proposition 5. Otherwise, the predicate entails Phi psi is not established. Note that Singular need not be trusted. If Xi is computed incorrectly, the check validate_zpentails Xi (Pi ++ zpexprs_of_meqns Phi) tau will fail in Coq. Proposition 5 allows us to show entails Phi psi with certification.

5.3 Optimization

Lots of optimizations are needed and verified to make algebraic abstraction feasible for ToyLang programs with thousands of instructions. For instance, the static single assignment transformation and program slicing algorithms are both specified and verified in Coq. Furthermore, the bit blasting algorithm is extended significantly to check soundness conditions effectively. For example, the soundness condition for the half-multiplication instruction \(\textsc {mul} \) requires \(\textit{bvmul} \) (Fig. 8). This could not work well because of complicated non-linear bit-vector computation. To reduce the complexity of overflow checking in half-multiplication, we implement and verify the algorithm from [10]. Last but not least, algebraic abstraction almost surely induces ideals with hundreds of polynomial generators if not thousands. Computing Gröbner bases for such ideals is infeasible. To address this problem, we develop heuristics to reduce the number of generators in ideals through rewriting. Our heuristics are also specified and verified in Coq. These optimizations are essential in our experiments.

6 Evaluation

We have implemented certified algebraic abstraction in the tool CoqCryptoLine  [1]. CoqCryptoLine is built upon OCaml codes extracted from our Coq development. It calls the computer algebra system Singular  [13] and certifies answers from the algebraic tool. The certified SMT QF_BV solver CoqQFBV  [26] is used to verify soundness conditions. We choose two classes of real-world cryptographic programs in experiments. For elliptic curve cryptography, we verify various field or group operations from Bitcoin  [27], boringSSL  [8, 12], nss  [20], OpenSSL  [23], and PQCrypto-SIDH  [18]. For post-quantum cryptography, we verify the C reference and optimized Intel avx2 implementations of the Number-Theoretic Transform in the cryptosystem Kyber  [6]. Experiments are conducted on an Ubuntu 22.04.1 Linux server with 3.20 GHz 32-core Xeon Gold 6134M and 1TB RAM.

We compare CoqCryptoLine with the uncertified CryptoLine  [9, 24]. Table 1 shows the experimental results. \(L_{CL}\) shows the number of instructions. \(T_{CCL}\) and \(T_{CL}\) give the verification time of CoqCryptoLine and CryptoLine in seconds respectively. \(\%_{Int}\) shows the percentage of time spent in extracted OCaml programs in CoqCryptoLine. \(\%_{CAS}\) and \(\%_{SMT}\) give the percentages of time spent on Singular and CoqQFBV respectively.

Table 1. Experimental Results on Industrial Cryptographic Programs

6.1 Field and Group Operation in Elliptic Curves

In elliptic curve cryptography, a rational point on a curve is represented by field elements from a large finite field. Rational points on the curve form a group. The group operation in turn is computed by operations in the underlying finite field. In Bitcoin, the finite field is \(\mathbb {Z}_{p256k1}\) with \(p256k1 = 2^{256} - 2^{32} - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1\). The underlying field for Curve25519 is \(\mathbb {Z}_{p25519}\) with \(p25519 = 2^{255} - 19\). PQCrypto-SIDH however uses slightly more complicated fields \(\mathbb {Z}_{p434}/\langle x^2 + 1\rangle \) and \(\mathbb {Z}_{p503}/\langle x^2 + 1 \rangle \) with \(p434 = 2^{216} \cdot 3^{137}-1\) and \(p503 = 2^{250} \cdot 3^{159}-1\). Field elements in \(\mathbb {Z}_{p256k1}\) and \(\mathbb {Z}_{p25519}\) are represented by multiple limbs of 64-bit numbers. Field multiplication, for instance, is implemented by a number of 64-bit arithmetic instructions. Field elements in \(\mathbb {Z}_{p434}/\langle x^2 + 1\rangle \) and \(\mathbb {Z}_{p503}/\langle x^2 + 1 \rangle \) are of the form \({u} + {v}x\) where \({u}, {v} \in \mathbb {Z}_{p434}\) or \(\mathbb {Z}_{p503}\) and \(x^2 = -1\). Two moduli are used to specify multiplication for such fields: p434, \(x^2 + 1\) for \(\mathbb {Z}_{p434}/\langle x^2 + 1\rangle \), and p503, \(x^2 + 1\) for \(\mathbb {Z}_{p503}/\langle x^2 + 1\rangle \). Multiplication of PQCrypto-SIDH is easily specified by modular equations with multiple moduli.

CoqCryptoLine verifies every field operation with certification within 12.1 min. Group operations are implemented by field operations. Their certified verification thus takes more time. The most complicated case x25519_scalar_mult_generic (3287 instructions) from boringSSL takes about 1.3 h.\(^\textrm{a}\) In comparison, CryptoLine verifies the same program in 4 min without certification. In almost all cases, a majority of time is spent on CoqQFBV. Running time for extracted OCaml programs is negligible. Interestingly, CoqCryptoLine finds a bug in the arm64 multiplication code for \(\mathbb {Z}_{p503}/\langle x^2 + 1 \rangle \) from PQCrypto-SIDH. Towards the end of multiplication, the programmer incorrectly stores the register x25 in memory before adding a carry. After fixing the bug, CoqCryptoLine finishes certified verification in about 5 min.

6.2 Number-Theoretic Transform in Kyber

The United States National Institute of Standards and Technology (NIST) is currently determining next-generation post-quantum cryptography (PQC) standards. In July 2022, Crystals-Kyber (or simply Kyber) was announced to be the winner for key establishment mechanisms.

One of the most critical steps in Kyber is modular polynomial multiplication over the polynomial ring \(\mathcal {R}_q=\mathbb {Z}_q[x]/\langle x^{256}+1\rangle \) with \(q=3329\). In \(\mathcal {R}_q\), coefficients are elements in the field \(\mathbb {Z}_q\). A polynomial in \(\mathcal {R}_q\) is obtained by modulo \(x^{256} + 1\) and hence has a degree less than 256. Consider \(x^{256} \in \mathbb {Z}_q[x]\). Since \(x^{256} \equiv -1 \bmod (x^{256} + 1)\), \(x^{256}\) is \(-1\) in \(\mathcal {R}_q\). Unsurprisingly, polynomial multiplication is one of the most expensive computations in Kyber. An efficient way to multiply polynomials is through a discretized Fast Fourier Transform called the Number-Theoretic Transform (NTT).

Recall the Chinese remainder theorem for integers is but a ring isomorphism between residue systems. For instance, \(\mathbb {Z}_{42} \cong \mathbb {Z}_6 \times \mathbb {Z}_7\). For polynomial rings, we have the following ring isomorphism

$$ \mathbb {Z}_q[x]/\langle x^{2n}-\omega ^2\rangle \cong \mathbb {Z}_q[x]/\langle x^{n}-\omega \rangle \times \mathbb {Z}_q[x]/\langle x^{n}+\omega \rangle (\omega \in \mathbb {Z}_q). $$

Observe that \(x^n\) is equal to \(\omega \) in \(\mathbb {Z}_q[x]/\langle x^{n}-\omega \rangle \) for \(x^n \equiv \omega \mod (x^n - \omega )\). Similarly, \(x^n\) is equal to \(-\omega \) in \(\mathbb {Z}_q[x]/\langle x^{n}+\omega \rangle \). Recall polynomials in \(\mathbb {Z}_q[x]/\langle x^{2n}-\omega ^2\rangle \) have degrees less than 2n. We can rewrite any polynomial in \(\mathbb {Z}_q[x]/\langle x^{2n}-\omega ^2\rangle \) as \(f (x) + g (x)x^n\) where degrees of f and g are both less than n. The polynomial \(f (x) + g (x)x^n\) is then equal to \(f (x) + \omega g (x)\) in \(\mathbb {Z}_q[x]/\langle x^{n}-\omega \rangle \); and it is equal to \(f (x) - \omega g (x)\) in \(\mathbb {Z}_q[x]/\langle x^{n}+\omega \rangle \). NTT computes the following ring isomorphism between \(\mathbb {Z}_q[x]/\langle x^{2n}-\omega ^2\rangle \) and \(\mathbb {Z}_q[x]/\langle x^{n}-\omega \rangle \times \mathbb {Z}_q[x]/\langle x^{n}+\omega \rangle \) by substituting \(\pm \omega \) for \(x^n\) in \(f (x) + g (x)x^n\):

$$\begin{aligned} f(x)+g(x)x^n \leftrightarrow \left( f(x)+\omega g(x), f(x)-\omega g(x)\right) . \end{aligned}$$
(1)

Multiplication in \(\mathbb {Z}_q[x]/\langle x^{2n}-\omega ^2\rangle \) can therefore be computed by respective multiplications in \(\mathbb {Z}_q[x]/\langle x^{n}\pm \omega \rangle \) through the isomorphism. That is, a multiplication for polynomials of degrees less than 2n (in \(\mathbb {Z}_q[x]/\langle x^{2n}-\omega ^2\rangle \)) is replaced by two multiplications for polynomials of degrees less than n (in \(\mathbb {Z}_q[x]/\langle x^{n}\pm \omega \rangle \)).

In Kyber, ring isomorphisms are applied repeatedly until linear polynomials are obtained. That is, Kyber NTT computes the isomorphism

$$\begin{aligned} \mathcal {R}_q = \mathbb {Z}_q[x]/\langle x^{256}+1\rangle \cong \mathbb {Z}_q[x]/\langle x^{2}-\zeta _0\rangle \times \cdots \times \mathbb {Z}_q[x]/\langle x^{2}-\zeta _{127}\rangle \end{aligned}$$
(2)

where \(\zeta _j\)’s are the principal 256-th roots of unity. A polynomial of a degree less than 256 is hence mapped via Kyber NTT to 128 linear polynomials, each modulo a different \(x^2-\zeta _j\). In PQClean  [25], a reference C implementation and a hand-optimized Intel avx2 assembly implementation of Kyber NTT are provided. In addition to degree reduction, the two implementations utilize signed Montgomery reduction extensively for efficient multiplication over \(\mathbb {Z}_q\). We verify whether the two NTT implementations compute the ring isomorphism correctly.

To specify the correctness requirements of Kyber NTT, one could write down modular equations (1) according to its computation. Each equation would require explicit substitution. Thanks to modular equations with multiple moduli, a more intuitive and mathematical specification based on (2) is also expressible. Let \(F = \Sigma _{k=0}^{255}f_k x^k\) denote the input polynomial in \(\mathcal {R}_q = \mathbb {Z}_q[x]/\langle x^{256}+1\rangle \) and the coefficients \(f_k\)’s are input variables with \(-q< f_k < q\) (\(0\le k < 256\)). Let \(G_j = g_{j,0} + g_{j,1} x\) be the j-th final output linear polynomial from the implementations. The modular equations

$$ F \equiv G_j \bmod [q, x^2 - \zeta _j], \text{ for } \text{ all } 0\le j < 128 $$

specify the correctness of the Kyber NTT implementations. Observe that our specification is almost identical to (2). Modular equations with multiple moduli allow cryptographic programmers to express mathematical specification naturally. They greatly improve usability and reduce specification efforts in algebraic abstraction.

CoqCryptoLine verifies the C reference implementation in about 18.6 min. The highly optimized avx2 implementation is verified in about 7.2 min. Observe that each layer of ring isomorphism requires 128 signed Montgomery reductions. Kyber NTT therefore has \(7 \times 128 = 896\) Montgomery reductions similar to the running example in Fig. 4b. Algebraic abstraction successfully verifies the two Kyber NTT implementations within 20 min. In comparison, CryptoLine verifies both NTT implementations in 1 min without certification.

7 Conclusion

Verification through algebraic abstraction combines both algebraic and bit-accurate analyses. Non-linear computation is analyzed algebraically; soundness conditions are checked with bit-accurate SMT QF_BV solvers. We describe how to verify the technique and certify its results. In the experiments, the hybrid technique successfully verifies non-linear integer computation found in cryptographic programs from elliptic curve and post-quantum cryptography with certification. We plan to explore more applications of algebraic abstraction in programs from post-quantum cryptography in near future.