packages feed

adb (empty) → 0.1.0.0

raw patch · 21 files changed

+3452/−0 lines, 21 filesdep +basedep +bytestringdep +cerealsetup-changed

Dependencies added: base, bytestring, cereal, containers, mtl, network

Files

+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Stephen Blackheath++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Stephen Blackheath nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Network/ADB/Client.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, OverloadedStrings,+        ForeignFunctionInterface, EmptyDataDecls #-}+module Network.ADB.Client (+        Session,+        withClientSession,+        withConnect,+        module Network.ADB.Transport+    ) where++import Network.ADB.Common+import Network.ADB.Transport++import Control.Applicative+import Control.Concurrent+import Control.Concurrent.MVar+import Control.Exception+import Control.Monad.Error+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as C+import qualified Data.ByteString.Unsafe as B+import qualified Data.ByteString.Internal as BI+import Data.Map (Map)+import qualified Data.Map as M+import Data.Monoid+import Foreign+import Foreign.C+import Prelude hiding (read, catch)+++withClientSession :: Transport (ErrorT TransportError IO)+                  -> (Session (ErrorT TransportError IO) -> ErrorT TransportError IO a)+                  -> ErrorT TransportError IO a+withClientSession tra code = do+    negotiate tra+    withSession tra code++-- | Performs negotiation on a packetTransport+negotiate :: (MonadError TransportError m, Applicative m, MonadIO m) =>+             Transport m -> m ()+negotiate tra = do+    write tra $ formatPacket $ Packet SYNC 1 0 B.empty+    write tra $ formatPacket $ Packet CNXN a_VERSION mAX_PAYLOAD "host::\0"+    auth <- liftIO adbAuthNew+    awaitCNXN auth+  where+    awaitCNXN auth = do+        pkt <- readPacket tra+        case pktCommand pkt of+            CNXN -> return ()+            AUTH -> do+                --liftIO $ putStrLn $ "RECV "++show pkt+                mReply <- liftIO $ adbAuth auth pkt+                case mReply of+                    Just reply -> do+                        --liftIO $ putStrLn $ "SEND "++show reply+                        write tra $ formatPacket reply+                    Nothing -> return ()+                awaitCNXN auth+            _    -> awaitCNXN auth++data ADBAuth_Struct+type ADBAuth = Ptr ADBAuth_Struct++foreign import ccall unsafe "adb_auth_new" adbAuthNew+    :: IO ADBAuth++{- Handle adb's AUTH command. If it wants to reply, it will return+   with 1 and pkt will contain the packet to be sent. -}+foreign import ccall unsafe "adb_auth" _adb_auth+    :: ADBAuth -> Ptr Word8 -> IO CInt++adbAuth :: ADBAuth -> Packet -> IO (Maybe Packet)+adbAuth auth pkt = do+    pkt_c <- B.unsafeUseAsCStringLen (formatPacket pkt) $ \(pkt_c, len) -> do+        p <- mallocBytes (4096 + 24)+        BI.memcpy p (castPtr pkt_c) len+        return p+    ret <-_adb_auth auth pkt_c+    if ret /= 0+        then do+            outLen <- peekElemOff (castPtr pkt_c :: Ptr Word32) 3+            let olen = fromIntegral outLen + 24+            bs' <- BI.create olen $ \p -> BI.memcpy p pkt_c olen+            free pkt_c+            case parsePacket bs' of+                Left err -> fail $ "bad packet from adbAuth: "++err+                Right opkt -> return $ Just opkt+        else do+            free pkt_c+            return Nothing++withConnect :: Session (ErrorT TransportError IO) +            -> C.ByteString+            -> (Transport (ErrorT TransportError IO) -> ErrorT TransportError IO a)+            -> ErrorT TransportError IO a+withConnect session@(Session allocLocalID writePkt readPkt) uri code = do+    localID <- liftIO allocLocalID+    writePkt $ Packet OPEN localID 0 (uri <> B.singleton 0)+    let awaitResult = do+            pkt <- readPkt+            if pktCommand pkt == OKAY && pktArg1 pkt == localID+                then return $ Just $ pktArg0 pkt+                else if pktCommand pkt == CLSE && pktArg1 pkt == localID+                    then return $ Nothing+                    else awaitResult+    mTransportID <- awaitResult++    case mTransportID of+        Nothing -> do+            throwError $ ConnectionFailure "no response"+        Just remoteID -> do+            withConversation session localID remoteID code+
+ Network/ADB/Common.hs view
@@ -0,0 +1,224 @@+{-# LANGUAGE FlexibleContexts #-}+module Network.ADB.Common where++import Network.ADB.Transport++import Control.Applicative+import Control.Concurrent+import Control.Exception+import Control.Monad.Error+import Data.Bits+import Data.ByteString (ByteString)+import qualified Data.ByteString as B+import Data.List+import Data.Map (Map)+import qualified Data.Map as M+import Data.Sequence (Seq, (<|), (|>))+import qualified Data.Sequence as Seq+import Data.Serialize+import Data.Word+import Prelude hiding (read)+++mAX_PAYLOAD :: Word32+mAX_PAYLOAD = 4096++a_VERSION :: Word32+a_VERSION = 0x01000000        -- ADB protocol version++data Command = SYNC | CNXN | AUTH | OPEN | OKAY | CLSE | WRTE+    deriving (Eq, Ord, Show)++fromCommand :: Command -> Word32+fromCommand SYNC = 0x434e5953+fromCommand CNXN = 0x4e584e43+fromCommand AUTH = 0x48545541+fromCommand OPEN = 0x4e45504f+fromCommand OKAY = 0x59414b4f+fromCommand CLSE = 0x45534c43+fromCommand WRTE = 0x45545257++toCommand :: Word32 -> Maybe Command+toCommand 0x434e5953 = Just SYNC+toCommand 0x4e584e43 = Just CNXN+toCommand 0x48545541 = Just AUTH+toCommand 0x4e45504f = Just OPEN +toCommand 0x59414b4f = Just OKAY +toCommand 0x45534c43 = Just CLSE +toCommand 0x45545257 = Just WRTE+toCommand _          = Nothing++data Packet = Packet {+        pktCommand :: Command,+        pktArg0    :: Word32,+        pktArg1    :: Word32,+        pktPayload :: ByteString+    }+    deriving Show++formatPacket :: Packet -> ByteString+formatPacket pkt = runPut $ do+    let cmd = fromCommand . pktCommand $ pkt+    putWord32le $ cmd+    putWord32le . pktArg0 $ pkt+    putWord32le . pktArg1 $ pkt+    putWord32le . fromIntegral . B.length . pktPayload $ pkt+    putWord32le . foldl' (+) 0 . map fromIntegral . B.unpack . pktPayload $ pkt+    putWord32le . complement $ cmd+    putByteString . pktPayload $ pkt++parsePacket :: ByteString -> Either String Packet+parsePacket = runGet $ do+    cmdNo <- getWord32le+    case toCommand cmdNo of+        Just cmd -> do+            arg0 <- getWord32le+            arg1 <- getWord32le+            len <- getWord32le+            _ <- getWord32le+            _ <- getWord32le+            payload <- getByteString (fromIntegral len)+            return $ Packet cmd arg0 arg1 payload+        Nothing  -> fail $ "bad command"++readPacket :: (MonadError TransportError m, Functor m, Applicative m) =>+              Transport m -> m Packet+readPacket rem = do+    Right [cmdNo, arg0, arg1, len, chk, magic] <- runGet (sequence $ replicate 6 getWord32le) <$> readFully rem (6*4)+    when (cmdNo /= complement magic) $ throwError IllegalData+    cmd <- case toCommand cmdNo of+        Just cmd -> return cmd+        Nothing  -> throwError IllegalData+    when (len > fromIntegral mAX_PAYLOAD) $ throwError IllegalData+    payload <- if len == 0 then pure B.empty else readFully rem (fromIntegral len)+    return $ Packet cmd arg0 arg1 payload++data Session m = Session (IO Word32) (Packet -> m ()) (m Packet)++withSession :: Transport (ErrorT TransportError IO)+            -> (Session (ErrorT TransportError IO) -> ErrorT TransportError IO a)+            -> ErrorT TransportError IO a+withSession tra code = do+    nextLocalIDRef <- liftIO $ newMVar 0+    let doAlloc 0      = doAlloc 1+        doAlloc nextID = return $ (nextID+1, nextID)+        allocLocalID = modifyMVar nextLocalIDRef doAlloc++    (chansVar, ch) <- liftIO $ do+        me <- myThreadId+        ch <- newChan+        chansVar <- newMVar $ M.insert me ch M.empty+        return (chansVar, ch)+    let readPkt = do+            ee <- liftIO $ do+                ch <- modifyMVar chansVar $ \chans -> do+                    me <- myThreadId+                    case me `M.lookup` chans of+                        Just ch -> return (chans, ch)+                        Nothing -> do+                            ch' <- dupChan ch+                            return (M.insert me ch' chans, ch')+                readChan ch+            case ee of+                Left err -> throwError err+                Right pkt -> return pkt++    readThr <- liftIO $ forkIO $ do+        forever $ do+            epkt <- runErrorT $ readPacket tra+            case epkt of+                Left err -> writeChan ch (Left err)+                Right pkt -> writeChan ch (Right pkt)++    ee <- liftIO $ runErrorT (code (Session allocLocalID (write tra . formatPacket) readPkt))+      `finally` killThread readThr+    case ee of+        Left err -> throwError err+        Right a  -> return a++withConversation :: Session (ErrorT TransportError IO)+                                  -> Word32+                                  -> Word32+                                  -> (Transport (ErrorT TransportError IO) -> ErrorT TransportError IO a)+                                  -> ErrorT TransportError IO a+withConversation session@(Session allocLocalID writePkt readPkt0) localID remoteID code = do+    queueVar <- liftIO $ newMVar Seq.empty+    (chansVar, ch) <- liftIO $ do+        me <- myThreadId+        ch <- newChan+        chansVar <- newMVar $ M.insert me ch M.empty+        return (chansVar, ch)+    let readPkt = do+            ee <- liftIO $ do+                ch <- modifyMVar chansVar $ \chans -> do+                    me <- myThreadId+                    case me `M.lookup` chans of+                        Just ch -> return (chans, ch)+                        Nothing -> do+                            ch' <- dupChan ch+                            return (M.insert me ch' chans, ch')+                readChan ch+            case ee of+                Left err -> throwError err+                Right pkt -> return pkt++    readThr <- liftIO $ forkIO $ do+        forever $ do+            epkt <- runErrorT $ readPkt0+            case epkt of+                Left err -> writeChan ch (Left err)+                Right pkt -> do+                    case pktCommand pkt of+                        WRTE | pktArg1 pkt == localID -> do+                            modifyMVar_ queueVar $ return . (|> pktPayload pkt)+                            runErrorT $ writePkt $ Packet OKAY localID remoteID B.empty+                            writeChan ch (Right pkt)+                        _                             -> writeChan ch (Right pkt)++    let traNew = Transport {+            write =+                let writeLoop bs = case bs of+                        bs | B.null bs -> return ()+                        bs -> do+                            let (now, next) = B.splitAt (fromIntegral mAX_PAYLOAD) bs+                            writePkt $ Packet WRTE localID remoteID now+                            let awaitResult = do+                                    pkt <- readPkt+                                    case pktCommand pkt of+                                        CLSE | pktArg1 pkt == localID -> throwError ClosedByPeer+                                        OKAY | pktArg0 pkt == remoteID -> writeLoop next+                                        _ -> awaitResult+                            awaitResult+                in  \bs -> writeLoop bs,+            read = \n -> do+                let readLoop = do+                        q <- liftIO $ readMVar queueVar+                        if Seq.length q == 0 then do+                                pkt <- readPkt+                                case pktCommand pkt of+                                    CLSE | pktArg1 pkt == localID -> throwError ClosedByPeer+                                    _ -> readLoop+                            else do+                                let hd = q `Seq.index` 0+                                if B.length hd > n then do+                                    let (mine, notMine) = B.splitAt n hd+                                    liftIO $ modifyMVar_ queueVar $ return . (\q -> notMine <| Seq.drop 1 q)+                                    return mine+                                  else do+                                    liftIO $ modifyMVar_ queueVar $ return . (Seq.drop 1)+                                    return hd+                readLoop,+            close = do+                writePkt $ Packet CLSE localID remoteID B.empty+                let awaitResult = do+                        pkt <- readPkt+                        case pktCommand pkt of+                            CLSE | pktArg1 pkt == localID -> throwError ClosedByPeer+                            _ -> awaitResult+                awaitResult+          }+    ea <- liftIO $ runErrorT (code traNew) `finally` killThread readThr+    case ea of+        Left err -> throwError err+        Right a  -> return a+
+ Network/ADB/Server.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, OverloadedStrings,+        ForeignFunctionInterface, EmptyDataDecls #-}+module Network.ADB.Server (+        Session,+        withServerSession,+        withAccept,+        module Network.ADB.Transport+    ) where++import Control.Applicative+import Control.Concurrent+import Control.Monad.Error+import Data.ByteString.Char8 (ByteString)+import qualified Data.ByteString.Char8 as C+import Data.Monoid+import Network.ADB.Common+import Network.ADB.Transport+++withServerSession :: Transport (ErrorT TransportError IO)+                  -> ByteString+                  -> (Session (ErrorT TransportError IO) -> ErrorT TransportError IO a)+                  -> ErrorT TransportError IO a+withServerSession tra descriptor code = do+    negotiate descriptor tra+    withSession tra code++-- | Performs negotiation on a packetTransport+negotiate :: (MonadError TransportError m, Applicative m, MonadIO m) =>+             ByteString+          -> Transport m -> m ()+negotiate descriptor tra = do+        pkt <- readPacket tra+        case pkt of+            Packet CNXN _ _ _ -> write tra $ formatPacket $ Packet CNXN a_VERSION mAX_PAYLOAD (descriptor <> "\0")+            _                 -> negotiate descriptor tra++-- | Loop forever, accepting incoming connections. The specified function returns some+-- code to spawn on a new thread if we should accept a connection on the specified URI.+withAccept :: Session (ErrorT TransportError IO) +           -> (C.ByteString -> Maybe (Transport (ErrorT TransportError IO) -> ErrorT TransportError IO ()))+           -> ErrorT TransportError IO ()+withAccept session@(Session allocLocalID writePkt readPkt) qCode = forever $ do+    pkt <- readPkt+    case pkt of+        Packet OPEN remoteID 0 uri ->+            if "\0" `C.isSuffixOf` uri+                then case qCode (C.take (C.length uri - 1) uri) of+                         Just code -> do+                             _ <- liftIO $ forkIO $ do+                                 localID <- allocLocalID+                                 _ <- runErrorT $ do+                                     writePkt $ Packet OKAY localID remoteID C.empty+                                     withConversation session localID remoteID code+                                 return ()+                             return ()+                         Nothing -> writePkt $ Packet CLSE 0 remoteID C.empty+                else writePkt $ Packet CLSE 0 remoteID C.empty+        _ -> return ()+
+ Network/ADB/Socket.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE ScopedTypeVariables #-}+module Network.ADB.Socket where++import Control.Exception+import Control.Monad.Error+import Network.ADB.Transport+import Network.Socket (Socket, sClose)+import Network.Socket.ByteString+import System.IO.Error+import Prelude hiding (read)+++socketTransport :: Socket -> Transport (ErrorT TransportError IO)+socketTransport s = Transport {+        write = \bs -> do+            --liftIO $ putStrLn $ hexdump 0 (C.unpack bs)   -- ###+            ee <- liftIO . try $ sendAll s bs+            case ee of+                Left (exc :: IOError) -> throwError ClosedByPeer+                Right () -> return (),+        read = \n -> do+            ee <- liftIO . try $ recv s n+            case ee of+                Left (exc :: IOError) -> throwError ClosedByPeer+                Right blk -> do+                    --liftIO $ putStrLn $ hexdump 0 (C.unpack blk)   -- ###+                    return blk,+        close = do+            ee <- liftIO . try $ sClose s+            case ee of+                Left (exc :: IOError) -> throwError ClosedByPeer+                Right blk -> return blk+    }+
+ Network/ADB/Transport.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE ScopedTypeVariables #-}
+module Network.ADB.Transport where
+
+
+import Control.Exception
+import Control.Monad.Error
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as C
+import Data.Monoid
+import Network.Socket.ByteString
+import System.IO.Error (IOError(..))
+import Prelude hiding (read)
+
+
+-- | \'m\' is the monad to to run it in, \'h\' is the heuristic value which, where
+-- \'e\' is 'ByteString', is the number of bytes to read.  \'e\' is the stream
+-- element type.
+data Transport m = Transport {
+        write :: ByteString -> m (),  -- ^ Write an item.
+        read  :: Int -> m ByteString, -- ^ Read an item with 'h' being the heuristic to say what it
+                                      -- is we want to read.
+        close :: m ()
+    }
+
+data TransportError = ADBFailure String
+                    | SocketFailure IOError
+                    | ConnectionFailure ByteString
+                    | ClosedByPeer
+                    | IllegalData
+    deriving Show
+
+instance Error TransportError where
+    noMsg = IllegalData
+    strMsg _ = IllegalData
+
+-- | Block until the specified number of bytes has been read.
+readFully :: Monad m => Transport m -> Int -> m ByteString
+readFully rem n = doRecv C.empty
+  where
+    doRecv sofar | C.length sofar == n = return sofar
+    doRecv sofar = do
+        blk <- read rem (n - C.length sofar)
+        doRecv (sofar `mappend` blk)
+
+ Network/ADB/adb.h view
@@ -0,0 +1,43 @@+#ifndef _ADB_PACKET_H_+#define _ADB_PACKET_H_++#define A_VERSION 0x01000000        // ADB protocol version++#define ADB_CLASS              0xff+#define ADB_SUBCLASS           0x42+#define ADB_PROTOCOL           0x1++#define A_SYNC 0x434e5953+#define A_CNXN 0x4e584e43+#define A_AUTH 0x48545541+#define A_OPEN 0x4e45504f+#define A_OKAY 0x59414b4f+#define A_CLSE 0x45534c43+#define A_WRTE 0x45545257++typedef struct amessage {+    unsigned command;       /* command identifier constant      */+    unsigned arg0;          /* first argument                   */+    unsigned arg1;          /* second argument                  */+    unsigned data_length;   /* length of payload (0 is allowed) */+    unsigned data_check;    /* checksum of data payload         */+    unsigned magic;         /* command ^ 0xffffffff             */+} amessage;++#define MAX_PAYLOAD 4096++typedef struct apacket+{+    amessage msg;+    unsigned char data[MAX_PAYLOAD];+} apacket;++/* AUTH packets first argument */+/* Request */+#define ADB_AUTH_TOKEN         1+/* Response */+#define ADB_AUTH_SIGNATURE     2+#define ADB_AUTH_RSAPUBLICKEY  3++#endif+
+ Network/ADB/adb_auth.c view
@@ -0,0 +1,133 @@+#define _HASKELL_HOOKS_++#if defined(TEXT_BASE)+#define U_BOOT+#endif++#if !defined(U_BOOT)+#include <stdio.h>+#include <string.h>+#include <stdlib.h>+#else+#include <common.h>+#include <malloc.h>+#endif++#include "adb_auth.h"+++#define RSANUMBYTES 256           /* 2048 bit key length */+#define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t))++typedef struct RSAPublicKey {+    int len;                  /* Length of n[] in number of uint32_t */+    uint32_t n0inv;           /* -1 / n[0] mod 2^32 */+    uint32_t n[RSANUMWORDS];  /* modulus as little endian array */+    uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */+    int exponent;             /* 3 or 65537 */+} RSAPublicKey;++#include "adb_auth_private_key.h"++void adb_auth_init(ADBAuth* auth)+{+    auth->ctx = NULL;+    RSA_priv_key_new(&auth->ctx,+        public_n, public_n_length,+        public_e, public_e_length,+        private_d, private_d_length);+    auth->key_try_ix = 0;+}++#if defined(_HASKELL_HOOKS_)+ADBAuth* adb_auth_new(void)+{+    ADBAuth* auth = (ADBAuth*)malloc(sizeof(ADBAuth));+    adb_auth_init(auth);+    return auth;+}+#endif++void adb_auth_free(ADBAuth* auth)+{+    RSA_free(auth->ctx);+}++static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',+                                'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',+                                'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',+                                'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',+                                'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',+                                'o', 'p', 'q', 'r', 's', 't', 'u', 'v',+                                'w', 'x', 'y', 'z', '0', '1', '2', '3',+                                '4', '5', '6', '7', '8', '9', '+', '/'};+static int mod_table[] = {0, 2, 1};++void base64_encode(const unsigned char *data,+                    size_t input_length,+                    char* encoded_data) {++    int output_length = 4 * ((input_length + 2) / 3);+    int i, j;++    for (i = 0, j = 0; i < input_length;) {++        uint32_t octet_a = i < input_length ? data[i++] : 0;+        uint32_t octet_b = i < input_length ? data[i++] : 0;+        uint32_t octet_c = i < input_length ? data[i++] : 0;++        uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;++        encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F];+        encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F];+        encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F];+        encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F];+    }++    for (i = 0; i < mod_table[input_length % 3]; i++)+        encoded_data[output_length - 1 - i] = '=';+    encoded_data[output_length] = 0;+}++static const uint8_t prefix[] = {+  0x30,0x21,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14+};++/* Handle adb's AUTH command. If it wants to reply, it will return+ * with 1 and pkt will contain the packet to be sent. */+int adb_auth(ADBAuth* auth, apacket* pkt)+{+    switch (pkt->msg.arg0) {+    case ADB_AUTH_TOKEN:+        if (auth->key_try_ix == 0) {+            uint8_t digest[4096];+            uint8_t answer[MAX_PAYLOAD];+            int outLen;+            memcpy(digest, prefix, sizeof(prefix));+            memcpy(digest+sizeof(prefix), pkt->data, pkt->msg.data_length);+            outLen = RSA_encrypt(auth->ctx, digest, sizeof(prefix)+pkt->msg.data_length, answer, 1);+            memcpy(pkt->data, answer, outLen);+            pkt->msg.command = A_AUTH;+            pkt->msg.arg0 = ADB_AUTH_SIGNATURE;+            pkt->msg.arg1 = 0;+            pkt->msg.data_length = (unsigned) outLen;+            auth->key_try_ix = 1;+            return 1;+        }+        else {+            base64_encode((const unsigned char *) &public_key, sizeof(public_key), (char*)pkt->data);+            pkt->msg.command = A_AUTH;+            pkt->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;+            pkt->msg.arg1 = 0;+            pkt->msg.data_length = (unsigned) strlen((const char*)pkt->data) + 1;+            return 1;+        }+    case ADB_AUTH_SIGNATURE:+        return 0;+    case ADB_AUTH_RSAPUBLICKEY:+        return 0;+    default:+        return 0;+    }+}+
+ Network/ADB/adb_auth.h view
@@ -0,0 +1,26 @@+#ifndef _ADB_AUTH_H_+#define _ADB_AUTH_H_++#include "adb.h"+#if !defined(U_BOOT)+#include <stdint.h>+#endif+#include "crypto.h"++typedef struct {+    RSA_CTX* ctx;+    int key_try_ix;+} ADBAuth;++void adb_auth_init(ADBAuth* auth);+#if defined(_HASKELL_HOOKS_)+ADBAuth* adb_auth_new(void);+#endif+void adb_auth_free(ADBAuth* auth);++/* Handle adb's AUTH command. If it wants to reply, it will return+ * with 1 and pkt will contain the packet to be sent. */+int adb_auth(ADBAuth* auth, apacket* pkt);++#endif+
+ Network/ADB/adb_auth_private_key.h view
@@ -0,0 +1,22 @@+const uint8_t public_n[] = {+0xde,0xcc,0xf3,0x1,0xaf,0xa,0xf3,0xd,0xcf,0x3f,0x42,0x9d,0x19,0x1f,0x11,0x2,0xd1,0x7f,0xfe,0x14,0x42,0xc0,0x5c,0x4a,0x3,0x91,0x91,0xe5,0xee,0x18,0x93,0x12,0xd8,0xf2,0xce,0x5d,0x10,0x5d,0x41,0xf6,0xda,0x26,0x6a,0x6a,0x86,0x94,0x7e,0x12,0x25,0x10,0x86,0x89,0x59,0x5a,0x64,0x5,0x32,0x99,0x8a,0xed,0x57,0xf3,0x73,0x6f,0xdf,0xd1,0x5a,0x54,0x8a,0xd6,0xf1,0xcd,0xbd,0x4,0xbb,0xdf,0x37,0x4d,0x67,0xf3,0xdd,0xbb,0x54,0xe3,0x6a,0x81,0xcc,0x3a,0x46,0x8c,0x67,0x77,0x74,0x2c,0xab,0x88,0x32,0xb6,0x34,0x30,0x5f,0x73,0x8b,0x49,0x1e,0x72,0x2b,0x76,0xb0,0x29,0x2e,0xa4,0x99,0x50,0xd7,0x71,0xcc,0x4b,0x32,0x9a,0x92,0x65,0x68,0x6e,0xe6,0x62,0xcf,0x40,0x29,0x88,0x1c,0x91,0x29,0x3,0xe5,0x8f,0xe5,0x21,0xd,0x19,0xe3,0x78,0x53,0xb0,0x2e,0x14,0xe4,0xb0,0x6a,0x11,0xc9,0xa7,0x2f,0xe4,0x57,0xbf,0xa7,0xaf,0xe3,0xf4,0x1e,0xe8,0x6a,0x20,0xfd,0x2e,0xdf,0x85,0xe7,0x79,0x21,0xd0,0x6a,0x19,0xca,0xd3,0xd3,0x56,0x9e,0x62,0x54,0x0,0xff,0x6c,0x36,0xf9,0x26,0x51,0x14,0x3f,0xa8,0xcb,0xe7,0x32,0x67,0x9f,0xd6,0x24,0x2e,0x13,0x73,0x6c,0xb6,0xeb,0x1,0x5,0xe5,0xd9,0xd8,0x21,0xc6,0x26,0x4b,0x36,0xcf,0xf0,0x21,0xe5,0xc6,0xa0,0xe0,0x11,0x68,0x69,0x41,0xe9,0x72,0x5d,0x1e,0xc6,0xf5,0x6e,0x49,0x9b,0x9d,0x70,0xc4,0xf4,0x25,0x1b,0xfd,0xa1,0x2a,0x16,0x1,0xaa,0x3f,0x9a,0xa3,0xdb,0x2b,0xf0,0xea,0x2c,0xdc,0x87+};+const int public_n_length = 256;++const uint8_t public_e[] = {+0x1,0x0,0x1+};+const int public_e_length = 3;++const uint8_t private_d[] = {+0x18,0x38,0x7,0x22,0x63,0xb8,0xb8,0xfb,0x3,0x50,0x49,0x19,0x72,0xa5,0xa1,0xdf,0xc0,0x8e,0x3d,0x3c,0x4e,0x95,0x42,0x72,0xf9,0x38,0x55,0xb7,0xbc,0xce,0x7,0xe,0xc1,0x6e,0x83,0x68,0x32,0x63,0x30,0xcc,0x78,0xa2,0x3c,0x67,0x20,0x1,0xfc,0x42,0x54,0xad,0x1b,0x32,0xca,0xf7,0xbc,0x6f,0xa4,0x34,0x74,0x99,0xa0,0x39,0xe2,0x8e,0x82,0xb1,0xeb,0x33,0xcd,0x73,0xd8,0xd,0x19,0x42,0xee,0x79,0x31,0x35,0xc4,0xdb,0x9,0x7b,0x57,0x9a,0xf0,0xf4,0xf3,0x12,0x52,0xa0,0xe8,0x8e,0x5f,0x9e,0x8b,0x76,0xde,0xac,0x57,0xb7,0xfa,0x68,0x40,0xf7,0xcd,0xcb,0x73,0x56,0xf,0x88,0x2a,0x7d,0xd1,0xfc,0xab,0xae,0xbf,0x1a,0x5d,0x81,0xd7,0xf0,0x16,0xe,0x18,0x15,0x1d,0x9a,0x13,0xeb,0x22,0xed,0x67,0x9e,0xb3,0x7f,0x1d,0xba,0x9f,0xcd,0x7b,0xea,0xa5,0x2e,0xa3,0xf2,0x81,0xe7,0x98,0xd9,0x96,0x5f,0xd1,0xc0,0xdd,0xa9,0xcc,0x8d,0x41,0xf8,0xde,0x56,0xa0,0x81,0xd7,0xf4,0x6d,0x41,0x1e,0xce,0x28,0xc7,0xb4,0x9f,0xc5,0x4,0x39,0x53,0x48,0x61,0xe4,0xbe,0x6b,0x51,0x9b,0x75,0x40,0xf4,0xb2,0x62,0xdc,0x99,0x49,0xf5,0xfe,0xbd,0xa5,0x27,0x69,0xbc,0xa2,0x9b,0xad,0x38,0xcb,0xc7,0xe,0x45,0x1e,0x71,0x7f,0x76,0x7a,0xd0,0x76,0xd0,0xb4,0x9e,0xf3,0x95,0x23,0x24,0xb7,0x83,0x1f,0x9d,0x59,0x5d,0x8d,0x3d,0x82,0x68,0xbb,0xa9,0xe1,0xda,0x2,0x66,0x9b,0x11,0x98,0xf,0xea,0xd1,0x45,0x32,0x39,0x8f,0x9a,0x25,0xd7,0x86,0xe3,0xa1,0xed,0xe1+};+const int private_d_length = 256;++const RSAPublicKey public_key = {+    64,+    -2086480183,+    {-366158713,-1545917456,27934618,-39769578,-990632677,1234935152,516355438,1105818205,-535730071,568706720,1261883376,-668875226,17163737,1936504555,-702271981,-416127073,339716299,922297937,1409351532,-749298078,1780075219,-411491888,-47259771,518548000,-1481645068,803493823,1779550631,773121200,-478653520,-450818791,688121231,696786065,-429732032,-1838847890,-867487078,-1722755215,-1339478364,510798710,1601407817,850801712,1949084552,1183606647,1786891322,-574925597,927819763,-1123763233,-1965624883,-539927980,1475572591,848923373,1499096069,621840009,-2037088750,-635016598,274547190,-655176099,-300379374,59871717,1119902794,-780141036,421466370,-817937763,-1358236915,-556993791},+    {-680089223,-223086018,455213076,259709388,556542659,-293057354,821528073,611556400,1521274678,1831462719,-304674729,842545110,973521751,-1143655792,473154895,-830707796,431437851,1815820373,-470513650,530194457,-794607273,1045821062,-512396943,-1380884004,1414132505,-1519702595,1005872574,-1044378383,-1979521599,-1171128315,-178710083,1377281803,1179717166,690438544,-217276920,1386046529,-925429649,-225916267,-1932816566,294396292,-527282176,1931197632,1042941970,-899269333,-1000286626,-413143069,-840851972,-629220562,1733300887,1505400970,1739245412,1881390228,1919690447,-1705906620,1316237371,1755947382,2057267192,-576770208,799408462,-1261886496,-1539284638,-376040433,539488060,1993460921},+    65537+};
+ Network/ADB/bigint.c view
@@ -0,0 +1,1536 @@+/*+ * Copyright (c) 2007, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/**+ * @defgroup bigint_api Big Integer API+ * @brief The bigint implementation as used by the axTLS project.+ *+ * The bigint library is for RSA encryption/decryption as well as signing.+ * This code tries to minimise use of malloc/free by maintaining a small + * cache. A bigint context may maintain state by being made "permanent". + * It be be later released with a bi_depermanent() and bi_free() call.+ *+ * It supports the following reduction techniques:+ * - Classical+ * - Barrett+ * - Montgomery+ *+ * It also implements the following:+ * - Karatsuba multiplication+ * - Squaring+ * - Sliding window exponentiation+ * - Chinese Remainder Theorem (implemented in rsa.c).+ *+ * All the algorithms used are pretty standard, and designed for different+ * data bus sizes. Negative numbers are not dealt with at all, so a subtraction+ * may need to be tested for negativity.+ *+ * This library steals some ideas from Jef Poskanzer+ * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>+ * and GMP <http://www.swox.com/gmp>. It gets most of its implementation+ * detail from "The Handbook of Applied Cryptography"+ * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>+ * @{+ */++#if defined(TEXT_BASE)+#define U_BOOT+#endif++#if !defined(U_BOOT)+#include <stdlib.h>+#include <limits.h>+#include <string.h>+#include <stdio.h>+#include <time.h>+#else+#include <common.h>+#include <malloc.h>+#endif+#include "os_port.h"+#include "bigint_impl.h"+#include "bigint.h"++#define V1      v->comps[v->size-1]                 /**< v1 for division */+#define V2      v->comps[v->size-2]                 /**< v2 for division */+#define U(j)    tmp_u->comps[tmp_u->size-j-1]       /**< uj for division */+#define Q(j)    quotient->comps[quotient->size-j-1] /**< qj for division */++static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i);+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom);+static bigint *alloc(BI_CTX *ctx, int size);+static bigint *trim(bigint *bi);+static void more_comps(bigint *bi, int n);+#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \+    defined(CONFIG_BIGINT_MONTGOMERY)+static bigint *comp_right_shift(bigint *biR, int num_shifts);+static bigint *comp_left_shift(bigint *biR, int num_shifts);+#endif++#ifdef CONFIG_BIGINT_CHECK_ON+static void check(const bigint *bi);+#else+#define check(A)                /**< disappears in normal production mode */+#endif+++/**+ * @brief Start a new bigint context.+ * @return A bigint context.+ */+BI_CTX *bi_initialize(void)+{+    /* calloc() sets everything to zero */+    BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX));+   +    /* the radix */+    ctx->bi_radix = alloc(ctx, 2); +    ctx->bi_radix->comps[0] = 0;+    ctx->bi_radix->comps[1] = 1;+    bi_permanent(ctx->bi_radix);+    return ctx;+}++/**+ * @brief Close the bigint context and free any resources.+ *+ * Free up any used memory - a check is done if all objects were not + * properly freed.+ * @param ctx [in]   The bigint session context.+ */+void bi_terminate(BI_CTX *ctx)+{+    bi_depermanent(ctx->bi_radix); +    bi_free(ctx, ctx->bi_radix);++    if (ctx->active_count != 0)+    {+#ifdef CONFIG_SSL_FULL_MODE+        printf("bi_terminate: there were %d un-freed bigints\n",+                       ctx->active_count);+#endif+#if !defined(U_BOOT)+        abort();+#endif+    }++    bi_clear_cache(ctx);+    free(ctx);+}++/**+ *@brief Clear the memory cache.+ */+void bi_clear_cache(BI_CTX *ctx)+{+    bigint *p, *pn;++    if (ctx->free_list == NULL)+        return;+    +    for (p = ctx->free_list; p != NULL; p = pn)+    {+        pn = p->next;+        free(p->comps);+        free(p);+    }++    ctx->free_count = 0;+    ctx->free_list = NULL;+}++/**+ * @brief Increment the number of references to this object. + * It does not do a full copy.+ * @param bi [in]   The bigint to copy.+ * @return A reference to the same bigint.+ */+bigint *bi_copy(bigint *bi)+{+    check(bi);+    if (bi->refs != PERMANENT)+        bi->refs++;+    return bi;+}++/**+ * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.+ *+ * For this object to be freed, bi_depermanent() must be called.+ * @param bi [in]   The bigint to be made permanent.+ */+void bi_permanent(bigint *bi)+{+    check(bi);+    if (bi->refs != 1)+    {+#ifdef CONFIG_SSL_FULL_MODE+        printf("bi_permanent: refs was not 1\n");+#endif+#if !defined(U_BOOT)+        abort();+#endif+    }++    bi->refs = PERMANENT;+}++/**+ * @brief Take a permanent object and make it eligible for freedom.+ * @param bi [in]   The bigint to be made back to temporary.+ */+void bi_depermanent(bigint *bi)+{+    check(bi);+    if (bi->refs != PERMANENT)+    {+#ifdef CONFIG_SSL_FULL_MODE+        printf("bi_depermanent: bigint was not permanent\n");+#endif+#if !defined(U_BOOT)+        abort();+#endif+    }++    bi->refs = 1;+}++/**+ * @brief Free a bigint object so it can be used again. + *+ * The memory itself it not actually freed, just tagged as being available + * @param ctx [in]   The bigint session context.+ * @param bi [in]    The bigint to be freed.+ */+void bi_free(BI_CTX *ctx, bigint *bi)+{+    check(bi);+    if (bi->refs == PERMANENT)+    {+        return;+    }++    if (--bi->refs > 0)+    {+        return;+    }++    bi->next = ctx->free_list;+    ctx->free_list = bi;+    ctx->free_count++;++    if (--ctx->active_count < 0)+    {+#ifdef CONFIG_SSL_FULL_MODE+        printf("bi_free: active_count went negative "+                "- double-freed bigint?\n");+#endif+#if !defined(U_BOOT)+        abort();+#endif+    }+}++/**+ * @brief Convert an (unsigned) integer into a bigint.+ * @param ctx [in]   The bigint session context.+ * @param i [in]     The (unsigned) integer to be converted.+ * + */+bigint *int_to_bi(BI_CTX *ctx, comp i)+{+    bigint *biR = alloc(ctx, 1);+    biR->comps[0] = i;+    return biR;+}++/**+ * @brief Do a full copy of the bigint object.+ * @param ctx [in]   The bigint session context.+ * @param bi  [in]   The bigint object to be copied.+ */+bigint *bi_clone(BI_CTX *ctx, const bigint *bi)+{+    bigint *biR = alloc(ctx, bi->size);+    check(bi);+    memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE);+    return biR;+}++/**+ * @brief Perform an addition operation between two bigints.+ * @param ctx [in]  The bigint session context.+ * @param bia [in]  A bigint.+ * @param bib [in]  Another bigint.+ * @return The result of the addition.+ */+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib)+{+    int n;+    comp carry = 0;+    comp *pa, *pb;++    check(bia);+    check(bib);++    n = max(bia->size, bib->size);+    more_comps(bia, n+1);+    more_comps(bib, n);+    pa = bia->comps;+    pb = bib->comps;++    do+    {+        comp  sl, rl, cy1;+        sl = *pa + *pb++;+        rl = sl + carry;+        cy1 = sl < *pa;+        carry = cy1 | (rl < sl);+        *pa++ = rl;+    } while (--n != 0);++    *pa = carry;                  /* do overflow */+    bi_free(ctx, bib);+    return trim(bia);+}++/**+ * @brief Perform a subtraction operation between two bigints.+ * @param ctx [in]  The bigint session context.+ * @param bia [in]  A bigint.+ * @param bib [in]  Another bigint.+ * @param is_negative [out] If defined, indicates that the result was negative.+ * is_negative may be null.+ * @return The result of the subtraction. The result is always positive.+ */+bigint *bi_subtract(BI_CTX *ctx, +        bigint *bia, bigint *bib, int *is_negative)+{+    int n = bia->size;+    comp *pa, *pb, carry = 0;++    check(bia);+    check(bib);++    more_comps(bib, n);+    pa = bia->comps;+    pb = bib->comps;++    do +    {+        comp sl, rl, cy1;+        sl = *pa - *pb++;+        rl = sl - carry;+        cy1 = sl > *pa;+        carry = cy1 | (rl > sl);+        *pa++ = rl;+    } while (--n != 0);++    if (is_negative)    /* indicate a negative result */+    {+        *is_negative = carry;+    }++    bi_free(ctx, trim(bib));    /* put bib back to the way it was */+    return trim(bia);+}++/**+ * Perform a multiply between a bigint an an (unsigned) integer+ */+static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)+{+    int j = 0, n = bia->size;+    bigint *biR = alloc(ctx, n + 1);+    comp carry = 0;+    comp *r = biR->comps;+    comp *a = bia->comps;++    check(bia);++    /* clear things to start with */+    memset(r, 0, ((n+1)*COMP_BYTE_SIZE));++    do+    {+        long_comp tmp = *r + (long_comp)a[j]*b + carry;+        *r++ = (comp)tmp;              /* downsize */+        carry = (comp)(tmp >> COMP_BIT_SIZE);+    } while (++j < n);++    *r = carry;+    bi_free(ctx, bia);+    return trim(biR);+}++/**+ * @brief Does both division and modulo calculations. + *+ * Used extensively when doing classical reduction.+ * @param ctx [in]  The bigint session context.+ * @param u [in]    A bigint which is the numerator.+ * @param v [in]    Either the denominator or the modulus depending on the mode.+ * @param is_mod [n] Determines if this is a normal division (0) or a reduction+ * (1).+ * @return  The result of the division/reduction.+ */+bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)+{+    int n = v->size, m = u->size-n;+    int j = 0, orig_u_size = u->size;+    uint8_t mod_offset = ctx->mod_offset;+    comp d;+    bigint *quotient, *tmp_u;+    comp q_dash;++    check(u);+    check(v);++    /* if doing reduction and we are < mod, then return mod */+    if (is_mod && bi_compare(v, u) > 0)+    {+        bi_free(ctx, v);+        return u;+    }++    quotient = alloc(ctx, m+1);+    tmp_u = alloc(ctx, n+1);+    v = trim(v);        /* make sure we have no leading 0's */+    d = (comp)((long_comp)COMP_RADIX/(V1+1));++    /* clear things to start with */+    memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));++    /* normalise */+    if (d > 1)+    {+        u = bi_int_multiply(ctx, u, d);++        if (is_mod)+        {+            v = ctx->bi_normalised_mod[mod_offset];+        }+        else+        {+            v = bi_int_multiply(ctx, v, d);+        }+    }++    if (orig_u_size == u->size)  /* new digit position u0 */+    {+        more_comps(u, orig_u_size + 1);+    }++    do+    {+        /* get a temporary short version of u */+        memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);++        /* calculate q' */+        if (U(0) == V1)+        {+            q_dash = COMP_RADIX-1;+        }+        else+        {+            q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1);++            if (v->size > 1 && V2)+            {+                /* we are implementing the following:+                if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) - +                        q_dash*V1)*COMP_RADIX) + U(2))) ... */+                comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) - +                                            (long_comp)q_dash*V1);+                if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2))+                {+                    q_dash--;+                }+            }+        }++        /* multiply and subtract */+        if (q_dash)+        {+            int is_negative;+            tmp_u = bi_subtract(ctx, tmp_u, +                    bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);+            more_comps(tmp_u, n+1);++            Q(j) = q_dash; ++            /* add back */+            if (is_negative)+            {+                Q(j)--;+                tmp_u = bi_add(ctx, tmp_u, bi_copy(v));++                /* lop off the carry */+                tmp_u->size--;+                v->size--;+            }+        }+        else+        {+            Q(j) = 0; +        }++        /* copy back to u */+        memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);+    } while (++j <= m);++    bi_free(ctx, tmp_u);+    bi_free(ctx, v);++    if (is_mod)     /* get the remainder */+    {+        bi_free(ctx, quotient);+        return bi_int_divide(ctx, trim(u), d);+    }+    else            /* get the quotient */+    {+        bi_free(ctx, u);+        return trim(quotient);+    }+}++/*+ * Perform an integer divide on a bigint.+ */+static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom)+{+    int i = biR->size - 1;+    long_comp r = 0;++    check(biR);++    do+    {+        r = (r<<COMP_BIT_SIZE) + biR->comps[i];+        biR->comps[i] = (comp)(r / denom);+        r %= denom;+    } while (--i >= 0);++    return trim(biR);+}++#ifdef CONFIG_BIGINT_MONTGOMERY+/**+ * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1, + * where B^-1(B-1) mod N=1. Actually, only the least significant part of + * N' is needed, hence the definition N0'=N' mod b. We reproduce below the + * simple algorithm from an article by Dusse and Kaliski to efficiently + * find N0' from N0 and b */+static comp modular_inverse(bigint *bim)+{+    int i;+    comp t = 1;+    comp two_2_i_minus_1 = 2;   /* 2^(i-1) */+    long_comp two_2_i = 4;      /* 2^i */+    comp N = bim->comps[0];++    for (i = 2; i <= COMP_BIT_SIZE; i++)+    {+        if ((long_comp)N*t%two_2_i >= two_2_i_minus_1)+        {+            t += two_2_i_minus_1;+        }++        two_2_i_minus_1 <<= 1;+        two_2_i <<= 1;+    }++    return (comp)(COMP_RADIX-t);+}+#endif++#if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \+    defined(CONFIG_BIGINT_MONTGOMERY)+/**+ * Take each component and shift down (in terms of components) + */+static bigint *comp_right_shift(bigint *biR, int num_shifts)+{+    int i = biR->size-num_shifts;+    comp *x = biR->comps;+    comp *y = &biR->comps[num_shifts];++    check(biR);++    if (i <= 0)     /* have we completely right shifted? */+    {+        biR->comps[0] = 0;  /* return 0 */+        biR->size = 1;+        return biR;+    }++    do+    {+        *x++ = *y++;+    } while (--i > 0);++    biR->size -= num_shifts;+    return biR;+}++/**+ * Take each component and shift it up (in terms of components) + */+static bigint *comp_left_shift(bigint *biR, int num_shifts)+{+    int i = biR->size-1;+    comp *x, *y;++    check(biR);++    if (num_shifts <= 0)+    {+        return biR;+    }++    more_comps(biR, biR->size + num_shifts);++    x = &biR->comps[i+num_shifts];+    y = &biR->comps[i];++    do+    {+        *x-- = *y--;+    } while (i--);++    memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */+    return biR;+}+#endif++/**+ * @brief Allow a binary sequence to be imported as a bigint.+ * @param ctx [in]  The bigint session context.+ * @param data [in] The data to be converted.+ * @param size [in] The number of bytes of data.+ * @return A bigint representing this data.+ */+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size)+{+    bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE);+    int i, j = 0, offset = 0;++    memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);++    for (i = size-1; i >= 0; i--)+    {+        biR->comps[offset] += data[i] << (j*8);++        if (++j == COMP_BYTE_SIZE)+        {+            j = 0;+            offset ++;+        }+    }++    return trim(biR);+}++#ifdef CONFIG_SSL_FULL_MODE+/**+ * @brief The testharness uses this code to import text hex-streams and + * convert them into bigints.+ * @param ctx [in]  The bigint session context.+ * @param data [in] A string consisting of hex characters. The characters must+ * be in upper case.+ * @return A bigint representing this data.+ */+bigint *bi_str_import(BI_CTX *ctx, const char *data)+{+    int size = strlen(data);+    bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES);+    int i, j = 0, offset = 0;+    memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);++    for (i = size-1; i >= 0; i--)+    {+        int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);+        biR->comps[offset] += num << (j*4);++        if (++j == COMP_NUM_NIBBLES)+        {+            j = 0;+            offset ++;+        }+    }++    return biR;+}++void bi_print(const char *label, bigint *x)+{+    int i, j;++    if (x == NULL)+    {+        printf("%s: (null)\n", label);+        return;+    }++    printf("%s: (size %d)\n", label, x->size);+    for (i = x->size-1; i >= 0; i--)+    {+        for (j = COMP_NUM_NIBBLES-1; j >= 0; j--)+        {+            comp mask = 0x0f << (j*4);+            comp num = (x->comps[i] & mask) >> (j*4);+            putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);+        }+    }  ++    printf("\n");+}+#endif++/**+ * @brief Take a bigint and convert it into a byte sequence. + *+ * This is useful after a decrypt operation.+ * @param ctx [in]  The bigint session context.+ * @param x [in]  The bigint to be converted.+ * @param data [out] The converted data as a byte stream.+ * @param size [in] The maximum size of the byte stream. Unused bytes will be+ * zeroed.+ */+void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)+{+    int i, j, k = size-1;++    check(x);+    memset(data, 0, size);  /* ensure all leading 0's are cleared */++    for (i = 0; i < x->size; i++)+    {+        for (j = 0; j < COMP_BYTE_SIZE; j++)+        {+            comp mask = 0xff << (j*8);+            int num = (x->comps[i] & mask) >> (j*8);+            data[k--] = num;++            if (k < 0)+            {+                goto buf_done;+            }+        }+    }+buf_done:++    bi_free(ctx, x);+}++/**+ * @brief Pre-calculate some of the expensive steps in reduction. + *+ * This function should only be called once (normally when a session starts).+ * When the session is over, bi_free_mod() should be called. bi_mod_power()+ * relies on this function being called.+ * @param ctx [in]  The bigint session context.+ * @param bim [in]  The bigint modulus that will be used.+ * @param mod_offset [in] There are three moduluii that can be stored - the+ * standard modulus, and its two primes p and q. This offset refers to which+ * modulus we are referring to.+ * @see bi_free_mod(), bi_mod_power().+ */+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)+{+    int k = bim->size;+    comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));+#ifdef CONFIG_BIGINT_MONTGOMERY+    bigint *R, *R2;+#endif++    ctx->bi_mod[mod_offset] = bim;+    bi_permanent(ctx->bi_mod[mod_offset]);+    ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);+    bi_permanent(ctx->bi_normalised_mod[mod_offset]);++#if defined(CONFIG_BIGINT_MONTGOMERY)+    /* set montgomery variables */+    R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1);     /* R */+    R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1);  /* R^2 */+    ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2);             /* R^2 mod m */+    ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R);               /* R mod m */++    bi_permanent(ctx->bi_RR_mod_m[mod_offset]);+    bi_permanent(ctx->bi_R_mod_m[mod_offset]);++    ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);++#elif defined (CONFIG_BIGINT_BARRETT)+    ctx->bi_mu[mod_offset] = +        bi_divide(ctx, comp_left_shift(+            bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);+    bi_permanent(ctx->bi_mu[mod_offset]);+#endif+}++/**+ * @brief Used when cleaning various bigints at the end of a session.+ * @param ctx [in]  The bigint session context.+ * @param mod_offset [in] The offset to use.+ * @see bi_set_mod().+ */+void bi_free_mod(BI_CTX *ctx, int mod_offset)+{+    bi_depermanent(ctx->bi_mod[mod_offset]);+    bi_free(ctx, ctx->bi_mod[mod_offset]);+#if defined (CONFIG_BIGINT_MONTGOMERY)+    bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);+    bi_depermanent(ctx->bi_R_mod_m[mod_offset]);+    bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);+    bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);+#elif defined(CONFIG_BIGINT_BARRETT)+    bi_depermanent(ctx->bi_mu[mod_offset]); +    bi_free(ctx, ctx->bi_mu[mod_offset]);+#endif+    bi_depermanent(ctx->bi_normalised_mod[mod_offset]); +    bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);+}++/** + * Perform a standard multiplication between two bigints.+ *+ * Barrett reduction has no need for some parts of the product, so ignore bits+ * of the multiply. This routine gives Barrett its big performance+ * improvements over Classical/Montgomery reduction methods. + */+static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib, +        int inner_partial, int outer_partial)+{+    int i = 0, j;+    int n = bia->size;+    int t = bib->size;+    bigint *biR = alloc(ctx, n + t);+    comp *sr = biR->comps;+    comp *sa = bia->comps;+    comp *sb = bib->comps;++    check(bia);+    check(bib);++    /* clear things to start with */+    memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE));++    do +    {+        long_comp tmp;+        comp carry = 0;+        int r_index = i;+        j = 0;++        if (outer_partial && outer_partial-i > 0 && outer_partial < n)+        {+            r_index = outer_partial-1;+            j = outer_partial-i-1;+        }++        do+        {+            if (inner_partial && r_index >= inner_partial) +            {+                break;+            }++            tmp = sr[r_index] + ((long_comp)sa[j])*sb[i] + carry;+            sr[r_index++] = (comp)tmp;              /* downsize */+            carry = tmp >> COMP_BIT_SIZE;+        } while (++j < n);++        sr[r_index] = carry;+    } while (++i < t);++    bi_free(ctx, bia);+    bi_free(ctx, bib);+    return trim(biR);+}++#ifdef CONFIG_BIGINT_KARATSUBA+/*+ * Karatsuba improves on regular multiplication due to only 3 multiplications + * being done instead of 4. The additional additions/subtractions are O(N) + * rather than O(N^2) and so for big numbers it saves on a few operations + */+static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square)+{+    bigint *x0, *x1;+    bigint *p0, *p1, *p2;+    int m;++    if (is_square)+    {+        m = (bia->size + 1)/2;+    }+    else+    {+        m = (max(bia->size, bib->size) + 1)/2;+    }++    x0 = bi_clone(ctx, bia);+    x0->size = m;+    x1 = bi_clone(ctx, bia);+    comp_right_shift(x1, m);+    bi_free(ctx, bia);++    /* work out the 3 partial products */+    if (is_square)+    {+        p0 = bi_square(ctx, bi_copy(x0));+        p2 = bi_square(ctx, bi_copy(x1));+        p1 = bi_square(ctx, bi_add(ctx, x0, x1));+    }+    else /* normal multiply */+    {+        bigint *y0, *y1;+        y0 = bi_clone(ctx, bib);+        y0->size = m;+        y1 = bi_clone(ctx, bib);+        comp_right_shift(y1, m);+        bi_free(ctx, bib);++        p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));+        p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));+        p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));+    }++    p1 = bi_subtract(ctx, +            bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL);++    comp_left_shift(p1, m);+    comp_left_shift(p2, 2*m);+    return bi_add(ctx, p1, bi_add(ctx, p0, p2));+}+#endif++/**+ * @brief Perform a multiplication operation between two bigints.+ * @param ctx [in]  The bigint session context.+ * @param bia [in]  A bigint.+ * @param bib [in]  Another bigint.+ * @return The result of the multiplication.+ */+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)+{+    check(bia);+    check(bib);++#ifdef CONFIG_BIGINT_KARATSUBA+    if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH)+    {+        return regular_multiply(ctx, bia, bib, 0, 0);+    }++    return karatsuba(ctx, bia, bib, 0);+#else+    return regular_multiply(ctx, bia, bib, 0, 0);+#endif+}++#ifdef CONFIG_BIGINT_SQUARE+/*+ * Perform the actual square operion. It takes into account overflow.+ */+static bigint *regular_square(BI_CTX *ctx, bigint *bi)+{+    int t = bi->size;+    int i = 0, j;+    bigint *biR = alloc(ctx, t*2+1);+    comp *w = biR->comps;+    comp *x = bi->comps;+    long_comp carry;+    memset(w, 0, biR->size*COMP_BYTE_SIZE);++    do+    {+        long_comp tmp = w[2*i] + (long_comp)x[i]*x[i];+        w[2*i] = (comp)tmp;+        carry = tmp >> COMP_BIT_SIZE;++        for (j = i+1; j < t; j++)+        {+            uint8_t c = 0;+            long_comp xx = (long_comp)x[i]*x[j];+            if ((COMP_MAX-xx) < xx)+                c = 1;++            tmp = (xx<<1);++            if ((COMP_MAX-tmp) < w[i+j])+                c = 1;++            tmp += w[i+j];++            if ((COMP_MAX-tmp) < carry)+                c = 1;++            tmp += carry;+            w[i+j] = (comp)tmp;+            carry = tmp >> COMP_BIT_SIZE;++            if (c)+                carry += COMP_RADIX;+        }++        tmp = w[i+t] + carry;+        w[i+t] = (comp)tmp;+        w[i+t+1] = tmp >> COMP_BIT_SIZE;+    } while (++i < t);++    bi_free(ctx, bi);+    return trim(biR);+}++/**+ * @brief Perform a square operation on a bigint.+ * @param ctx [in]  The bigint session context.+ * @param bia [in]  A bigint.+ * @return The result of the multiplication.+ */+bigint *bi_square(BI_CTX *ctx, bigint *bia)+{+    check(bia);++#ifdef CONFIG_BIGINT_KARATSUBA+    if (bia->size < SQU_KARATSUBA_THRESH) +    {+        return regular_square(ctx, bia);+    }++    return karatsuba(ctx, bia, NULL, 1);+#else+    return regular_square(ctx, bia);+#endif+}+#endif++/**+ * @brief Compare two bigints.+ * @param bia [in]  A bigint.+ * @param bib [in]  Another bigint.+ * @return -1 if smaller, 1 if larger and 0 if equal.+ */+int bi_compare(bigint *bia, bigint *bib)+{+    int r, i;++    check(bia);+    check(bib);++    if (bia->size > bib->size)+        r = 1;+    else if (bia->size < bib->size)+        r = -1;+    else+    {+        comp *a = bia->comps; +        comp *b = bib->comps; ++        /* Same number of components.  Compare starting from the high end+         * and working down. */+        r = 0;+        i = bia->size - 1;++        do +        {+            if (a[i] > b[i])+            { +                r = 1;+                break; +            }+            else if (a[i] < b[i])+            { +                r = -1;+                break; +            }+        } while (--i >= 0);+    }++    return r;+}++/*+ * Allocate and zero more components.  Does not consume bi. + */+static void more_comps(bigint *bi, int n)+{+    if (n > bi->max_comps)+    {+        bi->max_comps = max(bi->max_comps * 2, n);+        bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);+    }++    if (n > bi->size)+    {+        memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);+    }++    bi->size = n;+}++/*+ * Make a new empty bigint. It may just use an old one if one is available.+ * Otherwise get one off the heap.+ */+static bigint *alloc(BI_CTX *ctx, int size)+{+    bigint *biR;++    /* Can we recycle an old bigint? */+    if (ctx->free_list != NULL)+    {+        biR = ctx->free_list;+        ctx->free_list = biR->next;+        ctx->free_count--;++        if (biR->refs != 0)+        {+#ifdef CONFIG_SSL_FULL_MODE+            printf("alloc: refs was not 0\n");+#endif+#if !defined(U_BOOT)+            abort();+#endif+        }++        more_comps(biR, size);+    }+    else+    {+        /* No free bigints available - create a new one. */+        biR = (bigint *)malloc(sizeof(bigint));+        biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE);+        biR->max_comps = size;  /* give some space to spare */+    }++    biR->size = size;+    biR->refs = 1;+    biR->next = NULL;+    ctx->active_count++;+    return biR;+}++/*+ * Work out the highest '1' bit in an exponent. Used when doing sliding-window+ * exponentiation.+ */+static int find_max_exp_index(bigint *biexp)+{+    int i = COMP_BIT_SIZE-1;+    comp shift = COMP_RADIX/2;+    comp test = biexp->comps[biexp->size-1];    /* assume no leading zeroes */++    check(biexp);++    do+    {+        if (test & shift)+        {+            return i+(biexp->size-1)*COMP_BIT_SIZE;+        }++        shift >>= 1;+    } while (i-- != 0);++    return -1;      /* error - must have been a leading 0 */+}++/*+ * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window+ * exponentiation.+ */+static int exp_bit_is_one(bigint *biexp, int offset)+{+    comp test = biexp->comps[offset / COMP_BIT_SIZE];+    int num_shifts = offset % COMP_BIT_SIZE;+    comp shift = 1;+    int i;++    check(biexp);++    for (i = 0; i < num_shifts; i++)+    {+        shift <<= 1;+    }++    return (test & shift) != 0;+}++#ifdef CONFIG_BIGINT_CHECK_ON+/*+ * Perform a sanity check on bi.+ */+static void check(const bigint *bi)+{+    if (bi->refs <= 0)+    {+        printf("check: zero or negative refs in bigint\n");+#if !defined(U_BOOT)+        abort();+#endif+    }++    if (bi->next != NULL)+    {+        printf("check: attempt to use a bigint from "+                "the free list\n");+#if !defined(U_BOOT)+        abort();+#endif+    }+}+#endif++/*+ * Delete any leading 0's (and allow for 0).+ */+static bigint *trim(bigint *bi)+{+    check(bi);++    while (bi->comps[bi->size-1] == 0 && bi->size > 1)+    {+        bi->size--;+    }++    return bi;+}++#if defined(CONFIG_BIGINT_MONTGOMERY)+/**+ * @brief Perform a single montgomery reduction.+ * @param ctx [in]  The bigint session context.+ * @param bixy [in]  A bigint.+ * @return The result of the montgomery reduction.+ */+bigint *bi_mont(BI_CTX *ctx, bigint *bixy)+{+    int i = 0, n;+    uint8_t mod_offset = ctx->mod_offset;+    bigint *bim = ctx->bi_mod[mod_offset];+    comp mod_inv = ctx->N0_dash[mod_offset];++    check(bixy);++    if (ctx->use_classical)     /* just use classical instead */+    {+        return bi_mod(ctx, bixy);+    }++    n = bim->size;++    do+    {+        bixy = bi_add(ctx, bixy, comp_left_shift(+                    bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));+    } while (++i < n);++    comp_right_shift(bixy, n);++    if (bi_compare(bixy, bim) >= 0)+    {+        bixy = bi_subtract(ctx, bixy, bim, NULL);+    }++    return bixy;+}++#elif defined(CONFIG_BIGINT_BARRETT)+/*+ * Stomp on the most significant components to give the illusion of a "mod base+ * radix" operation + */+static bigint *comp_mod(bigint *bi, int mod)+{+    check(bi);++    if (bi->size > mod)+    {+        bi->size = mod;+    }++    return bi;+}++/**+ * @brief Perform a single Barrett reduction.+ * @param ctx [in]  The bigint session context.+ * @param bi [in]  A bigint.+ * @return The result of the Barrett reduction.+ */+bigint *bi_barrett(BI_CTX *ctx, bigint *bi)+{+    bigint *q1, *q2, *q3, *r1, *r2, *r;+    uint8_t mod_offset = ctx->mod_offset;+    bigint *bim = ctx->bi_mod[mod_offset];+    int k = bim->size;++    check(bi);+    check(bim);++    /* use Classical method instead  - Barrett cannot help here */+    if (bi->size > k*2)+    {+        return bi_mod(ctx, bi);+    }++    q1 = comp_right_shift(bi_clone(ctx, bi), k-1);++    /* do outer partial multiply */+    q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1); +    q3 = comp_right_shift(q2, k+1);+    r1 = comp_mod(bi, k+1);++    /* do inner partial multiply */+    r2 = comp_mod(regular_multiply(ctx, q3, bim, k+1, 0), k+1);+    r = bi_subtract(ctx, r1, r2, NULL);++    /* if (r >= m) r = r - m; */+    if (bi_compare(r, bim) >= 0)+    {+        r = bi_subtract(ctx, r, bim, NULL);+    }++    return r;+}+#endif /* CONFIG_BIGINT_BARRETT */++#ifdef CONFIG_BIGINT_SLIDING_WINDOW+/*+ * Work out g1, g3, g5, g7... etc for the sliding-window algorithm + */+static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1)+{+    int k = 1, i;+    bigint *g2;++    for (i = 0; i < window-1; i++)   /* compute 2^(window-1) */+    {+        k <<= 1;+    }++    ctx->g = (bigint **)malloc(k*sizeof(bigint *));+    ctx->g[0] = bi_clone(ctx, g1);+    bi_permanent(ctx->g[0]);+    g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0]));   /* g^2 */++    for (i = 1; i < k; i++)+    {+        ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2)));+        bi_permanent(ctx->g[i]);+    }++    bi_free(ctx, g2);+    ctx->window = k;+}+#endif++/**+ * @brief Perform a modular exponentiation.+ *+ * This function requires bi_set_mod() to have been called previously. This is + * one of the optimisations used for performance.+ * @param ctx [in]  The bigint session context.+ * @param bi  [in]  The bigint on which to perform the mod power operation.+ * @param biexp [in] The bigint exponent.+ * @return The result of the mod exponentiation operation+ * @see bi_set_mod().+ */+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)+{+    int i = find_max_exp_index(biexp), j, window_size = 1;+    bigint *biR = int_to_bi(ctx, 1);++#if defined(CONFIG_BIGINT_MONTGOMERY)+    uint8_t mod_offset = ctx->mod_offset;+    if (!ctx->use_classical)+    {+        /* preconvert */+        bi = bi_mont(ctx, +                bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset]));    /* x' */+        bi_free(ctx, biR);+        biR = ctx->bi_R_mod_m[mod_offset];                              /* A */+    }+#endif++    check(bi);+    check(biexp);++#ifdef CONFIG_BIGINT_SLIDING_WINDOW+    for (j = i; j > 32; j /= 5) /* work out an optimum size */+        window_size++;++    /* work out the slide constants */+    precompute_slide_window(ctx, window_size, bi);+#else   /* just one constant */+    ctx->g = (bigint **)malloc(sizeof(bigint *));+    ctx->g[0] = bi_clone(ctx, bi);+    ctx->window = 1;+    bi_permanent(ctx->g[0]);+#endif++    /* if sliding-window is off, then only one bit will be done at a time and+     * will reduce to standard left-to-right exponentiation */+    do+    {+        if (exp_bit_is_one(biexp, i))+        {+            int l = i-window_size+1;+            int part_exp = 0;++            if (l < 0)  /* LSB of exponent will always be 1 */+                l = 0;+            else+            {+                while (exp_bit_is_one(biexp, l) == 0)+                    l++;    /* go back up */+            }++            /* build up the section of the exponent */+            for (j = i; j >= l; j--)+            {+                biR = bi_residue(ctx, bi_square(ctx, biR));+                if (exp_bit_is_one(biexp, j))+                    part_exp++;++                if (j != l)+                    part_exp <<= 1;+            }++            part_exp = (part_exp-1)/2;  /* adjust for array */+            biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));+            i = l-1;+        }+        else    /* square it */+        {+            biR = bi_residue(ctx, bi_square(ctx, biR));+            i--;+        }+    } while (i >= 0);+     +    /* cleanup */+    for (i = 0; i < ctx->window; i++)+    {+        bi_depermanent(ctx->g[i]);+        bi_free(ctx, ctx->g[i]);+    }++    free(ctx->g);+    bi_free(ctx, bi);+    bi_free(ctx, biexp);+#if defined CONFIG_BIGINT_MONTGOMERY+    return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */+#else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */+    return biR;+#endif+}++#ifdef CONFIG_SSL_CERT_VERIFICATION+/**+ * @brief Perform a modular exponentiation using a temporary modulus.+ *+ * We need this function to check the signatures of certificates. The modulus+ * of this function is temporary as it's just used for authentication.+ * @param ctx [in]  The bigint session context.+ * @param bi  [in]  The bigint to perform the exp/mod.+ * @param bim [in]  The temporary modulus.+ * @param biexp [in] The bigint exponent.+ * @return The result of the mod exponentiation operation+ * @see bi_set_mod().+ */+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp)+{+    bigint *biR, *tmp_biR;++    /* Set up a temporary bigint context and transfer what we need between+     * them. We need to do this since we want to keep the original modulus+     * which is already in this context. This operation is only called when+     * doing peer verification, and so is not expensive :-) */+    BI_CTX *tmp_ctx = bi_initialize();+    bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET);+    tmp_biR = bi_mod_power(tmp_ctx, +                bi_clone(tmp_ctx, bi), +                bi_clone(tmp_ctx, biexp));+    biR = bi_clone(ctx, tmp_biR);+    bi_free(tmp_ctx, tmp_biR);+    bi_free_mod(tmp_ctx, BIGINT_M_OFFSET);+    bi_terminate(tmp_ctx);++    bi_free(ctx, bi);+    bi_free(ctx, bim);+    bi_free(ctx, biexp);+    return biR;+}+#endif++#ifdef CONFIG_BIGINT_CRT+/**+ * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.+ *+ * @param ctx [in]  The bigint session context.+ * @param bi  [in]  The bigint to perform the exp/mod.+ * @param dP [in] CRT's dP bigint+ * @param dQ [in] CRT's dQ bigint+ * @param p [in] CRT's p bigint+ * @param q [in] CRT's q bigint+ * @param qInv [in] CRT's qInv bigint+ * @return The result of the CRT operation+ */+bigint *bi_crt(BI_CTX *ctx, bigint *bi,+        bigint *dP, bigint *dQ,+        bigint *p, bigint *q, bigint *qInv)+{+    bigint *m1, *m2, *h;++    /* Montgomery has a condition the 0 < x, y < m and these products violate+     * that condition. So disable Montgomery when using CRT */+#if defined(CONFIG_BIGINT_MONTGOMERY)+    ctx->use_classical = 1;+#endif+    ctx->mod_offset = BIGINT_P_OFFSET;+    m1 = bi_mod_power(ctx, bi_copy(bi), dP);++    ctx->mod_offset = BIGINT_Q_OFFSET;+    m2 = bi_mod_power(ctx, bi, dQ);++    h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL);+    h = bi_multiply(ctx, h, qInv);+    ctx->mod_offset = BIGINT_P_OFFSET;+    h = bi_residue(ctx, h);+#if defined(CONFIG_BIGINT_MONTGOMERY)+    ctx->use_classical = 0;         /* reset for any further operation */+#endif+    return bi_add(ctx, m2, bi_multiply(ctx, q, h));+}+#endif+/** @} */
+ Network/ADB/bigint.h view
@@ -0,0 +1,97 @@+/*+ * Copyright (c) 2007, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef BIGINT_HEADER+#define BIGINT_HEADER++BI_CTX *bi_initialize(void);+void bi_terminate(BI_CTX *ctx);+void bi_permanent(bigint *bi);+void bi_depermanent(bigint *bi);+void bi_clear_cache(BI_CTX *ctx);+void bi_free(BI_CTX *ctx, bigint *bi);+bigint *bi_copy(bigint *bi);+bigint *bi_clone(BI_CTX *ctx, const bigint *bi);+void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size);+bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len);+bigint *int_to_bi(BI_CTX *ctx, comp i);++/* the functions that actually do something interesting */+bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib);+bigint *bi_subtract(BI_CTX *ctx, bigint *bia, +        bigint *bib, int *is_negative);+bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod);+bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib);+bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp);+bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp);+int bi_compare(bigint *bia, bigint *bib);+void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset);+void bi_free_mod(BI_CTX *ctx, int mod_offset);++#ifdef CONFIG_SSL_FULL_MODE+void bi_print(const char *label, bigint *bi);+bigint *bi_str_import(BI_CTX *ctx, const char *data);+#endif++/**+ * @def bi_mod+ * Find the residue of B. bi_set_mod() must be called before hand.+ */+#define bi_mod(A, B)      bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1)++/**+ * bi_residue() is technically the same as bi_mod(), but it uses the+ * appropriate reduction technique (which is bi_mod() when doing classical+ * reduction).+ */+#if defined(CONFIG_BIGINT_MONTGOMERY)+#define bi_residue(A, B)         bi_mont(A, B)+bigint *bi_mont(BI_CTX *ctx, bigint *bixy);+#elif defined(CONFIG_BIGINT_BARRETT)+#define bi_residue(A, B)         bi_barrett(A, B)+bigint *bi_barrett(BI_CTX *ctx, bigint *bi);+#else /* if defined(CONFIG_BIGINT_CLASSICAL) */+#define bi_residue(A, B)         bi_mod(A, B)+#endif++#ifdef CONFIG_BIGINT_SQUARE+bigint *bi_square(BI_CTX *ctx, bigint *bi);+#else+#define bi_square(A, B)     bi_multiply(A, bi_copy(B), B)+#endif++#ifdef CONFIG_BIGINT_CRT+bigint *bi_crt(BI_CTX *ctx, bigint *bi,+        bigint *dP, bigint *dQ,+        bigint *p, bigint *q,+        bigint *qInv);+#endif++#endif
+ Network/ADB/bigint_impl.h view
@@ -0,0 +1,126 @@+/*+ * Copyright (c) 2007, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++#ifndef BIGINT_IMPL_HEADER+#define BIGINT_IMPL_HEADER++/* Maintain a number of precomputed variables when doing reduction */+#define BIGINT_M_OFFSET     0    /**< Normal modulo offset. */+#ifdef CONFIG_BIGINT_CRT+#define BIGINT_P_OFFSET     1    /**< p modulo offset. */+#define BIGINT_Q_OFFSET     2    /**< q module offset. */+#define BIGINT_NUM_MODS     3    /**< The number of modulus constants used. */+#else+#define BIGINT_NUM_MODS     1    +#endif++/* Architecture specific functions for big ints */+#if defined(CONFIG_INTEGER_8BIT)+#define COMP_RADIX          256U       /**< Max component + 1 */+#define COMP_MAX            0xFFFFU/**< (Max dbl comp -1) */+#define COMP_BIT_SIZE       8   /**< Number of bits in a component. */+#define COMP_BYTE_SIZE      1   /**< Number of bytes in a component. */+#define COMP_NUM_NIBBLES    2   /**< Used For diagnostics only. */+typedef uint8_t comp;	        /**< A single precision component. */+typedef uint16_t long_comp;     /**< A double precision component. */+typedef int16_t slong_comp;     /**< A signed double precision component. */+#elif defined(CONFIG_INTEGER_16BIT)+#define COMP_RADIX          65536U       /**< Max component + 1 */+#define COMP_MAX            0xFFFFFFFFU/**< (Max dbl comp -1) */+#define COMP_BIT_SIZE       16  /**< Number of bits in a component. */+#define COMP_BYTE_SIZE      2   /**< Number of bytes in a component. */+#define COMP_NUM_NIBBLES    4   /**< Used For diagnostics only. */+typedef uint16_t comp;	        /**< A single precision component. */+typedef uint32_t long_comp;     /**< A double precision component. */+typedef int32_t slong_comp;     /**< A signed double precision component. */+#else /* regular 32 bit */+#define COMP_RADIX          4294967296ULL         /**< Max component + 1 */+#define COMP_MAX            0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */+#define COMP_BIT_SIZE       32  /**< Number of bits in a component. */+#define COMP_BYTE_SIZE      4   /**< Number of bytes in a component. */+#define COMP_NUM_NIBBLES    8   /**< Used For diagnostics only. */+typedef uint32_t comp;	        /**< A single precision component. */+typedef uint64_t long_comp;     /**< A double precision component. */+typedef int64_t slong_comp;     /**< A signed double precision component. */+#endif++/**+ * @struct  _bigint+ * @brief A big integer basic object+ */+struct _bigint+{+    struct _bigint* next;       /**< The next bigint in the cache. */+    short size;                 /**< The number of components in this bigint. */+    short max_comps;            /**< The heapsize allocated for this bigint */+    int refs;                   /**< An internal reference count. */+    comp* comps;                /**< A ptr to the actual component data */+};++typedef struct _bigint bigint;  /**< An alias for _bigint */++/**+ * Maintains the state of the cache, and a number of variables used in + * reduction.+ */+typedef struct /**< A big integer "session" context. */+{+    bigint *active_list;                    /**< Bigints currently used. */+    bigint *free_list;                      /**< Bigints not used. */+    bigint *bi_radix;                       /**< The radix used. */+    bigint *bi_mod[BIGINT_NUM_MODS];        /**< modulus */++#if defined(CONFIG_BIGINT_MONTGOMERY)+    bigint *bi_RR_mod_m[BIGINT_NUM_MODS];   /**< R^2 mod m */+    bigint *bi_R_mod_m[BIGINT_NUM_MODS];    /**< R mod m */+    comp N0_dash[BIGINT_NUM_MODS];+#elif defined(CONFIG_BIGINT_BARRETT)+    bigint *bi_mu[BIGINT_NUM_MODS];         /**< Storage for mu */+#endif+    bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */+    bigint **g;                 /**< Used by sliding-window. */+    int window;                 /**< The size of the sliding window */+    int active_count;           /**< Number of active bigints. */+    int free_count;             /**< Number of free bigints. */++#ifdef CONFIG_BIGINT_MONTGOMERY+    uint8_t use_classical;      /**< Use classical reduction. */+#endif+    uint8_t mod_offset;         /**< The mod offset we are using */+} BI_CTX;++#if !defined(U_BOOT)+#define max(a,b) ((a)>(b)?(a):(b))  /**< Find the maximum of 2 numbers. */+#define min(a,b) ((a)<(b)?(a):(b))  /**< Find the minimum of 2 numbers. */+#endif++#define PERMANENT           0x7FFF55AA  /**< A magic number for permanents. */++#endif
+ Network/ADB/crypto.h view
@@ -0,0 +1,230 @@+/*+ * Copyright (c) 2007, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/**+ * @file crypto.h+ */++#ifndef HEADER_CRYPTO_H+#define HEADER_CRYPTO_H++#define CONFIG_SSL_CERT_VERIFICATION++#ifdef __cplusplus+extern "C" {+#endif+#include "bigint_impl.h"+#include "bigint.h"++#ifndef STDCALL+#define STDCALL+#endif+#ifndef EXP_FUNC+#define EXP_FUNC+#endif+++/* enable features based on a 'super-set' capbaility. */+#if defined(CONFIG_SSL_FULL_MODE) +#define CONFIG_SSL_ENABLE_CLIENT+#define CONFIG_SSL_CERT_VERIFICATION+#elif defined(CONFIG_SSL_ENABLE_CLIENT)+#define CONFIG_SSL_CERT_VERIFICATION+#endif++/**************************************************************************+ * AES declarations + **************************************************************************/++#define AES_MAXROUNDS			14+#define AES_BLOCKSIZE           16+#define AES_IV_SIZE             16++typedef struct aes_key_st +{+    uint16_t rounds;+    uint16_t key_size;+    uint32_t ks[(AES_MAXROUNDS+1)*8];+    uint8_t iv[AES_IV_SIZE];+} AES_CTX;++typedef enum+{+    AES_MODE_128,+    AES_MODE_256+} AES_MODE;++void AES_set_key(AES_CTX *ctx, const uint8_t *key, +        const uint8_t *iv, AES_MODE mode);+void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, +        uint8_t *out, int length);+void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);+void AES_convert_key(AES_CTX *ctx);++/**************************************************************************+ * RC4 declarations + **************************************************************************/++typedef struct +{+    uint8_t x, y, m[256];+} RC4_CTX;++void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);+void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);++/**************************************************************************+ * SHA1 declarations + **************************************************************************/++#define SHA1_SIZE   20++/*+ *  This structure will hold context information for the SHA-1+ *  hashing operation+ */+typedef struct +{+    uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */+    uint32_t Length_Low;            /* Message length in bits */+    uint32_t Length_High;           /* Message length in bits */+    uint16_t Message_Block_Index;   /* Index into message block array   */+    uint8_t Message_Block[64];      /* 512-bit message blocks */+} SHA1_CTX;++void SHA1_Init(SHA1_CTX *);+void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len);+void SHA1_Final(uint8_t *digest, SHA1_CTX *);++/**************************************************************************+ * MD2 declarations + **************************************************************************/++#define MD2_SIZE 16++typedef struct+{+    unsigned char cksum[16];    /* checksum of the data block */+    unsigned char state[48];    /* intermediate digest state */+    unsigned char buffer[16];   /* data block being processed */+    int left;                   /* amount of data in buffer */+} MD2_CTX;++EXP_FUNC void STDCALL MD2_Init(MD2_CTX *ctx);+EXP_FUNC void STDCALL MD2_Update(MD2_CTX *ctx, const uint8_t *input, int ilen);+EXP_FUNC void STDCALL MD2_Final(uint8_t *digest, MD2_CTX *ctx);++/**************************************************************************+ * MD5 declarations + **************************************************************************/++#define MD5_SIZE    16++typedef struct +{+  uint32_t state[4];        /* state (ABCD) */+  uint32_t count[2];        /* number of bits, modulo 2^64 (lsb first) */+  uint8_t buffer[64];       /* input buffer */+} MD5_CTX;++EXP_FUNC void STDCALL MD5_Init(MD5_CTX *);+EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len);+EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *);++/**************************************************************************+ * HMAC declarations + **************************************************************************/+void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, +        int key_len, uint8_t *digest);+void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, +        int key_len, uint8_t *digest);++/**************************************************************************+ * RSA declarations + **************************************************************************/++typedef struct +{+    bigint *m;              /* modulus */+    bigint *e;              /* public exponent */+    bigint *d;              /* private exponent */+#ifdef CONFIG_BIGINT_CRT+    bigint *p;              /* p as in m = pq */+    bigint *q;              /* q as in m = pq */+    bigint *dP;             /* d mod (p-1) */+    bigint *dQ;             /* d mod (q-1) */+    bigint *qInv;           /* q^-1 mod p */+#endif+    int num_octets;+    BI_CTX *bi_ctx;+} RSA_CTX;++void RSA_priv_key_new(RSA_CTX **rsa_ctx, +        const uint8_t *modulus, int mod_len,+        const uint8_t *pub_exp, int pub_len,+        const uint8_t *priv_exp, int priv_len+#ifdef CONFIG_BIGINT_CRT+      , const uint8_t *p, int p_len,+        const uint8_t *q, int q_len,+        const uint8_t *dP, int dP_len,+        const uint8_t *dQ, int dQ_len,+        const uint8_t *qInv, int qInv_len+#endif+        );+void RSA_pub_key_new(RSA_CTX **rsa_ctx, +        const uint8_t *modulus, int mod_len,+        const uint8_t *pub_exp, int pub_len);+void RSA_free(RSA_CTX *ctx);+int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint8_t *out_data,+        int is_decryption);+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg);+#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)+bigint *RSA_sign_verify(BI_CTX *ctx, const uint8_t *sig, int sig_len,+        bigint *modulus, bigint *pub_exp);+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg);+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, +        uint8_t *out_data, int is_signing);+void RSA_print(const RSA_CTX *ctx);+#endif++/**************************************************************************+ * RNG declarations + **************************************************************************/+EXP_FUNC void STDCALL RNG_initialize(void);+EXP_FUNC void STDCALL RNG_custom_init(const uint8_t *seed_buf, int size);+EXP_FUNC void STDCALL RNG_terminate(void);+EXP_FUNC void STDCALL get_random(int num_rand_bytes, uint8_t *rand_data);+void get_random_NZ(int num_rand_bytes, uint8_t *rand_data);++#ifdef __cplusplus+}+#endif++#endif 
+ Network/ADB/os_int.h view
@@ -0,0 +1,56 @@+/*+ * Copyright (c) 2012, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/**+ * @file os_int.h+ *+ * Ensure a consistent bit size + */++#ifndef HEADER_OS_INT_H+#define HEADER_OS_INT_H++#ifdef __cplusplus+extern "C" {+#endif++#if !defined(U_BOOT)+#ifdef CONFIG_PLATFORM_SOLARIS+#include <inttypes.h>+#else+#include <stdint.h>+#endif /* Not Solaris */+#endif++#ifdef __cplusplus+}+#endif++#endif 
+ Network/ADB/os_port.h view
@@ -0,0 +1,113 @@+/*+ * Copyright (c) 2007, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/**+ * @file os_port.h+ *+ * Some stuff to minimise the differences between windows and linux/unix+ */++#ifndef HEADER_OS_PORT_H+#define HEADER_OS_PORT_H++#ifdef __cplusplus+extern "C" {+#endif++#include "os_int.h"+#if !defined(U_BOOT)+#include <stdio.h>+#endif++#define STDCALL+#define EXP_FUNC++#if !defined(U_BOOT)+#include <unistd.h>+#include <dirent.h>+#include <fcntl.h>+#include <errno.h>+#include <sys/stat.h>+#include <sys/time.h>+#endif++#define SOCKET_READ(A,B,C)      read(A,B,C)+#define SOCKET_WRITE(A,B,C)     write(A,B,C)+#define SOCKET_CLOSE(A)         if (A >= 0) close(A)+#define TTY_FLUSH()++#if 0+/* some functions to mutate the way these work */+#define malloc(A)       ax_malloc(A)+#ifndef realloc+#define realloc(A,B)    ax_realloc(A,B)+#endif+#define calloc(A,B)     ax_calloc(A,B)+#endif++EXP_FUNC void * STDCALL ax_malloc(size_t s);+EXP_FUNC void * STDCALL ax_realloc(void *y, size_t s);+EXP_FUNC void * STDCALL ax_calloc(size_t n, size_t s);+EXP_FUNC int STDCALL ax_open(const char *pathname, int flags); ++#ifdef CONFIG_PLATFORM_LINUX+void exit_now(const char *format, ...) __attribute((noreturn));+#else+void exit_now(const char *format, ...);+#endif++/* Mutexing definitions */+#if defined(CONFIG_SSL_CTX_MUTEXING)+#if defined(WIN32)+#define SSL_CTX_MUTEX_TYPE          HANDLE+#define SSL_CTX_MUTEX_INIT(A)       A=CreateMutex(0, FALSE, 0)+#define SSL_CTX_MUTEX_DESTROY(A)    CloseHandle(A)+#define SSL_CTX_LOCK(A)             WaitForSingleObject(A, INFINITE)+#define SSL_CTX_UNLOCK(A)           ReleaseMutex(A)+#else +#include <pthread.h>+#define SSL_CTX_MUTEX_TYPE          pthread_mutex_t+#define SSL_CTX_MUTEX_INIT(A)       pthread_mutex_init(&A, NULL)+#define SSL_CTX_MUTEX_DESTROY(A)    pthread_mutex_destroy(&A)+#define SSL_CTX_LOCK(A)             pthread_mutex_lock(&A)+#define SSL_CTX_UNLOCK(A)           pthread_mutex_unlock(&A)+#endif+#else   /* no mutexing */+#define SSL_CTX_MUTEX_INIT(A)+#define SSL_CTX_MUTEX_DESTROY(A)+#define SSL_CTX_LOCK(A)+#define SSL_CTX_UNLOCK(A)+#endif++#ifdef __cplusplus+}+#endif++#endif 
+ Network/ADB/rsa.c view
@@ -0,0 +1,279 @@+/*+ * Copyright (c) 2007, Cameron Rich+ * + * All rights reserved.+ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met:+ *+ * * Redistributions of source code must retain the above copyright notice, + *   this list of conditions and the following disclaimer.+ * * Redistributions in binary form must reproduce the above copyright notice, + *   this list of conditions and the following disclaimer in the documentation + *   and/or other materials provided with the distribution.+ * * Neither the name of the axTLS project nor the names of its contributors + *   may be used to endorse or promote products derived from this software + *   without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+ */++/**+ * Implements the RSA public encryption algorithm. Uses the bigint library to+ * perform its calculations.+ */++#if defined(TEXT_BASE)+#define U_BOOT+#endif++#if !defined(TEXT_BASE)+#include <stdio.h>+#include <string.h>+#include <time.h>+#include <stdlib.h>+#else+#include <common.h>+#include <malloc.h>+#endif+#include "os_port.h"+#include "crypto.h"++void RSA_priv_key_new(RSA_CTX **ctx, +        const uint8_t *modulus, int mod_len,+        const uint8_t *pub_exp, int pub_len,+        const uint8_t *priv_exp, int priv_len+#if CONFIG_BIGINT_CRT+      , const uint8_t *p, int p_len,+        const uint8_t *q, int q_len,+        const uint8_t *dP, int dP_len,+        const uint8_t *dQ, int dQ_len,+        const uint8_t *qInv, int qInv_len+#endif+    )+{+    RSA_CTX *rsa_ctx;+    BI_CTX *bi_ctx;+    RSA_pub_key_new(ctx, modulus, mod_len, pub_exp, pub_len);+    rsa_ctx = *ctx;+    bi_ctx = rsa_ctx->bi_ctx;+    rsa_ctx->d = bi_import(bi_ctx, priv_exp, priv_len);+    bi_permanent(rsa_ctx->d);++#ifdef CONFIG_BIGINT_CRT+    rsa_ctx->p = bi_import(bi_ctx, p, p_len);+    rsa_ctx->q = bi_import(bi_ctx, q, q_len);+    rsa_ctx->dP = bi_import(bi_ctx, dP, dP_len);+    rsa_ctx->dQ = bi_import(bi_ctx, dQ, dQ_len);+    rsa_ctx->qInv = bi_import(bi_ctx, qInv, qInv_len);+    bi_permanent(rsa_ctx->dP);+    bi_permanent(rsa_ctx->dQ);+    bi_permanent(rsa_ctx->qInv);+    bi_set_mod(bi_ctx, rsa_ctx->p, BIGINT_P_OFFSET);+    bi_set_mod(bi_ctx, rsa_ctx->q, BIGINT_Q_OFFSET);+#endif+}++void RSA_pub_key_new(RSA_CTX **ctx, +        const uint8_t *modulus, int mod_len,+        const uint8_t *pub_exp, int pub_len)+{+    RSA_CTX *rsa_ctx;+    BI_CTX *bi_ctx;++    if (*ctx)   /* if we load multiple certs, dump the old one */+        RSA_free(*ctx);++    bi_ctx = bi_initialize();+    *ctx = (RSA_CTX *)calloc(1, sizeof(RSA_CTX));+    rsa_ctx = *ctx;+    rsa_ctx->bi_ctx = bi_ctx;+    rsa_ctx->num_octets = mod_len;+    rsa_ctx->m = bi_import(bi_ctx, modulus, mod_len);+    bi_set_mod(bi_ctx, rsa_ctx->m, BIGINT_M_OFFSET);+    rsa_ctx->e = bi_import(bi_ctx, pub_exp, pub_len);+    bi_permanent(rsa_ctx->e);+}++/**+ * Free up any RSA context resources.+ */+void RSA_free(RSA_CTX *rsa_ctx)+{+    BI_CTX *bi_ctx;+    if (rsa_ctx == NULL)                /* deal with ptrs that are null */+        return;++    bi_ctx = rsa_ctx->bi_ctx;++    bi_depermanent(rsa_ctx->e);+    bi_free(bi_ctx, rsa_ctx->e);+    bi_free_mod(rsa_ctx->bi_ctx, BIGINT_M_OFFSET);++    if (rsa_ctx->d)+    {+        bi_depermanent(rsa_ctx->d);+        bi_free(bi_ctx, rsa_ctx->d);+#ifdef CONFIG_BIGINT_CRT+        bi_depermanent(rsa_ctx->dP);+        bi_depermanent(rsa_ctx->dQ);+        bi_depermanent(rsa_ctx->qInv);+        bi_free(bi_ctx, rsa_ctx->dP);+        bi_free(bi_ctx, rsa_ctx->dQ);+        bi_free(bi_ctx, rsa_ctx->qInv);+        bi_free_mod(rsa_ctx->bi_ctx, BIGINT_P_OFFSET);+        bi_free_mod(rsa_ctx->bi_ctx, BIGINT_Q_OFFSET);+#endif+    }++    bi_terminate(bi_ctx);+    free(rsa_ctx);+}++/**+ * @brief Use PKCS1.5 for decryption/verification.+ * @param ctx [in] The context+ * @param in_data [in] The data to encrypt (must be < modulus size-11)+ * @param out_data [out] The encrypted data.+ * @param is_decryption [in] Decryption or verify operation.+ * @return  The number of bytes that were originally encrypted. -1 on error.+ * @see http://www.rsasecurity.com/rsalabs/node.asp?id=2125+ */+int RSA_decrypt(const RSA_CTX *ctx, const uint8_t *in_data, +                            uint8_t *out_data, int is_decryption)+{+    const int byte_size = ctx->num_octets;+    int i, size;+    bigint *decrypted_bi, *dat_bi;+    uint8_t *block = (uint8_t *)malloc(byte_size);++    memset(out_data, 0, byte_size); /* initialise */++    /* decrypt */+    dat_bi = bi_import(ctx->bi_ctx, in_data, byte_size);+#ifdef CONFIG_SSL_CERT_VERIFICATION+    decrypted_bi = is_decryption ?  /* decrypt or verify? */+            RSA_private(ctx, dat_bi) : RSA_public(ctx, dat_bi);+#else   /* always a decryption */+    decrypted_bi = RSA_private(ctx, dat_bi);+#endif++    /* convert to a normal block */+    bi_export(ctx->bi_ctx, decrypted_bi, block, byte_size);++    i = 10; /* start at the first possible non-padded byte */++#ifdef CONFIG_SSL_CERT_VERIFICATION+    if (is_decryption == 0) /* PKCS1.5 signing pads with "0xff"s */+    {+        while (block[i++] == 0xff && i < byte_size);++        if (block[i-2] != 0xff)+            i = byte_size;     /*ensure size is 0 */   +    }+    else                    /* PKCS1.5 encryption padding is random */+#endif+    {+        while (block[i++] && i < byte_size);+    }+    size = byte_size - i;++    /* get only the bit we want */+    if (size > 0)+        memcpy(out_data, &block[i], size);++    free(block);+    return size ? size : -1;+}++/**+ * Performs m = c^d mod n+ */+bigint *RSA_private(const RSA_CTX *c, bigint *bi_msg)+{+#ifdef CONFIG_BIGINT_CRT+    return bi_crt(c->bi_ctx, bi_msg, c->dP, c->dQ, c->p, c->q, c->qInv);+#else+    BI_CTX *ctx = c->bi_ctx;+    ctx->mod_offset = BIGINT_M_OFFSET;+    return bi_mod_power(ctx, bi_msg, c->d);+#endif+}++#ifdef CONFIG_SSL_FULL_MODE+/**+ * Used for diagnostics.+ */+void RSA_print(const RSA_CTX *rsa_ctx) +{+    if (rsa_ctx == NULL)+        return;++    printf("-----------------   RSA DEBUG   ----------------\n");+    printf("Size:\t%d\n", rsa_ctx->num_octets);+    bi_print("Modulus", rsa_ctx->m);+    bi_print("Public Key", rsa_ctx->e);+    bi_print("Private Key", rsa_ctx->d);+}+#endif++#if defined(CONFIG_SSL_CERT_VERIFICATION) || defined(CONFIG_SSL_GENERATE_X509_CERT)+/**+ * Performs c = m^e mod n+ */+bigint *RSA_public(const RSA_CTX * c, bigint *bi_msg)+{+    c->bi_ctx->mod_offset = BIGINT_M_OFFSET;+    return bi_mod_power(c->bi_ctx, bi_msg, c->e);+}++/**+ * Use PKCS1.5 for encryption/signing.+ * see http://www.rsasecurity.com/rsalabs/node.asp?id=2125+ */+int RSA_encrypt(const RSA_CTX *ctx, const uint8_t *in_data, uint16_t in_len, +        uint8_t *out_data, int is_signing)+{+    int byte_size = ctx->num_octets;+    int num_pads_needed = byte_size-in_len-3;+    bigint *dat_bi, *encrypt_bi;++    /* note: in_len+11 must be > byte_size */+    out_data[0] = 0;     /* ensure encryption block is < modulus */++    if (is_signing)+    {+        out_data[1] = 1;        /* PKCS1.5 signing pads with "0xff"'s */+        memset(&out_data[2], 0xff, num_pads_needed);+    }+    else /* randomize the encryption padding with non-zero bytes */   +    {+        out_data[1] = 2;+        // NOT USED - get_random_NZ(num_pads_needed, &out_data[2]);+    }++    out_data[2+num_pads_needed] = 0;+    memcpy(&out_data[3+num_pads_needed], in_data, in_len);++    /* now encrypt it */+    dat_bi = bi_import(ctx->bi_ctx, out_data, byte_size);+    encrypt_bi = is_signing ? RSA_private(ctx, dat_bi) : +                              RSA_public(ctx, dat_bi);+    bi_export(ctx->bi_ctx, encrypt_bi, out_data, byte_size);++    /* save a few bytes of memory */+    bi_clear_cache(ctx->bi_ctx);+    return byte_size;+}++#endif  /* CONFIG_SSL_CERT_VERIFICATION */
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ adb.cabal view
@@ -0,0 +1,43 @@+-- Initial adb.cabal generated by cabal init.  For further documentation, +-- see http://haskell.org/cabal/users-guide/++name:                adb+version:             0.1.0.0+synopsis:            Android Debug Bridge (ADB) protocol+-- description:         +license:             BSD3+license-file:        LICENSE+author:              Stephen Blackheath+maintainer:          adb.protocol.stephen@blacksapphire.com+-- copyright:           +category:            Network+build-type:          Simple+extra-source-files:  programs/generate-rsa-key.hs+                     programs/adb-shell.hs+                     Network/ADB/os_port.h+                     Network/ADB/crypto.h+                     Network/ADB/adb_auth_private_key.h+                     Network/ADB/adb_auth.h+                     Network/ADB/bigint_impl.h+                     Network/ADB/os_int.h+                     Network/ADB/adb.h+                     Network/ADB/bigint.h+cabal-version:       >=1.10++library+  exposed-modules:     Network.ADB.Transport,+                       Network.ADB.Client,+                       Network.ADB.Server,+                       Network.ADB.Socket+  other-modules:       Network.ADB.Common+  other-extensions:    ScopedTypeVariables, FlexibleContexts, OverloadedStrings, ForeignFunctionInterface, EmptyDataDecls+  build-depends:       base >=4.6 && <4.8,+                       mtl >=2.1 && <2.2,+                       bytestring >=0.10,+                       network >=2.4,+                       containers >=0.5,+                       cereal >=0.4+  c-sources:           Network/ADB/adb_auth.c+                       Network/ADB/bigint.c+                       Network/ADB/rsa.c+  default-language:    Haskell2010
+ programs/adb-shell.hs view
@@ -0,0 +1,148 @@+-- This program talks to a locally running Android Virtual Device, giving you a+-- shell.+{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}+import Control.Applicative+import Control.Concurrent+import Control.Exception+import Control.Monad.Error+import qualified Data.ByteString.Char8 as B+import Data.List+import Network.ADB.Client+import Network.ADB.Server+import Network.ADB.Socket+import Network.Socket+import Prelude hiding (read)+import qualified Prelude+import System.Environment+import System.Exit+import System.IO+import System.Posix.Terminal+import System.Posix.Types+++main = withSocketsDo $ do+    args <- getArgs+    let def_host = "localhost"+        def_port = "5555"+        def_uri = "shell:"+        (host, port, uri) = case args of+            [] -> (def_host, def_port, def_uri)+            [host] -> (host, def_port, def_uri)+            [host, port] -> (host, port, def_uri)+            (host:port:uri:_) -> (host, port, B.pack uri)+    putStrLn $ "  Usage is: adb-shell {host {port {uri}}}      (client connection)"+    putStrLn $ "            adb-shell --server port            (test server)"+    putStrLn $ "    where { } means 'optional'"+    putStrLn ""+    if host == "--server" then do+        let localAddresses = ["*"]   -- On Windows this should be ["", "localhost"]+        ais <- concat <$> forM localAddresses (\addr ->+            getAddrInfo (Just $ AddrInfo {+                addrFlags = [AI_PASSIVE],+                addrFamily = AF_UNSPEC,+                addrSocketType = Stream,+                addrProtocol = 0,+                addrAddress = SockAddrInet 0 0,+                addrCanonName = Nothing+              }) (Just addr) (Just port)+          )+        forM_ (nub ais) $ \ai -> do+            ss <- socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai)+            setSocketOption ss ReusePort 1+              `catch` \(exc :: IOException) ->+                return ()  -- ignore failure on Windows+            when (addrFamily ai == AF_INET6) $ setSocketOption ss IPv6Only 1+            bind ss (addrAddress ai)+            listen ss 50+            putStrLn $ "listening on port "++port++" and uri "++show uri+            _ <- forkIO $ forever $ do+                (s, _) <- accept ss+                _ <- forkIO $ do+                    let tra = socketTransport s+                    _ <- runErrorT $ withServerSession tra "device::" $ \ses -> do+                        withAccept ses $ \descriptor ->+                            if descriptor /= uri+                                then Nothing+                                else Just $ \tra -> do+                                    liftIO $ do+                                        hPutStrLn stdout "incoming connection started"+                                        hFlush stdout+                                    terminal tra+                    return ()+                  `finally` sClose s+                return ()+            return ()+        forever $ threadDelay 10000000+      else do+        putStrLn $ "connecting to "++host++":"++port++" and uri "++show uri+        putStrLn ""+        putStrLn "Default port 5555 is used by a local Android emulator:"+        putStrLn "  Make sure you enable USB debugging in your emulator, which you'll"+        putStrLn "  find under '{ } Developer options'"+        putStrLn "  press ctrl-D or 'exit' to quit"+        putStrLn ""+        let hints = defaultHints { addrSocketType = Stream }+        ais <- getAddrInfo (Just hints) (Just host) (Just port)+        mSocket <- foldM (\mSocket ai -> do+                case mSocket of+                    Nothing -> do+                        s <- socket (addrFamily ai) (addrSocketType ai) (addrProtocol ai)+                        do+                            connect s (addrAddress ai)+                            return (Just s)+                          `catch` \(exc :: IOException) -> do+                            sClose s+                            return Nothing+                    Just _ -> return mSocket+            ) Nothing ais+        case mSocket of+            Nothing -> do+                hPutStrLn stderr $ "failed to connect to "++host++":"++port+                exitFailure+            Just skt -> do+                let stra = socketTransport skt+                ee <- runErrorT $ do+                    withClientSession stra $ \ses -> do+                        --let uri = "tcp:5000"   -- Connect to a localhost socket on the Android device+                        withConnect ses uri $ \tra -> terminal tra+                case ee of+                    Left err -> putStrLn $ "FAILED: "++show err+                    Right () -> return ()++terminal :: Transport (ErrorT TransportError IO) -> ErrorT TransportError IO ()+terminal tra = do+    attrs <- liftIO $ do+        --hSetEcho stdin False+        hSetBuffering stdin NoBuffering+        attrs <- getTerminalAttributes (Fd 0)+        let attrs' = attrs `withoutMode` EnableEcho+                           `withoutMode` ProcessInput+                           `withoutMode` ProcessOutput+                           `withoutMode` MapCRtoLF+                           `withoutMode` IgnoreBreak+                           `withoutMode` IgnoreCR+                           `withoutMode` MapLFtoCR+                           `withoutMode` EchoLF+                           `withoutMode` ExtendedFunctions+                           `withoutMode` KeyboardInterrupts+        setTerminalAttributes (Fd 0) attrs' Immediately+        return attrs+    writeThr <- liftIO $ forkIO $ do+        runErrorT $ forever $ do+            l <- liftIO $ B.hGetSome stdin 1024+            write tra l+        return ()+    -- Need to lift and unlift to use finally, if we don't want to+    -- use some fancy package like 'exceptions' to do this for us.+    ee <- liftIO $ runErrorT (forever $ do+            x <- read tra 1024+            liftIO $ do+                B.hPutStr stdout x+                hFlush stdout+        ) `finally` do+            killThread writeThr+            setTerminalAttributes (Fd 0) attrs Immediately+    case ee of+        Left err -> throwError err+        Right () -> return ()+
+ programs/generate-rsa-key.hs view
@@ -0,0 +1,92 @@+-- Requires RSA package+--+-- Write the output of this program to Network/ADB/adb_auth_private_key.h+import Crypto.Random+import Codec.Crypto.RSA+import Data.Bits+import Data.Char+import Data.List+import Data.Maybe+import Numeric+import Data.Int+import Data.Word+++public_n :: PublicKey -> Integer+public_n k = extract "public_n = " (show k)++public_e :: PublicKey -> Integer+public_e k = extract "public_e = " (show k)++private_d :: PrivateKey -> Integer+private_d k = extract "private_d = " (show k)++extract :: String -> String -> Integer+extract n [] = error $ "can't extract "++show n+extract n h | n `isPrefixOf` h = read $ takeWhile isDigit (drop (length n) h)+extract n (_:h) = extract n h++main :: IO ()+main = do+    g <- newGenIO :: IO SystemRandom+    let (pub, priv, _) = generateKeyPair g 2048+    putStr $ dumpBigInt "public_n" (public_n pub)+    putStr $ dumpBigInt "public_e" (public_e pub)+    putStr $ dumpBigInt "private_d" (private_d priv)+    let rsaNumBytes = 256+        rsaNumWords = rsaNumBytes `div` 4+        r32 = 2^32+        r = 2 ^ (rsaNumWords * 32)+        rr = (r^2) `mod` public_n pub+        rem = public_n pub `mod` r32+        n0inv =+            let one = fromMaybe (error "no modular inverse") $ rem `modInv` r32+            in  fromIntegral (-one) .&. (2^32 - 1) :: Int32+    --putStrLn $ show rem ++ " -> " ++ show (rem `modInv` 32)+    putStr $ dumpRSAKey rsaNumWords n0inv (public_n pub) rr (public_e pub)++dumpRSAKey rsaNumWords n0inv n rr e =+    "const RSAPublicKey public_key = {\n" +++    "    "++show rsaNumWords++",\n" +++    "    "++show n0inv++",\n" +++    "    {"++(intercalate "," . map show . toWords $ n)++"},\n" +++    "    {"++(intercalate "," . map show . toWords $ rr)++"},\n" +++    "    "++show e++"\n"+++    "};\n"++toWords :: Integer -> [Int32]+toWords i = go i+  where+    go i | i == 0 = []+    go i = let (hi, lo) = i `divMod` (2^32)+           in  fromIntegral lo : go hi++-- Extended Euclidean algorithm.  Given non-negative a and b, return x, y and g+-- such that ax + by = g, where g = gcd(a,b).  Note that x or y may be negative.+gcdExt a 0 = (1, 0, a)+gcdExt a b = let (q, r) = a `quotRem` b+                 (s, t, g) = gcdExt b r+             in (t, s - q * t, g)+ +-- Given a and m, return Just x such that ax = 1 mod m.  If there is no such x+-- return Nothing.+modInv a m = let (i, _, g) = gcdExt a m+             in if g == 1 then Just (mkPos i) else Nothing+  where mkPos x = if x < 0 then x + m else x+ +dumpBigInt :: String -> Integer -> String+dumpBigInt name i =+    "const uint8_t "++name++"[] = {\n"+++    hex ++ "\n" +++    "};\n"+++    "const int "++name++"_length = "++show n++";\n\n" +  where+    bytes = toBytes i :: [Word8]+    n = length bytes+    hex = intercalate "," .+          map (\x -> "0x"++showHex x "") $ bytes+    toBytes i = reverse (go i)+      where+        go i | i == 0 = []+        go i = let (hi, lo) = i `divMod` 256+               in  fromIntegral lo : go hi