Merged revisions 182281 via svnmerge from
authorDavid Vossel <dvossel@digium.com>
Mon, 16 Mar 2009 17:49:58 +0000 (17:49 +0000)
committerDavid Vossel <dvossel@digium.com>
Mon, 16 Mar 2009 17:49:58 +0000 (17:49 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
  r182281 | dvossel | 2009-03-16 12:47:42 -0500 (Mon, 16 Mar 2009) | 7 lines

  Randomize IAX2 encryption padding

  The 16-32 byte random padding at the beginning of an encrypted IAX2 frame turns out to not be all that random at all.  This patch calls ast_random to fill the padding buffer with random data.  The padding is randomized at the beginning of every encrypted call and for every encrypted retransmit frame.

  Review: http://reviewboard.digium.com/r/193/
........

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182282 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c

index d8e0088..bda25b2 100644 (file)
@@ -1064,6 +1064,7 @@ static int acf_channel_write(struct ast_channel *chan, const char *function, cha
 static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen);
 static int encrypt_frame(ast_aes_encrypt_key *ecx, struct ast_iax2_full_hdr *fh, unsigned char *poo, int *datalen);
 static void build_ecx_key(const unsigned char *digest, struct chan_iax2_pvt *pvt);
+static void build_rand_pad(unsigned char *buf, ssize_t len);
 
 static const struct ast_channel_tech iax2_tech = {
        .type = "IAX2",
@@ -2547,6 +2548,9 @@ static int update_packet(struct iax_frame *f)
 
        /* Now re-encrypt the frame */
        if (f->encmethods) {
+       /* since this is a retransmit frame, create a new random padding
+        * before re-encrypting. */
+               build_rand_pad(f->semirand, sizeof(f->semirand));
                encrypt_frame(&f->ecx, fh, f->semirand, &f->datalen);
        }
        return 0;
@@ -4856,6 +4860,18 @@ static int iax2_trunk_queue(struct chan_iax2_pvt *pvt, struct iax_frame *fr)
        return 0;
 }
 
+/* IAX2 encryption requires 16 to 32 bytes of random padding to be present
+ * before the encryption data.  This function randomizes that data. */
+static void build_rand_pad(unsigned char *buf, ssize_t len)
+{
+       long tmp;
+       for (tmp = ast_random(); len > 0; tmp = ast_random()) {
+               memcpy(buf, (unsigned char *) &tmp, (len > sizeof(tmp)) ? sizeof(tmp) : len);
+               buf += sizeof(tmp);
+               len -= sizeof(tmp);
+       }
+}
+
 static void build_encryption_keys(const unsigned char *digest, struct chan_iax2_pvt *pvt)
 {
        build_ecx_key(digest, pvt);
@@ -4867,6 +4883,7 @@ static void build_ecx_key(const unsigned char *digest, struct chan_iax2_pvt *pvt
        /* it is required to hold the corresponding decrypt key to our encrypt key
         * in the pvt struct because queued frames occasionally need to be decrypted and
         * re-encrypted when updated for a retransmission */
+       build_rand_pad(pvt->semirand, sizeof(pvt->semirand));
        ast_aes_encrypt_key(digest, &pvt->ecx);
        ast_aes_decrypt_key(digest, &pvt->mydcx);
 }
@@ -4933,7 +4950,7 @@ static int decode_frame(ast_aes_decrypt_key *dcx, struct ast_iax2_full_hdr *fh,
                /* Decrypt */
                memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
 
-               padding = 16 + (workspace[15] & 0xf);
+               padding = 16 + (workspace[15] & 0x0f);
                if (iaxdebug)
                        ast_debug(1, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
                if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))