Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * A 32-bit implementation of the TEA algorithm
  3.  * Copyright (c) 2015 Vesselin Bontchev
  4.  *
  5.  * Loosely based on the implementation of David Wheeler and Roger Needham,
  6.  * https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm#Reference_code
  7.  *
  8.  * This file is part of FFmpeg.
  9.  *
  10.  * FFmpeg is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU Lesser General Public
  12.  * License as published by the Free Software Foundation; either
  13.  * version 2.1 of the License, or (at your option) any later version.
  14.  *
  15.  * FFmpeg is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.  * Lesser General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU Lesser General Public
  21.  * License along with FFmpeg; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23.  */
  24.  
  25. #include "avutil.h"
  26. #include "common.h"
  27. #include "intreadwrite.h"
  28. #include "tea.h"
  29.  
  30. typedef struct AVTEA {
  31.     uint32_t key[16];
  32.     int rounds;
  33. } AVTEA;
  34.  
  35. struct AVTEA *av_tea_alloc(void)
  36. {
  37.     return av_mallocz(sizeof(struct AVTEA));
  38. }
  39.  
  40. const int av_tea_size = sizeof(AVTEA);
  41.  
  42. void av_tea_init(AVTEA *ctx, const uint8_t key[16], int rounds)
  43. {
  44.     int i;
  45.  
  46.     for (i = 0; i < 4; i++)
  47.         ctx->key[i] = AV_RB32(key + (i << 2));
  48.  
  49.     ctx->rounds = rounds;
  50. }
  51.  
  52. static void tea_crypt_ecb(AVTEA *ctx, uint8_t *dst, const uint8_t *src,
  53.                           int decrypt, uint8_t *iv)
  54. {
  55.     uint32_t v0, v1;
  56.     int rounds = ctx->rounds;
  57.     uint32_t k0, k1, k2, k3;
  58.     k0 = ctx->key[0];
  59.     k1 = ctx->key[1];
  60.     k2 = ctx->key[2];
  61.     k3 = ctx->key[3];
  62.  
  63.     v0 = AV_RB32(src);
  64.     v1 = AV_RB32(src + 4);
  65.  
  66.     if (decrypt) {
  67.         int i;
  68.         uint32_t delta = 0x9E3779B9U, sum = delta * (rounds / 2);
  69.  
  70.         for (i = 0; i < rounds / 2; i++) {
  71.             v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
  72.             v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
  73.             sum -= delta;
  74.         }
  75.         if (iv) {
  76.             v0 ^= AV_RB32(iv);
  77.             v1 ^= AV_RB32(iv + 4);
  78.             memcpy(iv, src, 8);
  79.         }
  80.     } else {
  81.         int i;
  82.         uint32_t sum = 0, delta = 0x9E3779B9U;
  83.  
  84.         for (i = 0; i < rounds / 2; i++) {
  85.             sum += delta;
  86.             v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
  87.             v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
  88.         }
  89.     }
  90.  
  91.     AV_WB32(dst, v0);
  92.     AV_WB32(dst + 4, v1);
  93. }
  94.  
  95. void av_tea_crypt(AVTEA *ctx, uint8_t *dst, const uint8_t *src, int count,
  96.                   uint8_t *iv, int decrypt)
  97. {
  98.     int i;
  99.  
  100.     if (decrypt) {
  101.         while (count--) {
  102.             tea_crypt_ecb(ctx, dst, src, decrypt, iv);
  103.  
  104.             src   += 8;
  105.             dst   += 8;
  106.         }
  107.     } else {
  108.         while (count--) {
  109.             if (iv) {
  110.                 for (i = 0; i < 8; i++)
  111.                     dst[i] = src[i] ^ iv[i];
  112.                 tea_crypt_ecb(ctx, dst, dst, decrypt, NULL);
  113.                 memcpy(iv, dst, 8);
  114.             } else {
  115.                 tea_crypt_ecb(ctx, dst, src, decrypt, NULL);
  116.             }
  117.             src   += 8;
  118.             dst   += 8;
  119.         }
  120.     }
  121. }
  122.  
  123. #ifdef TEST
  124. #include <stdio.h>
  125.  
  126. #define TEA_NUM_TESTS 4
  127.  
  128. // https://github.com/logandrews/TeaCrypt/blob/master/tea/tea_test.go
  129. static const uint8_t tea_test_key[TEA_NUM_TESTS][16] = {
  130.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  131.       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  132.     },
  133.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  134.       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  135.     },
  136.     { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  137.       0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
  138.     },
  139.     { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  140.       0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
  141.     }
  142. };
  143.  
  144. static const uint8_t tea_test_pt[TEA_NUM_TESTS][8] = {
  145.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  146.     { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
  147.     { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 },
  148.     { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }
  149. };
  150.  
  151. static const uint8_t tea_test_ct[TEA_NUM_TESTS][8] = {
  152.     { 0x41, 0xEA, 0x3A, 0x0A, 0x94, 0xBA, 0xA9, 0x40 },
  153.     { 0x6A, 0x2F, 0x9C, 0xF3, 0xFC, 0xCF, 0x3C, 0x55 },
  154.     { 0xDE, 0xB1, 0xC0, 0xA2, 0x7E, 0x74, 0x5D, 0xB3 },
  155.     { 0x12, 0x6C, 0x6B, 0x92, 0xC0, 0x65, 0x3A, 0x3E }
  156. };
  157.  
  158. static void test_tea(AVTEA *ctx, uint8_t *dst, const uint8_t *src,
  159.                      const uint8_t *ref, int len, uint8_t *iv, int dir,
  160.                      const char *test)
  161. {
  162.     av_tea_crypt(ctx, dst, src, len, iv, dir);
  163.     if (memcmp(dst, ref, 8*len)) {
  164.         int i;
  165.         printf("%s failed\ngot      ", test);
  166.         for (i = 0; i < 8*len; i++)
  167.             printf("%02x ", dst[i]);
  168.         printf("\nexpected ");
  169.         for (i = 0; i < 8*len; i++)
  170.             printf("%02x ", ref[i]);
  171.         printf("\n");
  172.         exit(1);
  173.     }
  174. }
  175.  
  176. int main(void)
  177. {
  178.     AVTEA *ctx;
  179.     uint8_t buf[8], iv[8];
  180.     int i;
  181.     static const uint8_t src[32] = "HelloWorldHelloWorldHelloWorld";
  182.     uint8_t ct[32];
  183.     uint8_t pl[32];
  184.  
  185.     ctx = av_tea_alloc();
  186.     if (!ctx)
  187.         return 1;
  188.  
  189.     for (i = 0; i < TEA_NUM_TESTS; i++) {
  190.         av_tea_init(ctx, tea_test_key[i], 64);
  191.  
  192.         test_tea(ctx, buf, tea_test_pt[i], tea_test_ct[i], 1, NULL, 0, "encryption");
  193.         test_tea(ctx, buf, tea_test_ct[i], tea_test_pt[i], 1, NULL, 1, "decryption");
  194.  
  195.         /* encrypt */
  196.         memcpy(iv, "HALLO123", 8);
  197.         av_tea_crypt(ctx, ct, src, 4, iv, 0);
  198.  
  199.         /* decrypt into pl */
  200.         memcpy(iv, "HALLO123", 8);
  201.         test_tea(ctx, pl, ct, src, 4, iv, 1, "CBC decryption");
  202.  
  203.         memcpy(iv, "HALLO123", 8);
  204.         test_tea(ctx, ct, ct, src, 4, iv, 1, "CBC inplace decryption");
  205.     }
  206.  
  207.     printf("Test encryption/decryption success.\n");
  208.     av_free(ctx);
  209.  
  210.     return 0;
  211. }
  212.  
  213. #endif
  214.