Skip to content

Commit

Permalink
Merge pull request #21 from formosa-crypto/proof-optimization
Browse files Browse the repository at this point in the history
Further proof optimization
  • Loading branch information
tfaoliveira-sb authored Oct 1, 2024
2 parents 97e789f + 9e109bc commit 1bc6d07
Show file tree
Hide file tree
Showing 29 changed files with 274 additions and 510 deletions.
4 changes: 2 additions & 2 deletions proof/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ EXCLUDE ?=
EXTRACTED ?= $(shell find $(PROOF) -type f -name "*_s.ec")
EXTRACTED_OUT := $(addsuffix .out, $(EXTRACTED))

ALL ?= $(shell find $(PROOF) -type f -name "*.ec")
ALL ?= $(shell find $(PROOF)/crypto_* -type f -name "*.ec")
ALL_OUT := $(addsuffix .out, $(ALL))


Expand Down Expand Up @@ -68,7 +68,7 @@ $(ALL_OUT):
ifeq ($(CI),1)
mkdir -p $(@D)/$(CI_DIR)
endif
($(EASYCRYPT) -R arrays/ $(ECARGS) $(subst .out,,$@) > $@) $(CI_CMD) || !(($(FAIL_ON_ERROR)))
($(EASYCRYPT) -R arrays/ -R $(abspath $(@D)/../../) $(ECARGS) $(subst .out,,$@) > $@) $(CI_CMD) || !(($(FAIL_ON_ERROR)))


# -----------------------------------------------------------------------------
Expand Down
15 changes: 6 additions & 9 deletions proof/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Formosa-25519 proof
# `crypto_scalarmult/curve25519` proof
Correctness proof for the reference and optimised 4-limb implementation in Jasmin.

Note, some lemmas are left with the tactic `admit`, which means that the lemmas are not proven, but assumed to be correct. All `admits` have been proved in Cryptoline and including them is future work.
Expand All @@ -8,10 +8,9 @@ Note, some lemmas are left with the tactic `admit`, which means that the lemmas
The logic in the `common/` folder is that the following files provide various lemmas used throughout the correctness proofs.

#### Generic files
- **W64limbs.ec** includes lemmas that lay the foundation of implementations using limbs of unsigned 64-bit words, such as digit representation, addition and redundant limbs. No dependencies.
- **EClib.ec** includes lemmas relating the implementation of elliptic curve cryptography, such as packing/unpacking. Depends on W64limbs.
- **Zp_25519** includes lemmas relating to the finite field of size 2^255 - 19, such as congruence over said finite field and reduction. Depends on both EClib and W64limbs.
- **Zp_limbs** includes lemmas concerning the implementation of 4 limbs representations (called `valRep4` in these proofs). Some miscellaneous lemmas concerning, for example, valid pointers are also present. Depends on the above three files.
- **EClib.ec** includes lemmas relating the implementation of elliptic curve cryptography, such as packing/unpacking. No dependencies.
- **Zp_25519** includes lemmas relating to the finite field of size 2^255 - 19, such as congruence over said finite field and reduction. No dependencies.
- **Zp_limbs** includes lemmas concerning the implementation of 4 limbs representations (called `valRep4` in these proofs). Some miscellaneous lemmas concerning, for example, valid pointers are also present. Depends on the above two files.

Naturally, not all the lemmas in these files are used, but are still present as they allow for efficient modification of proofs in case of either software changes (e.g. Jasmin or Easycrypt) and if the implementation changes.

