{-# LANGUAGE DeriveDataTypeable, GeneralizedNewtypeDeriving, DeriveGeneric #-}

-- |
-- Module      : Crypto.Saltine.Core.ScalarMult
-- Copyright   : (c) Joseph Abrahamson 2013
-- License     : MIT
--
-- Maintainer  : me@jspha.com
-- Stability   : experimental
-- Portability : non-portable
--
-- Scalar multiplication: "Crypto.Saltine.Core.ScalarMult"
--
-- The 'mult' function multiplies a group element by an integer of
-- length 'Bytes.multScalar'. It returns the resulting group element
-- of length 'Bytes.mult'. The 'multBase' function multiplies a
-- standard group element by an integer of length
-- 'Bytes.multScalar'. It returns the resulting group element of
-- length 'Bytes.mult'.
--
-- The correspondence between strings and group elements depends on
-- the primitive implemented by 'mult'. The correspondence is not
-- necessarily injective in either direction, but it is compatible
-- with scalar multiplication in the group. The correspondence does
-- not necessarily include all group elements, but it does include all
-- strings; i.e., every string represents at least one group element.
--
-- The correspondence between strings and integers also depends on the
-- primitive implemented by 'mult'. Every string represents at least
-- one integer.
--
-- 'mult' is designed to be strong as a component of various
-- well-known \"hashed Diffie–Hellman\" applications. In particular,
-- it is designed to make the \"computational Diffie–Hellman\" problem
-- (CDH) difficult with respect to the standard base. 'mult' is also
-- designed to make CDH difficult with respect to other nontrivial
-- bases. In particular, if a represented group element has small
-- order, then it is annihilated by all represented scalars. This
-- feature allows protocols to avoid validating membership in the
-- subgroup generated by the standard base.
--
-- NaCl does not make any promises regarding the \"decisional
-- Diffie–Hellman\" problem (DDH), the \"static Diffie–Hellman\"
-- problem (SDH), etc. Users are responsible for hashing group
-- elements.
--
-- 'mult' is the function @crypto_scalarmult_curve25519@ specified in
-- \"Cryptography in NaCl\", Sections 2, 3, and 4
-- (<http://nacl.cr.yp.to/valid.html>). This function is conjectured
-- to be strong. For background see Bernstein, \"Curve25519: new
-- Diffie-Hellman speed records,\" Lecture Notes in Computer Science
-- 3958 (2006), 207–228, <http://cr.yp.to/papers.html#curve25519>.
--
-- This is version 2010.08.30 of the scalarmult.html web page.
module Crypto.Saltine.Core.ScalarMult (
  Scalar, GroupElement,
  mult, multBase
  ) where

import Crypto.Saltine.Internal.Util
import Crypto.Saltine.Internal.ScalarMult
            ( c_scalarmult
            , c_scalarmult_base
            , GroupElement(..)
            , Scalar(..)
            )

import qualified Crypto.Saltine.Internal.ScalarMult as Bytes


mult :: Scalar -> GroupElement -> GroupElement
mult :: Scalar -> GroupElement -> GroupElement
mult (Sc ByteString
n) (GE ByteString
p) = ByteString -> GroupElement
GE (ByteString -> GroupElement)
-> ((Ptr CChar -> IO CInt) -> ByteString)
-> (Ptr CChar -> IO CInt)
-> GroupElement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CInt, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((CInt, ByteString) -> ByteString)
-> ((Ptr CChar -> IO CInt) -> (CInt, ByteString))
-> (Ptr CChar -> IO CInt)
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
Bytes.scalarmult_bytes ((Ptr CChar -> IO CInt) -> GroupElement)
-> (Ptr CChar -> IO CInt) -> GroupElement
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
pq ->
  [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
n, ByteString
p] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \[(Ptr CChar
pn, Int
_), (Ptr CChar
pp, Int
_)] ->
    Ptr CChar -> Ptr CChar -> Ptr CChar -> IO CInt
c_scalarmult Ptr CChar
pq Ptr CChar
pn Ptr CChar
pp

multBase :: Scalar -> GroupElement
multBase :: Scalar -> GroupElement
multBase (Sc ByteString
n) = ByteString -> GroupElement
GE (ByteString -> GroupElement)
-> ((Ptr CChar -> IO CInt) -> ByteString)
-> (Ptr CChar -> IO CInt)
-> GroupElement
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CInt, ByteString) -> ByteString
forall a b. (a, b) -> b
snd ((CInt, ByteString) -> ByteString)
-> ((Ptr CChar -> IO CInt) -> (CInt, ByteString))
-> (Ptr CChar -> IO CInt)
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> (Ptr CChar -> IO CInt) -> (CInt, ByteString)
forall b. Int -> (Ptr CChar -> IO b) -> (b, ByteString)
buildUnsafeByteString Int
Bytes.scalarmult_bytes ((Ptr CChar -> IO CInt) -> GroupElement)
-> (Ptr CChar -> IO CInt) -> GroupElement
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
pq ->
  [ByteString] -> ([CStringLen] -> IO CInt) -> IO CInt
forall b. [ByteString] -> ([CStringLen] -> IO b) -> IO b
constByteStrings [ByteString
n] (([CStringLen] -> IO CInt) -> IO CInt)
-> ([CStringLen] -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \[(Ptr CChar
pn, Int
_)] ->
    Ptr CChar -> Ptr CChar -> IO CInt
c_scalarmult_base Ptr CChar
pq Ptr CChar
pn