[rtmpdump] r439 - trunk/librtmp/handshake.h

hyc subversion at mplayerhq.hu
Tue Apr 20 14:21:22 CEST 2010


Author: hyc
Date: Tue Apr 20 14:21:21 2010
New Revision: 439

Log:
Fix digest offset computation, handshake versions

Modified:
   trunk/librtmp/handshake.h

Modified: trunk/librtmp/handshake.h
==============================================================================
--- trunk/librtmp/handshake.h	Tue Apr 20 03:12:37 2010	(r438)
+++ trunk/librtmp/handshake.h	Tue Apr 20 14:21:21 2010	(r439)
@@ -231,6 +231,9 @@ GetDigestOffset1(uint8_t *handshake, uns
   return res;
 }
 
+static getoff *digoff[] = {GetDigestOffset1, GetDigestOffset2};
+static getoff *dhoff[] = {GetDHOffset1, GetDHOffset2};
+
 static void
 HMACsha256(const uint8_t *message, size_t messageLen, const uint8_t *key,
 	   size_t keylen, uint8_t *digest)
@@ -334,7 +337,7 @@ static void rtmpe8_sig(uint8_t *in, uint
 static bool
 HandShake(RTMP * r, bool FP9HandShake)
 {
-  int i;
+  int i, offalg = 0;
   int dhposClient = 0;
   int digestPosClient = 0;
   bool encrypted = r->Link.protocol & RTMP_FEATURE_ENC;
@@ -348,7 +351,7 @@ HandShake(RTMP * r, bool FP9HandShake)
   uint8_t clientbuf[RTMP_SIG_SIZE + 4], *clientsig=clientbuf+4;
   uint8_t serversig[RTMP_SIG_SIZE], client2[RTMP_SIG_SIZE], *reply;
   uint8_t type;
-  getoff *getdh, *getdig;
+  getoff *getdh = NULL, *getdig = NULL;
 
   if (encrypted || r->Link.SWFSize)
     FP9HandShake = true;
@@ -358,7 +361,10 @@ HandShake(RTMP * r, bool FP9HandShake)
   r->Link.rc4keyIn = r->Link.rc4keyOut = 0;
 
   if (encrypted)
-    clientsig[-1] = 0x06;	/* 0x08 is RTMPE as well */
+    {
+      clientsig[-1] = 0x06;	/* 0x08 is RTMPE as well */
+      offalg = 1;
+    }
   else
     clientsig[-1] = 0x03;
 
@@ -369,15 +375,9 @@ HandShake(RTMP * r, bool FP9HandShake)
     {
       /* set version to at least 9.0.115.0 */
 #ifdef FP10
-      getdig = GetDigestOffset2;
-      getdh = GetDHOffset2;
-
       clientsig[4] = 128;
       clientsig[6] = 3;
 #else
-      getdig = GetDigestOffset1;
-      getdh = GetDHOffset1;
-
       clientsig[4] = 9;
       clientsig[6] = 124;
 #endif
@@ -385,6 +385,8 @@ HandShake(RTMP * r, bool FP9HandShake)
       clientsig[7] = 2;
 
       RTMP_Log(RTMP_LOGDEBUG, "%s: Client type: %02X", __FUNCTION__, clientsig[-1]);
+      getdig = digoff[offalg];
+      getdh  = dhoff[offalg];
     }
   else
     {
@@ -480,33 +482,27 @@ HandShake(RTMP * r, bool FP9HandShake)
 #endif
 
   if (FP9HandShake)
-  {
-    int dhposServer;
-    uint8_t digestResp[SHA256_DIGEST_LENGTH];
-    uint8_t *signatureResp = NULL;
+    {
+      uint8_t digestResp[SHA256_DIGEST_LENGTH];
+      uint8_t *signatureResp = NULL;
 
       /* we have to use this signature now to find the correct algorithms for getting the digest and DH positions */
-      int digestPosServer = GetDigestOffset2(serversig, RTMP_SIG_SIZE);
+      int digestPosServer = getdig(serversig, RTMP_SIG_SIZE);
 
       if (!VerifyDigest(digestPosServer, serversig, GenuineFMSKey, 36))
 	{
 	  RTMP_Log(RTMP_LOGWARNING, "Trying different position for server digest!");
-	  digestPosServer = GetDigestOffset1(serversig, RTMP_SIG_SIZE);
+	  offalg ^= 1;
+	  getdig = digoff[offalg];
+	  getdh  = dhoff[offalg];
+	  digestPosServer = getdig(serversig, RTMP_SIG_SIZE);
 
 	  if (!VerifyDigest(digestPosServer, serversig, GenuineFMSKey, 36))
 	    {
 	      RTMP_Log(RTMP_LOGERROR, "Couldn't verify the server digest");	/* continuing anyway will probably fail */
 	      return false;
 	    }
-	  dhposServer = GetDHOffset1(serversig, RTMP_SIG_SIZE);
 	}
-      else
-        {
-	  dhposServer = GetDHOffset2(serversig, RTMP_SIG_SIZE);
-        }
-
-      RTMP_Log(RTMP_LOGDEBUG, "%s: Server DH public key offset: %d", __FUNCTION__,
-	  dhposServer);
 
       /* generate SWFVerification token (SHA256 HMAC hash of decompressed SWF, key are the last 32 bytes of the server handshake) */
       if (r->Link.SWFSize)
@@ -528,10 +524,13 @@ HandShake(RTMP * r, bool FP9HandShake)
 	{
 	  /* compute secret key */
 	  uint8_t secretKey[128] = { 0 };
+	  int len, dhposServer;
 
-	  int len =
-	    DHComputeSharedSecretKey(r->Link.dh, &serversig[dhposServer], 128,
-				     secretKey);
+	  dhposServer = getdh(serversig, RTMP_SIG_SIZE);
+	  RTMP_Log(RTMP_LOGDEBUG, "%s: Server DH public key offset: %d", __FUNCTION__,
+	    dhposServer);
+	  len = DHComputeSharedSecretKey(r->Link.dh, &serversig[dhposServer],
+	  				128, secretKey);
 	  if (len < 0)
 	    {
 	      RTMP_Log(RTMP_LOGDEBUG, "%s: Wrong secret key position!", __FUNCTION__);
@@ -596,8 +595,10 @@ HandShake(RTMP * r, bool FP9HandShake)
   else
     {
       reply = serversig;
+#if 0
       uptime = htonl(RTMP_GetTime());
       memcpy(reply+4, &uptime, 4);
+#endif
     }
 
 #ifdef _DEBUG
@@ -713,8 +714,7 @@ HandShake(RTMP * r, bool FP9HandShake)
 static bool
 SHandShake(RTMP * r)
 {
-  int i;
-  int dhposClient = 0;
+  int i, offalg = 0;
   int dhposServer = 0;
   int digestPosServer = 0;
   RC4_handle keyIn = 0;
@@ -727,6 +727,7 @@ SHandShake(RTMP * r)
   uint8_t serverbuf[RTMP_SIG_SIZE + 4], *serversig = serverbuf+4;
   uint8_t type;
   uint32_t uptime;
+  getoff *getdh = NULL, *getdig = NULL;
 
   if (ReadN(r, (char *)&type, 1) != 1)	/* 0x03 or 0x06 */
     return false;
@@ -743,11 +744,12 @@ SHandShake(RTMP * r)
     }
   else if (type == 6 || type == 8)
     {
+      offalg = 1;
       encrypted = true;
       FP9HandShake = true;
       r->Link.protocol |= RTMP_FEATURE_ENC;
       /* use FP10 if client is capable */
-      if (clientsig[4] == 128 || clientsig[4] == -128)
+      if (clientsig[4] == 128)
 	type = 8;
     }
   else
@@ -757,6 +759,9 @@ SHandShake(RTMP * r)
       return false;
     }
 
+  if (!FP9HandShake && clientsig[4])
+    FP9HandShake = true;
+
   serversig[-1] = type;
 
   r->Link.rc4keyIn = r->Link.rc4keyOut = 0;
@@ -771,6 +776,9 @@ SHandShake(RTMP * r)
       serversig[5] = 5;
       serversig[6] = 1;
       serversig[7] = 1;
+
+      getdig = digoff[offalg];
+      getdh  = dhoff[offalg];
     }
   else
     {
@@ -800,7 +808,7 @@ SHandShake(RTMP * r)
 	      return false;
 	    }
 
-	  dhposServer = GetDHOffset2(serversig, RTMP_SIG_SIZE);
+	  dhposServer = getdh(serversig, RTMP_SIG_SIZE);
 	  RTMP_Log(RTMP_LOGDEBUG, "%s: DH pubkey position: %d", __FUNCTION__, dhposServer);
 
 	  if (!DHGenerateKey(r->Link.dh))
@@ -818,8 +826,8 @@ SHandShake(RTMP * r)
 	    }
 	}
 
-      digestPosServer = GetDigestOffset2(serversig, RTMP_SIG_SIZE);	/* reuse this value in verification */
-      RTMP_Log(RTMP_LOGDEBUG, "%s: Client digest offset: %d", __FUNCTION__,
+      digestPosServer = getdig(serversig, RTMP_SIG_SIZE);	/* reuse this value in verification */
+      RTMP_Log(RTMP_LOGDEBUG, "%s: Server digest offset: %d", __FUNCTION__,
 	  digestPosServer);
 
       CalculateDigest(digestPosServer, serversig, GenuineFMSKey, 36,
@@ -850,27 +858,23 @@ SHandShake(RTMP * r)
       uint8_t *signatureResp = NULL;
 
       /* we have to use this signature now to find the correct algorithms for getting the digest and DH positions */
-      int digestPosClient = GetDigestOffset1(clientsig, RTMP_SIG_SIZE);
+      int digestPosClient = getdig(clientsig, RTMP_SIG_SIZE);
 
       if (!VerifyDigest(digestPosClient, clientsig, GenuineFPKey, 30))
 	{
 	  RTMP_Log(RTMP_LOGWARNING, "Trying different position for client digest!");
-	  digestPosClient = GetDigestOffset2(clientsig, RTMP_SIG_SIZE);
+	  offalg ^= 1;
+	  getdig = digoff[offalg];
+	  getdh  = dhoff[offalg];
+
+	  digestPosClient = getdig(clientsig, RTMP_SIG_SIZE);
 
 	  if (!VerifyDigest(digestPosClient, clientsig, GenuineFPKey, 30))
 	    {
 	      RTMP_Log(RTMP_LOGERROR, "Couldn't verify the client digest");	/* continuing anyway will probably fail */
 	      return false;
 	    }
-	  dhposClient = GetDHOffset2(clientsig, RTMP_SIG_SIZE);
 	}
-      else
-        {
-	  dhposClient = GetDHOffset1(clientsig, RTMP_SIG_SIZE);
-        }
-
-      RTMP_Log(RTMP_LOGDEBUG, "%s: Client DH public key offset: %d", __FUNCTION__,
-	  dhposClient);
 
       /* generate SWFVerification token (SHA256 HMAC hash of decompressed SWF, key are the last 32 bytes of the server handshake) */
       if (r->Link.SWFSize)
@@ -890,10 +894,14 @@ SHandShake(RTMP * r)
       /* do Diffie-Hellmann Key exchange for encrypted RTMP */
       if (encrypted)
 	{
+	  int dhposClient, len;
 	  /* compute secret key */
 	  uint8_t secretKey[128] = { 0 };
 
-	  int len =
+	  dhposClient = getdh(clientsig, RTMP_SIG_SIZE);
+	  RTMP_Log(RTMP_LOGDEBUG, "%s: Client DH public key offset: %d", __FUNCTION__,
+	    dhposClient);
+	  len =
 	    DHComputeSharedSecretKey(r->Link.dh,
 				     (uint8_t *) &clientsig[dhposClient], 128,
 				     secretKey);
@@ -950,11 +958,13 @@ SHandShake(RTMP * r)
       RTMP_Log(RTMP_LOGDEBUG, "%s: Server signature calculated:", __FUNCTION__);
       RTMP_LogHex(RTMP_LOGDEBUG, signatureResp, SHA256_DIGEST_LENGTH);
     }
+#if 0
   else
     {
       uptime = htonl(RTMP_GetTime());
       memcpy(clientsig+4, &uptime, 4);
     }
+#endif
 
   RTMP_Log(RTMP_LOGDEBUG2, "%s: Sending handshake response: ",
     __FUNCTION__);


More information about the rtmpdump mailing list