Expand All @@ -30,8 +29,6 @@ Note that the dependency chain (where x <- y indicates that y depends on x) is:
Curve25519_Specs <- Curve25519_Operations <- Curve25519_Procedures <- Curve25519_PHoare
```

and all of these depend on the generic files mentioned above.


### Correctness proofs
The correctness proofs are similar for both implementations, so unless specified, all explanations apply to both implementations. Each lemma corresponds to a step in the X25519 implementation and are presented and proven in the same order. This order is:
Expand All @@ -54,8 +51,8 @@ These correctness proofs prove that all computations are correct with respect to
### Note on admitted lemmas
The following list of lemmas are left as `admit`, but are proven in Cryptoline (not available on this repository, yet):

1. `h_add_rrs_ref4` and `h_add_rrs_mulx` (correctness proof for the implementation of 4-limb addition implementation).
2. `h_sub_rrs_ref4` and `h_sub_rrs_mulx` (correctness proof for the implementation of 4-limb subtraction).
1. `h_add_rrs_ref4` (correctness proof for the implementation of 4-limb addition implementation).
2. `h_sub_rrs_ref4` (correctness proof for the implementation of 4-limb subtraction).
3. `h_mul_a24_ref4` and `h_mul_a24_mulx` (correctness proof for the implementation of 4-limb multiplication with a constant).
4. `h_mul_rss_ref4` and `h_mul_rsr_mulx` (correctness proof for the implementation of 4-limb multiplication).
5. `h_mul_pp_ref4` (correctness proof for the implementation of 4-limb multiplication).
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require import Bool List Int IntDiv CoreMap Real Ring StdOrder Zp_25519 Zp_limbs EClib.
require import Bool List Int IntDiv.
from Jasmin require import JModel.
require import Curve25519_Spec.
import Zp StdOrder.IntOrder Ring.IntID Array4 EClib.
require import Curve25519_Spec Zp_25519 Zp_limbs EClib.

(* sets last bit to 0 *)
import Zp StdOrder.IntOrder Ring.IntID.

require import Array4.

(* sets last bit to 0 *)
op last_bit_to_zero64 (x: Rep4) : Rep4 = let x = x.[3 <- x.[3].[63 <- false]] in x.

(* returns the first 2 elements of the input triple *)
Expand All @@ -23,7 +26,7 @@ lemma eq_reconstruct_select_triple (t : (('a * 'a) * ('a * 'a) * bool)) :
select_double_from_triple t = reconstruct_triple t.
proof.
rewrite /reconstruct_triple /select_double_from_triple.
by move => ? /#.
move => A. rewrite A => />.
qed.


Expand Down Expand Up @@ -190,16 +193,21 @@ op op_invert_p(z1 : zp) : zp =
let z_50_0 = op_invert_p_p2 z_5_0 in
let z_255_21 = op_invert_p_p3 z_50_0 z11 in
z_255_21 axiomatized by op_invert_pE.

(* lemma: invert is the same as z1^(p-2) from fermat's little theorem *)

lemma eq_op_invert_p (z1: zp) :
op_invert_p z1 = ZModpRing.exp z1 (p-2).
lemma eq_op_invert_p_part1 (z1: zp):
op_invert_p z1 = op_invert_p_p3 (op_invert_p_p2 ((ZModpRing.exp z1 31))) ((ZModpRing.exp z1 11)).
proof.
rewrite op_invert_pE.
rewrite /op_invert_p_p1 /= expE //= /op_invert_p_p3 /op_invert_p_p2 => />.
rewrite -!ZModpRing.exprS => />.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite /op_invert_p_p1 => />.
smt(ZModpRing.exprM ZModpRing.exprS ZModpRing.exprD_nneg).
qed.

lemma eq_op_invert_p_part2 (z1: zp):
op_invert_p_p3 (op_invert_p_p2 ((ZModpRing.exp z1 31))) ((ZModpRing.exp z1 11)) =
op_invert_p_p3 ((ZModpRing.exp z1 1125899906842623)) ((ZModpRing.exp z1 11)).
proof.
rewrite /op_invert_p_p2 => />.
rewrite -!ZModpRing.exprM => />.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite -!ZModpRing.exprM => />.
Expand All @@ -208,17 +216,32 @@ proof.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite -!ZModpRing.exprM => />.
rewrite -!ZModpRing.exprD_nneg => />.
qed.


lemma eq_op_invert_p_part3 (z1: zp):
op_invert_p_p3 ((ZModpRing.exp z1 1125899906842623)) ((ZModpRing.exp z1 11)) = (ZModpRing.exp z1
57896044618658097711785492504343953926634992332820282019728792003956564819947).
proof.
rewrite /op_invert_p_p3.
rewrite -!ZModpRing.exprM => />.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite -!ZModpRing.exprM => />.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite -!ZModpRing.exprM => />.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite -!ZModpRing.exprM => />.
rewrite -ZModpRing.exprD_nneg => />.
rewrite -ZModpRing.exprM => />.
rewrite -!ZModpRing.exprD_nneg => />.
rewrite pE => />.
qed.

lemma eq_op_invert_p (z1: zp) :
op_invert_p z1 = ZModpRing.exp z1 (p-2).
proof.
rewrite pE.
rewrite eq_op_invert_p_part1.
rewrite eq_op_invert_p_part2.
rewrite eq_op_invert_p_part3.
by congr.
qed.

(* now we define invert as one op and prove it equiv to exp z1 (p-2) *)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
require import Bool List Int IntDiv CoreMap Real Ring Zp_25519.
require import Int Real.
from Jasmin require import JModel.
require import Curve25519_Spec.
require import Curve25519_Operations.
require import Curve25519_Procedures.
require import Curve25519_Spec Curve25519_Procedures Curve25519_Operations Zp_25519.

import Zp Ring.IntID Curve25519_Spec Curve25519_Procedures Curve25519_Operations.
import Zp.

(** step 1 : decode_scalar_25519 **)
lemma ill_decode_scalar_25519 : islossless CurveProcedures.decode_scalar.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require import Bool List Int IntDiv CoreMap Real Zp_25519 Ring Distr StdOrder BitEncoding Zp_25519 StdBigop.
from Jasmin require import JModel JWord JModel_x86.
require import Curve25519_Spec.
require import Curve25519_Operations.
import Zp Zp_25519 Ring.IntID StdOrder.IntOrder BitEncoding.BS2Int StdBigop.Bigint.
require import Bool List Int IntDiv.
from Jasmin require import JModel.
require import Curve25519_Spec Curve25519_Operations Zp_25519.

import Zp Ring.IntID.

module CurveProcedures = {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require import List Int Int IntDiv CoreMap Real.
require import List Int.
from Jasmin require import JModel.
require import Zp_25519.

import Zp.

from Jasmin require import JModel.

op spec_decode_scalar_25519 (k:W256.t) =
let k = k.[0 <- false] in
Expand Down
5 changes: 1 addition & 4 deletions proof/crypto_scalarmult/curve25519/amd64/common/EClib.ec
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
require import List Int IntDiv CoreMap Ring StdOrder StdBigop BitEncoding.
import Ring.IntID IntOrder StdBigop.Bigint.BIA BitEncoding.BS2Int.

from Jasmin require import JModel JWord JWord_array.
require import List Int IntDiv.

lemma foldl_in_eq_r (f1 : 'a1 -> 'b -> 'a1)
(f2 : 'a2 -> 'b -> 'a2)
Expand Down
6 changes: 3 additions & 3 deletions proof/crypto_scalarmult/curve25519/amd64/common/Zp_25519.ec
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require import List Int IntDiv Ring CoreMap StdOrder.
require import EClib Array4 Array5 Array32.
require import Int.

from Jasmin require import JModel.
import Ring.IntID IntOrder.

import Ring.IntID.

(* modular operations modulo P *)
op p = 2^255 - 19 axiomatized by pE.
Expand Down
22 changes: 12 additions & 10 deletions proof/crypto_scalarmult/curve25519/amd64/common/Zp_limbs.ec
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
require import List Int IntDiv Ring CoreMap StdOrder.
require import Zp_25519 EClib Array4 Array32.
require import List Int IntDiv.

from Jasmin require import JModel JWord.
require import Zp_25519 EClib Array4.

import Zp EClib Ring.IntID Array4 Array32 IntOrder JWord.W8 JWord.W64.
import Zp Ring.IntID.

require import Array4.

op val_digits (base: int) (x: int list) =
foldr (fun w r => w + base * r) 0 x.


abbrev digits64 = List.map W64.to_uint.
abbrev digits8 = List.map W8.to_uint.
(*abbrev digits8 = List.map W8.to_uint.*)
abbrev val_limbs base l = val_digits base (digits64 l).

abbrev val_digits64 = val_digits (2^64).
abbrev val_limbs64 x = val_digits64 (digits64 x).

abbrev val_digits8 = val_digits (2^8).
abbrev val_limbs8 x = val_digits8 (digits8 x).

(*abbrev val_digits8 = val_digits (2^8).
abbrev val_limbs8 x = val_digits8 (digits8 x).*)
type Rep4 = W64.t Array4.t.
type Rep32 = W8.t Array32.t.

(*type Rep32 = W8.t Array32.t.*)
op valRep4 (x : Rep4) : int = val_limbs64 (Array4.to_list x) axiomatized by valRep4E.
op valRep4List (x : W64.t list) : int = val_limbs64 x axiomatized by valRep4ListE.
op inzpRep4 (x : Rep4) : zp = inzp (valRep4 x) axiomatized by inzpRep4E.
op inzpRep4List (x: W64.t list) : zp = inzp (valRep4List x) axiomatized by inzpRep4ListE.

op valRep32List (x : W8.t list) : int = val_limbs8 x axiomatized by valRep32ListE.
(*op valRep32List (x : W8.t list) : int = val_limbs8 x axiomatized by valRep32ListE.
op valRep32 (x : Rep32) : int = val_limbs8 (Array32.to_list x) axiomatized by valRep32E.
op inzpRep32 (x : Rep32) : zp = inzp (valRep32 x) axiomatized by inzpRep32E.
op inzpRep32List (x : W8.t list) : zp = inzp (valRep32List x) axiomatized by inzpRep32ListE.
*)

lemma to_uint_unpack4u64 w:
W256.to_uint w = val_digits W64.modulus (map W64.to_uint (W4u64.to_list w)).
Expand Down
Loading

0 comments on commit 1bc6d07

Please sign in to comment.