module Crypto.OpenSSL.BN where
import Crypto.OpenSSL.BN.Foreign
import Crypto.OpenSSL.Misc
import Foreign.Ptr
import Foreign.ForeignPtr
import Data.Bits
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B
withIntegerAsBN :: Integer -> (Ptr BIGNUM -> IO a) -> IO a
withIntegerAsBN i f = do
bn <- withForeignPtr fptr $ \bsPtr ->
ssl_bn_bin2 (castPtr (bsPtr `plusPtr` o)) (fromIntegral len) nullPtr
foreignBn <- newForeignPtr ssl_bn_free bn
withForeignPtr foreignBn f
where (fptr, o, len) = B.toForeignPtr bs
bs = B.reverse $ B.unfoldr fdivMod256 i
fdivMod256 0 = Nothing
fdivMod256 n = Just (fromIntegral a,b) where (b,a) = divMod256 n
divMod256 :: Integer -> (Integer, Integer)
divMod256 n = (n `shiftR` 8, n .&. 0xff)
bnToInt :: Ptr BIGNUM -> IO Integer
bnToInt bn = do
bytes <- ssl_bn_num_bytes bn
bs <- B.create (fromIntegral bytes) $ \bufPtr ->
check $ ssl_bn_2bin bn (castPtr bufPtr)
return $ os2ip bs
where os2ip = B.foldl' (\a b -> (256 * a) .|. (fromIntegral b)) 0
withBnCtxNew :: (Ptr BN_CTX -> IO a) -> IO a
withBnCtxNew f = do
fptr <- ssl_bn_ctx_new >>= newForeignPtr ssl_bn_ctx_free
withForeignPtr fptr f
withBnNew :: (Ptr BIGNUM -> IO a) -> IO a
withBnNew f = do
fptr <- ssl_bn_new >>= newForeignPtr ssl_bn_free
withForeignPtr fptr f