Hello Supraja, 2014-12-23 18:38 GMT+01:00 supraja reddy <supraja0...@gmail.com>: > I have attached the patch to the basic implementation of camellia block > cipher. Please let me know if there are any bugs to be fixed or if any > further optimization needed.
thanks for the patch and thank you Michael for the first review. My comments follow: > From 4ace69c4cc76f04e0e795e67290e979925df600c Mon Sep 17 00:00:00 2001 > From: Supraja Meedinti <supraja0...@gmail.com> > Date: Fri, 19 Dec 2014 20:02:29 +0530 > Subject: [PATCH] libavutil: added camellia block cipher > > Signed-off-by: Supraja Meedinti <supraja0...@gmail.com> > --- > libavutil/Makefile | 3 + > libavutil/camellia.c | 456 > +++++++++++++++++++++++++++++++++++++++++++++++++++ > libavutil/camellia.h | 68 ++++++++ > 3 files changed, 527 insertions(+) > create mode 100644 libavutil/camellia.c > create mode 100644 libavutil/camellia.h > > diff --git a/libavutil/Makefile b/libavutil/Makefile > index c1aa8aa..4db89b8 100644 > --- a/libavutil/Makefile > +++ b/libavutil/Makefile > @@ -16,6 +16,7 @@ HEADERS = adler32.h > \ > bswap.h \ > buffer.h \ > cast5.h \ > + camellia.h \ > channel_layout.h \ > common.h \ > cpu.h \ > @@ -84,6 +85,7 @@ OBJS = adler32.o > \ > bprint.o \ > buffer.o \ > cast5.o \ > + camellia.o \ > channel_layout.o \ > cpu.o \ > crc.o \ > @@ -154,6 +156,7 @@ TESTPROGS = adler32 > \ > blowfish \ > bprint \ > cast5 \ > + camellia \ > cpu \ > crc \ > des \ > diff --git a/libavutil/camellia.c b/libavutil/camellia.c > new file mode 100644 > index 0000000..6f0d859 > --- /dev/null > +++ b/libavutil/camellia.c > @@ -0,0 +1,456 @@ > +/* > + * An implementation of the CAMELLIA algorithm as mentioned in RFC3713 > + * Copyright (c) 2014 Supraja Meedinti > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > +#include "camellia.h" > +#include "common.h" > +#include "intreadwrite.h" > +#include "attributes.h" > + > +#define MASK8 0xff > +#define MASK32 0xffffffff > +#define MASK64 0xffffffffffffffff > + > +#define Sigma1 0xA09E667F3BCC908B > +#define Sigma2 0xB67AE8584CAA73B2 > +#define Sigma3 0xC6EF372FE94F82BE > +#define Sigma4 0x54FF53A5F1D36F1C > +#define Sigma5 0x10E527FADE682D1D > +#define Sigma6 0xB05688C2B3E6C1FD > + > +typedef struct AVCAMELLIA { > + uint64_t K[34]; > + int key_bits; > +} AVCAMELLIA; You are using a single array K for all the keys, without distinguishing between kw, k and ke as in the rfc. This makes code harder to read/maintain with no real gain I guess. Any reason why you made this decision? > + > +static void LROT(uint64_t *K, int x) > +{ > + uint64_t d[2]; > + if (x) > + return; Maybe if (!x) ? > + d[0] = (K[0] << x | K[1] >> (64 - x)); > + d[1] = (K[1] << x | K[0] >> (64 - x)); > + K[0] = d[0]; > + K[1] = d[1]; > +} > + > +static void swap(uint64_t *k1, uint64_t *k2) > +{ > + uint64_t temp; > + temp = *k1; > + *k1 = *k2; > + *k2 = temp; > +} > + > +static const uint8_t SBOX1[256] = > +{ > + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, > + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, > + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, > + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, > + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, > 153, > + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, > + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, > + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, > + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, > 210, > + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, > + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, > 226, > + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, > + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, > 89, > + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, > 250, > + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, > + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, > 158 > +}; Nit: it would be nice if the values were aligned, like this: 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, but if you decide to leave them as they are, I'm fine with it. > + > +static const uint8_t SBOX2[256] = > +{ > + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, > + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, > + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, > + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, > 154, > + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, > + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, > + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, > + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, > 160, > + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, > + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, > + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, > + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, > + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, > + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, > + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, > 73, > + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 > +}; > + > +static const uint8_t SBOX3[256] = > +{ > + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, > + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, > 222, > + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, > + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, > 166, > + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, > + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, > + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, > + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, > + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, > + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, > + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, > 113, > + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, > + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, > + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, > + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, > + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, > 79 > +}; > + > +static const uint8_t SBOX4[256] = > +{ > + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, > + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, > + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, > 4, > + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, > + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, > + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, > 99, > + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, > 141, > + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, > + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, > + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, > + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, > + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, > + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, > 148, > + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, > + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, > 250, > + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 > +}; > + > +const int av_camellia_size = sizeof(AVCAMELLIA); > + > +static uint64_t F(uint64_t f_in, uint64_t K) For consistency I would use F_IN and KE (or f_in and ke) like in the rfc. What do you think? > +{ > + uint32_t Zl, Zr; > + uint64_t x; You probably don't need x. > + Zl = (f_in >> 32) ^ (K >> 32); > + Zr = (f_in & MASK32) ^ (K & MASK32); > + Zl = ((SBOX1[(Zl >> 24) & MASK8] << 24) | (SBOX2[(Zl >> 16) & MASK8] << > 16) |(SBOX3[(Zl >> 8) & MASK8] << 8) |(SBOX4[Zl & MASK8])); > + Zr = ((SBOX2[(Zr >> 24) & MASK8] << 24) | (SBOX3[(Zr >> 16) & MASK8] << > 16) |(SBOX4[(Zr >> 8) & MASK8] << 8) |(SBOX1[Zr & MASK8])); > + Zl ^= ((Zr << 8) | (Zr >> 24)); > + Zr ^= ((Zl << 16) | (Zl >> 16)); > + Zl ^= ((Zr >> 8) | (Zr << 24)); > + Zr ^= ((Zl >> 8) | (Zl << 24)); This optimization is correct, just curious, where did you read about it? Also here and in other places: can we have two macros for left and right rotation on uint32? Something like: /* left rotation */ #define LR32(x, c) ((x) << (c) | (x) >> (32 - (c))) /* right rotation */ #define RR32(x, c) ((x) >> (c) | (x) << (32 - (c))) Also, it's up to you, but for clarity you could rename LROT to LR128 or something like that. > + x = Zr; > + return (x << 32) | Zl; return ((uint64_t)Zr << 32) | (uint64_t)Zl; > +} > + > +static uint64_t FL(uint64_t fl_in, uint64_t ke) > +{ > + uint64_t out; > + uint32_t x1,x2,k1,k2; Missing spaces after commas. > + x1 = fl_in >> 32; > + x2 = fl_in & MASK32; > + k1 = ke >> 32; > + k2 = ke & MASK32; > + x2 = x2 ^ ((x1 & k1) << 1 | (x1 & k1) >> 31); > + x1 = x1 ^ (x2 | k2); > + out = x1; > + return (out << 32) | x2; > +} > + > +static uint64_t FLINV(uint64_t flinv_in, uint64_t ke) > +{ > + uint32_t x1,x2,k1,k2; Missing spaces after commas. > + uint64_t out; > + x1 = flinv_in >> 32; > + x2 = flinv_in & MASK32; > + k1 = ke >> 32; > + k2 = ke & MASK32; > + x1 = x1 ^ (x2 | k2); > + x2 = x2 ^ ((x1 & k1) << 1 | (x1 & k1) >> 31); > + out = x1; > + return (out << 32) | x2; > +} > + > +static const int shift1[2][6] = { > + {0, 15, 30, 17, 17, 17}, > + {0, 15, 15, 15, 34, 17} > +}; > +static const int pos1[2][6] = { > + {0, 4, 10, 16, 18, 22}, > + {2, 6, 8, 14, 20, 24} > +}; > +static const int pos2[4][4]= { > + {0, 12, 16, 22}, > + {6, 14, 24, 28}, > + {2, 10, 20, 32}, > + {4, 8, 18, 26} > +}; > +static const int shift2[4][5]= { > + {0, 45, 15, 17}, > + {15, 30, 32, 17}, > + {0, 30, 30, 51}, > + {15, 15, 30, 34} > +}; > + > +static void generate_round_keys(AVCAMELLIA* cs, uint64_t *Ka, uint64_t *Kb, > uint64_t *Kl, uint64_t *Kr) > +{ > + int i; > + if (cs->key_bits == 128) { > + for (i = 0; i < 3; i++) { > + LROT(Kl, shift1[0][i]); > + cs->K[pos1[0][i]] = Kl[0]; > + cs->K[pos1[0][i]+1] = Kl[1]; > + > + LROT(Ka, shift1[1][i]); > + cs->K[pos1[1][i]] = Ka[0]; > + cs->K[pos1[1][i]+1] = Ka[1]; > + } > + LROT(Ka, 15); > + cs->K[12] = Ka[0]; > + LROT(Kl, 15); > + cs->K[13] = Kl[1]; > + for (i = 3; i < 6; i++) { > + LROT(Kl, shift1[0][i]); > + cs->K[pos1[0][i]] = Kl[0]; > + cs->K[pos1[0][i]+1] = Kl[1]; > + > + LROT(Ka, shift1[1][i]); > + cs->K[pos1[1][i]] = Ka[0]; > + cs->K[pos1[1][i]+1] = Ka[1]; > + } > + } else { > + for ( i = 0; i < 4; i++) { > + LROT(Kl, shift2[0][i]); > + cs->K[pos2[0][i]] = Kl[0]; > + cs->K[pos2[0][i]+1] = Kl[1]; > + > + LROT(Ka, shift2[1][i]); > + cs->K[pos2[1][i]] = Ka[0]; > + cs->K[pos2[1][i]+1] = Ka[1]; > + > + LROT(Kb, shift2[2][i]); > + cs->K[pos2[2][i]] = Kb[0]; > + cs->K[pos2[2][i]+1] = Kb[1]; > + > + LROT(Kr, shift2[3][i]); > + cs->K[pos2[3][i]] = Kr[0]; > + cs->K[pos2[3][i]+1] = Kr[1]; > + } > + LROT(Kl, 34); > + cs->K[30] = Kl[0]; > + cs->K[31] = Kl[1]; > + } Yes, I see what you did here... good for code compactness at the expense of code clarity. I'll let you know if I can think of a more elegant method to do this. > +} > + > +static void camellia_crypt(AVCAMELLIA* cs, uint8_t* dst, const uint8_t* src, > uint8_t* iv, int decrypt) > +{ > + uint64_t D1, D2; > + int i; > + D1 = AV_RB64(src); > + D2 = AV_RB64(src + 8); > + D1 = D1 ^ cs->K[0]; > + D2 = D2 ^ cs->K[1]; > + for (i = 2; i< 8; i += 2) { > + D2 = D2 ^ F(D1, cs->K[i]); > + D1 = D1 ^ F(D2, cs->K[i+1]); > + } > + D1 = FL(D1, cs->K[8]); > + D2 = FLINV(D2, cs->K[9]); > + for (i = 10; i < 16; i += 2) { > + D2 = D2 ^ F(D1, cs->K[i]); > + D1 = D1 ^ F(D2, cs->K[i+1]); > + } > + D1 = FL(D1, cs->K[16]); > + D2 = FLINV(D2, cs->K[17]); > + for (i = 18; i < 24 ; i += 2) { > + D2 = D2 ^ F(D1, cs->K[i]); > + D1 = D1 ^ F(D2, cs->K[i+1]); > + } > + if (cs->key_bits == 128) { > + D2 = D2 ^ cs->K[24]; > + D1 = D1 ^ cs->K[25]; > + } else { > + D1 = FL(D1, cs->K[24]); > + D2 = FLINV(D2, cs->K[25]); > + for (i = 26; i < 32; i += 2) { > + D2 = D2 ^ F(D1, cs->K[i]); > + D1 = D1 ^ F(D2, cs->K[i+1]); > + } > + D2 = D2 ^ cs->K[32]; > + D1 = D1 ^ cs->K[33]; > + } > + > + if (decrypt && iv) { > + D2 ^= AV_RB64(iv); > + D1 ^= AV_RB64(iv + 8); > + memcpy(iv, src, 8); > + } > + AV_WB64(dst, D2); > + AV_WB64(dst + 8, D1); Hmm, I'd say please remove the for loops and fully unroll this function. > +} > + > +struct AVCAMELLIA *av_camellia_alloc(void) > +{ > + return av_mallocz(sizeof(struct AVCAMELLIA)); > +} > + > +av_cold int av_camellia_init(AVCAMELLIA* cs, const uint8_t *key, int > key_bits) > +{ > + uint64_t Kl[2], Kr[2], Ka[2], Kb[2]; > + uint64_t D1, D2; > + if (key_bits != 128 && key_bits != 192 && key_bits != 256) > + return -1; > + memset(Kb, 0, sizeof(Kb)); > + memset(Kr, 0, sizeof(Kr)); > + cs->key_bits = key_bits; > + Kl[0] = AV_RB64(key); > + Kl[1] = AV_RB64(key+8); > + if (key_bits == 192) { > + Kr[0] = AV_RB64(key + 16); > + Kr[1] = ~Kr[0]; > + } else if (key_bits == 256) { > + Kr[0] = AV_RB64(key + 16); > + Kr[1] = AV_RB64(key + 24); > + } > + D1 = Kl[0] ^ Kr[0]; > + D2 = Kl[1] ^ Kr[1]; > + D2 = D2 ^ F(D1, Sigma1); > + D1 = D1 ^ F(D2, Sigma2); > + D1 = D1 ^ Kl[0]; > + D2 = D2 ^ Kl[1]; > + D2 = D2 ^ F(D1, Sigma3); > + D1 = D1 ^ F(D2, Sigma4); > + Ka[0] = D1; > + Ka[1] = D2; > + if (key_bits != 128) { > + D1 = Ka[0] ^ Kr[0]; > + D2 = Ka[1] ^ Kr[1]; > + D2 = D2 ^ F(D1, Sigma5); > + D1 = D1 ^ F(D2, Sigma6); > + Kb[0] = D1; > + Kb[1] = D2; > + } > + generate_round_keys(cs, Ka, Kb, Kl, Kr); > + return 0; > +} > + > +void av_camellia_crypt(AVCAMELLIA* cs, uint8_t* dst, const uint8_t* src, int > count, uint8_t *iv, int decrypt) > +{ > + int i; > + while (count--) { > + if (decrypt){ > + if (cs->key_bits == 128) { > + for (i = 2; i <= 12; i++) > + swap(&cs->K[i], &cs->K[25-i]); > + swap(&cs->K[0], &cs->K[24]); > + swap(&cs->K[1], &cs->K[25]); > + } else { > + for (i = 2; i <= 16; i++) > + swap(&cs->K[i], &cs->K[33-i]); > + swap(&cs->K[0], &cs->K[32]); > + swap(&cs->K[1], &cs->K[33]); > + } I think this, apart from being inefficient, cannot work: if you perform the decryption two times in sequence the keys get swapped twice, and that's not what you want. Do you agree? A possible solution: make a second function, static void camellia_decrypt(), and hardcode the proper key sequence to use. > + camellia_crypt(cs, dst, src, iv, decrypt); > + } else { > + if (iv) { > + for (i = 0; i < 16; i++) > + dst[i] = src[i] ^ iv[i]; > + camellia_crypt(cs, dst, dst, iv, decrypt); > + memcpy(iv, dst, 8); > + } else { > + camellia_crypt(cs, dst, src, iv, decrypt); > + } > + } > + src = src + 8; > + dst = dst + 8; > + } > +} I'll review everything from here to the end at the next iteration. > + > +#ifdef TEST > +#include<stdio.h> > +#include<stdlib.h> > +#include"log.h" > + > +int main(int argc, char** argv) > +{ > + > + const uint8_t Key[3][32] = { > + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, > 0x98, 0x76, 0x54, 0x32, 0x10}, > + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, > 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}, > + {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, > 0x98, 0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, > 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff} > + }; > + const uint8_t rpt[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, > 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}; > + const uint8_t rct[3][16] = { > + {0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, 0x08, 0x57, 0x06, > 0x56, 0x48, 0xea, 0xbe, 0x43}, > + {0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9,0x96, 0xf8, 0x4e, 0xe5, 0xce, > 0xe7, 0xd7, 0x9b, 0x09, 0xb9}, > + {0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, 0x20, 0xef, 0x7c, > 0x91, 0x9e, 0x3a, 0x75, 0x09} }; > + int i, err = 0; > + uint8_t temp[16]; > + AVCAMELLIA *cs; > + cs = av_camellia_alloc(); > + if (!cs) > + return 1; > + av_camellia_init(cs, Key[0], 128); > + av_camellia_crypt(cs, temp, rpt, 1, NULL, 0); > + for (i = 0; i < 16; i++) { > + if (rct[0][i] != temp[i]) { > + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[0][i], > temp[i]); > + err = 1; > + } > + } > + av_camellia_crypt(cs, temp, rct[0], 1, NULL, 1); > + for (i = 0; i < 16; i++) { > + if (rpt[i] != temp[i]) { > + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]); > + err = 1; > + } > + } > + av_camellia_init(cs, Key[1], 192); > + av_camellia_crypt(cs, temp, rpt, 1, NULL, 0); > + for (i = 0; i < 16; i++) { > + if (rct[1][i] != temp[i]) { > + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[1][i], > temp[i]); > + err = 1; > + } > + } > + av_camellia_crypt(cs, temp, rct[1], 1, NULL, 1); > + for (i = 0; i < 16; i++) { > + if (rpt[i] != temp[i]){ > + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]); > + err = 1; > + } > + } > + av_camellia_init(cs, Key[2], 256); > + av_camellia_crypt(cs, temp, rpt, 1, NULL, 0); > + for (i = 0; i < 16; i++) { > + if (rct[2][i] != temp[i]) { > + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[1][i], > temp[i]); > + err = 1; > + } > + } > + av_camellia_crypt(cs, temp, rct[2], 1, NULL, 1); > + for (i = 0; i < 16; i++) { > + if (rpt[i] != temp[i]) { > + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rpt[i], temp[i]); > + err = 1; > + } > + } > + > + > + av_free(cs); > + return err; > +} > +#endif > diff --git a/libavutil/camellia.h b/libavutil/camellia.h > new file mode 100644 > index 0000000..41076d4 > --- /dev/null > +++ b/libavutil/camellia.h > @@ -0,0 +1,68 @@ > +/* > + * An implementation of the CAMELLIA algorithm as mentioned in RFC3713 > + * Copyright (c) 2014 Supraja Meedinti > + * > + * This file is part of FFmpeg. > + * > + * FFmpeg is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2.1 of the License, or (at your option) any later version. > + * > + * FFmpeg is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with FFmpeg; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > + */ > + > +#ifndef AVUTIL_CAMELLIA_H > +#define AVUTIL_CAMELLIA_H > + > +#include <stdint.h> > + > + > +/** > + * @file > + * @brief Public header for libavutil CAMELLIA algorithm > + * @defgroup lavu_camellia CAMELLIA > + * @ingroup lavu_crypto > + * @{ > + */ > + > +extern const int av_camellia_size; > + > +struct AVCAMELLIA; > + > +/** > + * Allocate an AVCAMELLIA context > + * To free the struct: av_free(ptr) > + */ > +struct AVCAMELLIA *av_camellia_alloc(void); > +/** > + * Initialize an AVCAMELLIA context. > + * > + * @param ctx an AVCAMELLIA context > + * @param key a key of 16, 24, 32 bytes used for encryption/decryption > + * @param key_bits number of keybits: possible are 128, 192, 256 > + */ > +int av_camellia_init(struct AVCAMELLIA *ctx, const uint8_t *key, int > key_bits); > + > +/** > + * Encrypt or decrypt a buffer using a previously initialized context > + * > + * @param ctx an AVCAMELLIA context > + * @param dst destination array, can be equal to src > + * @param src source array, can be equal to dst > + * @param count number of 8 byte blocks > + * @paran iv initialization vector for CBC mode, NULL for ECB mode > + * @param decrypt 0 for encryption, 1 for decryption > + */ > +void av_camellia_crypt(struct AVCAMELLIA *ctx, uint8_t *dst, const uint8_t > *src, int count, uint8_t* iv, int decrypt); > +/** > + * @} > + */ > +#endif /* AVUTIL_CAMELLIA_H */ > -- > 1.8.3.2 > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel