Fix IAX2 encryption (really, bug #4500 for reference)
authorMark Spencer <markster@digium.com>
Tue, 12 Jul 2005 14:46:20 +0000 (14:46 +0000)
committerMark Spencer <markster@digium.com>
Tue, 12 Jul 2005 14:46:20 +0000 (14:46 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6103 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c
channels/iax2-parser.c

index e01f02f..14ca240 100755 (executable)
@@ -3701,7 +3701,14 @@ static void build_enc_keys(const unsigned char *digest, aes_encrypt_ctx *ecx, ae
 
 static void memcpy_decrypt(unsigned char *dst, const unsigned char *src, int len, aes_decrypt_ctx *dcx)
 {
-/*     memcpy(dst, src, len); */
+#if 0
+       /* Debug with "fake encryption" */
+       int x;
+       if (len % 16)
+               ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
+       for (x=0;x<len;x++)
+               dst[x] = src[x] ^ 0xff;
+#else  
        unsigned char lastblock[16] = { 0 };
        int x;
        while(len > 0) {
@@ -3713,11 +3720,19 @@ static void memcpy_decrypt(unsigned char *dst, const unsigned char *src, int len
                src += 16;
                len -= 16;
        }
+#endif
 }
 
 static void memcpy_encrypt(unsigned char *dst, const unsigned char *src, int len, aes_encrypt_ctx *ecx)
 {
-/*     memcpy(dst, src, len); */
+#if 0
+       /* Debug with "fake encryption" */
+       int x;
+       if (len % 16)
+               ast_log(LOG_WARNING, "len should be multiple of 16, not %d!\n", len);
+       for (x=0;x<len;x++)
+               dst[x] = src[x] ^ 0xff;
+#else
        unsigned char curblock[16] = { 0 };
        int x;
        while(len > 0) {
@@ -3729,6 +3744,7 @@ static void memcpy_encrypt(unsigned char *dst, const unsigned char *src, int len
                src += 16;
                len -= 16;
        }
+#endif
 }
 
 static int decode_frame(aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, struct ast_frame *f, int *datalen)
@@ -3740,15 +3756,17 @@ static int decode_frame(aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, stru
                return -1;
        if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
                struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
-               if (option_debug)
-                       ast_log(LOG_DEBUG, "Decoding full frame with length %d\n", *datalen);
                if (*datalen < 16 + sizeof(struct ast_iax2_full_hdr))
                        return -1;
-               padding = 16 + (efh->encdata[15] & 0xf);
+               /* Decrypt */
+               memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr), dcx);
+
+               padding = 16 + (workspace[15] & 0xf);
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Decoding full frame with length %d (padding = %d) (15=%02x)\n", *datalen, padding, workspace[15]);
                if (*datalen < padding + sizeof(struct ast_iax2_full_hdr))
                        return -1;
-               /* Decrypt */
-               memcpy_decrypt(workspace, efh->encdata, *datalen, dcx);
+
                *datalen -= padding;
                memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
                f->frametype = fh->type;
@@ -3763,11 +3781,11 @@ static int decode_frame(aes_decrypt_ctx *dcx, struct ast_iax2_full_hdr *fh, stru
                        ast_log(LOG_DEBUG, "Decoding mini with length %d\n", *datalen);
                if (*datalen < 16 + sizeof(struct ast_iax2_mini_hdr))
                        return -1;
-               padding = 16 + (efh->encdata[15] & 0x0f);
+               /* Decrypt */
+               memcpy_decrypt(workspace, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), dcx);
+               padding = 16 + (workspace[15] & 0x0f);
                if (*datalen < padding + sizeof(struct ast_iax2_mini_hdr))
                        return -1;
-               /* Decrypt */
-               memcpy_decrypt(workspace, efh->encdata, *datalen, dcx);
                *datalen -= padding;
                memcpy(efh->encdata, workspace + padding, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
        }
@@ -3784,15 +3802,17 @@ static int encrypt_frame(aes_encrypt_ctx *ecx, struct ast_iax2_full_hdr *fh, uns
        if (ntohs(fh->scallno) & IAX_FLAG_FULL) {
                struct ast_iax2_full_enc_hdr *efh = (struct ast_iax2_full_enc_hdr *)fh;
                if (option_debug)
-                       ast_log(LOG_DEBUG, "Encoding full frame with length %d\n", *datalen);
+                       ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d\n", fh->type, fh->csub, *datalen);
                padding = 16 - ((*datalen - sizeof(struct ast_iax2_full_enc_hdr)) % 16);
                padding = 16 + (padding & 0xf);
                memcpy(workspace, poo, padding);
                memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_full_enc_hdr));
-               *datalen += padding;
                workspace[15] &= 0xf0;
                workspace[15] |= (padding & 0xf);
-               memcpy_encrypt(efh->encdata, workspace, *datalen, ecx);
+               if (option_debug)
+                       ast_log(LOG_DEBUG, "Encoding full frame %d/%d with length %d + %d padding (15=%02x)\n", fh->type, fh->csub, *datalen, padding, workspace[15]);
+               *datalen += padding;
+               memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_full_enc_hdr), ecx);
                if (*datalen >= 32 + sizeof(struct ast_iax2_full_enc_hdr))
                        memcpy(poo, workspace + *datalen - 32, 32);
        } else {
@@ -3801,12 +3821,12 @@ static int encrypt_frame(aes_encrypt_ctx *ecx, struct ast_iax2_full_hdr *fh, uns
                        ast_log(LOG_DEBUG, "Encoding mini frame with length %d\n", *datalen);
                padding = 16 - ((*datalen - sizeof(struct ast_iax2_mini_enc_hdr)) % 16);
                padding = 16 + (padding & 0xf);
-               memset(workspace, 0, padding);
+               memcpy(workspace, poo, padding);
                memcpy(workspace + padding, efh->encdata, *datalen - sizeof(struct ast_iax2_mini_enc_hdr));
                workspace[15] &= 0xf0;
                workspace[15] |= (padding & 0x0f);
                *datalen += padding;
-               memcpy_encrypt(efh->encdata, workspace, *datalen, ecx);
+               memcpy_encrypt(efh->encdata, workspace, *datalen - sizeof(struct ast_iax2_mini_enc_hdr), ecx);
                if (*datalen >= 32 + sizeof(struct ast_iax2_mini_enc_hdr))
                        memcpy(poo, workspace + *datalen - 32, 32);
        }
@@ -3955,6 +3975,12 @@ static int iax2_send(struct chan_iax2_pvt *pvt, struct ast_frame *f, unsigned in
                        pvt->svideoformat = f->subclass & ~0x1;
                if (ast_test_flag(pvt, IAX_ENCRYPTED)) {
                        if (ast_test_flag(pvt, IAX_KEYPOPULATED)) {
+                               if (iaxdebug) {
+                                       if (fr->transfer)
+                                               iax_showframe(fr, NULL, 2, &pvt->transfer, fr->datalen - sizeof(struct ast_iax2_full_hdr));
+                                       else
+                                               iax_showframe(fr, NULL, 2, &pvt->addr, fr->datalen - sizeof(struct ast_iax2_full_hdr));
+                               }
                                encrypt_frame(&pvt->ecx, fh, pvt->semirand, &fr->datalen);
                        } else
                                ast_log(LOG_WARNING, "Supposed to send packet encrypted, but no key?\n");
@@ -6359,7 +6385,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
                }
 #ifdef DEBUG_SUPPORT
                else if (iaxdebug)
-                       iax_showframe(NULL, fh, 1, &sin, res - sizeof(struct ast_iax2_full_hdr));
+                       iax_showframe(NULL, fh, 3, &sin, res - sizeof(struct ast_iax2_full_hdr));
 #endif
        }
 
index 1cd0f40..e11a57c 100755 (executable)
@@ -440,8 +440,23 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
        char subclass2[20];
        char *class;
        char *subclass;
+       char *dir;
        char tmp[256];
        char iabuf[INET_ADDRSTRLEN];
+       switch(rx) {
+       case 0:
+               dir = "Tx";
+               break;
+       case 2:
+               dir = "TE";
+               break;
+       case 3:
+               dir = "RD";
+               break;
+       default:
+               dir = "Rx";
+               break;
+       }
        if (f) {
                fh = f->data;
                snprintf(retries, (int)sizeof(retries), "%03d", f->retries);
@@ -485,7 +500,7 @@ void iax_showframe(struct iax_frame *f, struct ast_iax2_full_hdr *fhi, int rx, s
        }
 snprintf(tmp, (int)sizeof(tmp), 
 "%s-Frame Retry[%s] -- OSeqno: %3.3d ISeqno: %3.3d Type: %s Subclass: %s\n",
-       (rx ? "Rx" : "Tx"),
+       dir,
        retries, fh->oseqno, fh->iseqno, class, subclass);
        outputf(tmp);
 snprintf(tmp, (int)sizeof(tmp),