Revision 8a7e1b7f7f7dda7d9ac75c7adbb915b5c7db208f authored by Dzomo the everest Yak on 09 January 2020, 09:25:31 UTC, committed by Dzomo the everest Yak on 09 January 2020, 09:25:31 UTC
1 parent 9cd0bde
Raw File
Spec.Curve448.fst
module Spec.Curve448

open FStar.Mul
open Lib.IntTypes
open Lib.RawIntTypes
open Lib.Sequence
open Lib.ByteSequence
open Lib.NatMod

open Spec.Curve448.Lemmas

#reset-options "--initial_fuel 0 --max_fuel 0 --z3rlimit 20"

(* Field types and parameters *)
let prime = pow2 448 - pow2 224 - 1

unfold type elem = nat_mod prime
let to_elem x = x `modulo` prime
let from_elem (x:elem) = nat_mod_v x
let zero : elem = to_elem 0
let one  : elem = to_elem 1

(* Type aliases *)
type scalar = lbytes 56
type serialized_point = lbytes 56
type proj_point = | Proj: x:elem -> z:elem -> proj_point

let decodeScalar (k:scalar) =
  let k : scalar = k.[0] <- (k.[0] &. u8 252) in
  let k : scalar = k.[55] <- (k.[55] |. u8 128) in k

let decodePoint (u:serialized_point) =
  (nat_from_bytes_le u % pow2 448) % prime

let add_and_double qx nq nqp1 =
  let x_1 = qx in
  let x_2, z_2 = nq.x, nq.z in
  let x_3, z_3 = nqp1.x, nqp1.z in
  let a  = x_2 +% z_2 in
  let aa = a **% 2 in
  let b  = x_2 -% z_2 in
  let bb = b **% 2 in
  let e = aa -% bb in
  let c = x_3 +% z_3 in
  let d = x_3 -% z_3 in
  let da = d *% a in
  let cb = c *% b in
  let x_3 = (da +% cb) **% 2 in
  let z_3 = x_1 *% ((da -% cb) **% 2) in
  let x_2 = aa *% bb in
  let z_2 = e *% (aa +% (39081 *% e)) in
  Proj x_2 z_2, Proj x_3 z_3

let ith_bit (k:scalar) (i:nat{i < 448}) : uint8 =
  let (&.) = logand #U8 in
  let q = i / 8 in let r = size (i % 8) in
  (k.[q] >>. r) &. u8 1

let rec montgomery_ladder_ (init:elem) x xp1 (k:scalar) (ctr:nat{ctr<=448})
  : Tot proj_point (decreases ctr) =
  if ctr = 0 then x
  else (
    let ctr' = ctr - 1 in
    let (x', xp1') =
      if uint_to_nat #U8 (ith_bit k ctr') = 1 then (
        let nqp2, nqp1 = add_and_double init xp1 x in
        nqp1, nqp2
      ) else add_and_double init x xp1 in
    montgomery_ladder_ init x' xp1' k ctr'
  )

let montgomery_ladder (init:elem) (k:scalar) : Tot proj_point =
  montgomery_ladder_ init (Proj one zero) (Proj init one) k 448

let encodePoint (p:proj_point) : Tot serialized_point =
  assert_norm (prime - 2 > 0);
  let p = p.x *% (p.z **% (prime - 2)) in
  nat_to_bytes_le 56 p

let scalarmult (k:scalar) (u:serialized_point) : Tot serialized_point =
  let k = decodeScalar k in
  let u = decodePoint u in
  let res = montgomery_ladder u k in
  encodePoint res

val secret_to_public: lbytes 56 -> Tot (lbytes 56)
let secret_to_public kpriv =
  let basepoint_zeros = create 56 (u8 0) in
  let basepoint = upd basepoint_zeros (56 - 1) (u8 0x09) in
  scalarmult kpriv basepoint
back to top