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 +30/−0
- Network/ADB/Client.hs +114/−0
- Network/ADB/Common.hs +224/−0
- Network/ADB/Server.hs +60/−0
- Network/ADB/Socket.hs +34/−0
- Network/ADB/Transport.hs +44/−0
- Network/ADB/adb.h +43/−0
- Network/ADB/adb_auth.c +133/−0
- Network/ADB/adb_auth.h +26/−0
- Network/ADB/adb_auth_private_key.h +22/−0
- Network/ADB/bigint.c +1536/−0
- Network/ADB/bigint.h +97/−0
- Network/ADB/bigint_impl.h +126/−0
- Network/ADB/crypto.h +230/−0
- Network/ADB/os_int.h +56/−0
- Network/ADB/os_port.h +113/−0
- Network/ADB/rsa.c +279/−0
- Setup.hs +2/−0
- adb.cabal +43/−0
- programs/adb-shell.hs +148/−0
- programs/generate-rsa-key.hs +92/−0
+ 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