1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner.
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works.
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @file kasumi.c
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Implementation of the 3GPP Kasumi block cipher
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Derived from the 3GPP standard source code
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h"
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_KASUMI
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projecttypedef unsigned u16;
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ROL16(x, y) ((((x)<<(y)) | ((x)>>(16-(y)))) & 0xFFFF)
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ltc_cipher_descriptor kasumi_desc = {
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   "kasumi",
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   21,
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   16, 16, 8, 8,
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &kasumi_setup,
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &kasumi_ecb_encrypt,
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &kasumi_ecb_decrypt,
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &kasumi_test,
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &kasumi_done,
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   &kasumi_keysize,
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic u16 FI( u16 in, u16 subkey )
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   u16 nine, seven;
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   static const u16 S7[128] = {
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      54, 50, 62, 56, 22, 34, 94, 96, 38, 6, 63, 93, 2, 18,123, 33,
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      55,113, 39,114, 21, 67, 65, 12, 47, 73, 46, 27, 25,111,124, 81,
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      53, 9,121, 79, 52, 60, 58, 48,101,127, 40,120,104, 70, 71, 43,
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      20,122, 72, 61, 23,109, 13,100, 77, 1, 16, 7, 82, 10,105, 98,
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      117,116, 76, 11, 89,106, 0,125,118, 99, 86, 69, 30, 57,126, 87,
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      112, 51, 17, 5, 95, 14, 90, 84, 91, 8, 35,103, 32, 97, 28, 66,
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      102, 31, 26, 45, 75, 4, 85, 92, 37, 74, 80, 49, 68, 29,115, 44,
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      64,107,108, 24,110, 83, 36, 78, 42, 19, 15, 41, 88,119, 59, 3 };
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  static const u16 S9[512] = {
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      167,239,161,379,391,334, 9,338, 38,226, 48,358,452,385, 90,397,
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      183,253,147,331,415,340, 51,362,306,500,262, 82,216,159,356,177,
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      175,241,489, 37,206, 17, 0,333, 44,254,378, 58,143,220, 81,400,
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       95, 3,315,245, 54,235,218,405,472,264,172,494,371,290,399, 76,
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      165,197,395,121,257,480,423,212,240, 28,462,176,406,507,288,223,
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      501,407,249,265, 89,186,221,428,164, 74,440,196,458,421,350,163,
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      232,158,134,354, 13,250,491,142,191, 69,193,425,152,227,366,135,
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      344,300,276,242,437,320,113,278, 11,243, 87,317, 36, 93,496, 27,
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      487,446,482, 41, 68,156,457,131,326,403,339, 20, 39,115,442,124,
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      475,384,508, 53,112,170,479,151,126,169, 73,268,279,321,168,364,
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      363,292, 46,499,393,327,324, 24,456,267,157,460,488,426,309,229,
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      439,506,208,271,349,401,434,236, 16,209,359, 52, 56,120,199,277,
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      465,416,252,287,246, 6, 83,305,420,345,153,502, 65, 61,244,282,
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      173,222,418, 67,386,368,261,101,476,291,195,430, 49, 79,166,330,
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      280,383,373,128,382,408,155,495,367,388,274,107,459,417, 62,454,
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      132,225,203,316,234, 14,301, 91,503,286,424,211,347,307,140,374,
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       35,103,125,427, 19,214,453,146,498,314,444,230,256,329,198,285,
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       50,116, 78,410, 10,205,510,171,231, 45,139,467, 29, 86,505, 32,
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       72, 26,342,150,313,490,431,238,411,325,149,473, 40,119,174,355,
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      185,233,389, 71,448,273,372, 55,110,178,322, 12,469,392,369,190,
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        1,109,375,137,181, 88, 75,308,260,484, 98,272,370,275,412,111,
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      336,318, 4,504,492,259,304, 77,337,435, 21,357,303,332,483, 18,
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       47, 85, 25,497,474,289,100,269,296,478,270,106, 31,104,433, 84,
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      414,486,394, 96, 99,154,511,148,413,361,409,255,162,215,302,201,
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      266,351,343,144,441,365,108,298,251, 34,182,509,138,210,335,133,
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      311,352,328,141,396,346,123,319,450,281,429,228,443,481, 92,404,
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      485,422,248,297, 23,213,130,466, 22,217,283, 70,294,360,419,127,
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      312,377, 7,468,194, 2,117,295,463,258,224,447,247,187, 80,398,
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      284,353,105,390,299,471,470,184, 57,200,348, 63,204,188, 33,451,
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       97, 30,310,219, 94,160,129,493, 64,179,263,102,189,207,114,402,
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      438,477,387,122,192, 42,381, 5,145,118,180,449,293,323,136,380,
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       43, 66, 60,455,341,445,202,432, 8,237, 15,376,436,464, 59,461};
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* The sixteen bit input is split into two unequal halves, *
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   * nine bits and seven bits - as is the subkey            */
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  nine  = (u16)(in>>7)&0x1FF;
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  seven = (u16)(in&0x7F);
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* Now run the various operations */
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  nine   = (u16)(S9[nine] ^ seven);
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  seven  = (u16)(S7[seven] ^ (nine & 0x7F));
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  seven ^= (subkey>>9);
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  nine  ^= (subkey&0x1FF);
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  nine   = (u16)(S9[nine] ^ seven);
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  seven  = (u16)(S7[seven] ^ (nine & 0x7F));
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  return (u16)(seven<<9) + nine;
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic ulong32 FO( ulong32 in, int round_no, symmetric_key *key)
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   u16 left, right;
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* Split the input into two 16-bit words */
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left = (u16)(in>>16);
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  right = (u16) in&0xFFFF;
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  /* Now apply the same basic transformation three times */
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left ^= key->kasumi.KOi1[round_no];
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left = FI( left, key->kasumi.KIi1[round_no] );
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left ^= right;
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  right ^= key->kasumi.KOi2[round_no];
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  right = FI( right, key->kasumi.KIi2[round_no] );
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  right ^= left;
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left ^= key->kasumi.KOi3[round_no];
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left = FI( left, key->kasumi.KIi3[round_no] );
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  left ^= right;
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  return (((ulong32)right)<<16)+left;
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic ulong32 FL( ulong32 in, int round_no, symmetric_key *key )
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    u16 l, r, a, b;
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* split out the left and right halves */
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    l = (u16)(in>>16);
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    r = (u16)(in)&0xFFFF;
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* do the FL() operations           */
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    a = (u16) (l & key->kasumi.KLi1[round_no]);
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    r ^= ROL16(a,1);
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    b = (u16)(r | key->kasumi.KLi2[round_no]);
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    l ^= ROL16(b,1);
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* put the two halves back together */
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return (((ulong32)l)<<16) + r;
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint kasumi_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 left, right, temp;
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int n;
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(pt   != NULL);
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(ct   != NULL);
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(skey != NULL);
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LOAD32H(left, pt);
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LOAD32H(right, pt+4);
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (n = 0; n <= 7; ) {
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FL(left,  n,   skey);
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FO(temp,  n++, skey);
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        right ^= temp;
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FO(right, n,   skey);
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FL(temp,  n++, skey);
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        left ^= temp;
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    STORE32H(left, ct);
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    STORE32H(right, ct+4);
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint kasumi_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 left, right, temp;
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int n;
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(pt   != NULL);
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(ct   != NULL);
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(skey != NULL);
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LOAD32H(left, ct);
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LOAD32H(right, ct+4);
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (n = 7; n >= 0; ) {
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FO(right, n,   skey);
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FL(temp,  n--, skey);
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        left ^= temp;
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FL(left,  n,   skey);
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        temp = FO(temp,  n--, skey);
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        right ^= temp;
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    STORE32H(left, pt);
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    STORE32H(right, pt+4);
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint kasumi_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    static const u16 C[8] = { 0x0123,0x4567,0x89AB,0xCDEF, 0xFEDC,0xBA98,0x7654,0x3210 };
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    u16 ukey[8], Kprime[8];
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int n;
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(key  != NULL);
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(skey != NULL);
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (keylen != 16) {
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return CRYPT_INVALID_KEYSIZE;
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (num_rounds != 0 && num_rounds != 8) {
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return CRYPT_INVALID_ROUNDS;
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Start by ensuring the subkeys are endian correct on a 16-bit basis */
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (n = 0; n < 8; n++ ) {
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        ukey[n] = (((u16)key[2*n]) << 8) | key[2*n+1];
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Now build the K'[] keys */
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (n = 0; n < 8; n++) {
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        Kprime[n] = ukey[n] ^ C[n];
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Finally construct the various sub keys */
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for(n = 0; n < 8; n++) {
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KLi1[n] = ROL16(ukey[n],1);
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KLi2[n] = Kprime[(n+2)&0x7];
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KOi1[n] = ROL16(ukey[(n+1)&0x7],5);
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KOi2[n] = ROL16(ukey[(n+5)&0x7],8);
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KOi3[n] = ROL16(ukey[(n+6)&0x7],13);
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KIi1[n] = Kprime[(n+4)&0x7];
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KIi2[n] = Kprime[(n+3)&0x7];
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        skey->kasumi.KIi3[n] = Kprime[(n+7)&0x7];
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid kasumi_done(symmetric_key *skey)
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint kasumi_keysize(int *keysize)
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(keysize != NULL);
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   if (*keysize >= 16) {
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      *keysize = 16;
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_OK;
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } else {
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      return CRYPT_INVALID_KEYSIZE;
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint kasumi_test(void)
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifndef LTC_TEST
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_NOP;
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   static const struct {
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project      unsigned char key[16], pt[8], ct[8];
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   } tests[] = {
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x4B, 0x58, 0xA7, 0x71, 0xAF, 0xC7, 0xE5, 0xE8 }
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project},
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x7E, 0xEF, 0x11, 0x3C, 0x95, 0xBB, 0x5A, 0x77 }
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project},
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x5F, 0x14, 0x06, 0x86, 0xD7, 0xAD, 0x5A, 0x39 },
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project},
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x2E, 0x14, 0x91, 0xCF, 0x70, 0xAA, 0x46, 0x5D }
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project},
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 },
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 0xB5, 0x45, 0x86, 0xF4, 0xAB, 0x9A, 0xE5, 0x46 }
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project},
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   unsigned char buf[2][8];
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   symmetric_key key;
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int err, x;
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = kasumi_setup(tests[x].key, 16, 0, &key)) != CRYPT_OK) {
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = kasumi_ecb_encrypt(tests[x].pt, buf[0], &key)) != CRYPT_OK) {
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if ((err = kasumi_ecb_decrypt(tests[x].ct, buf[1], &key)) != CRYPT_OK) {
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return err;
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       if (XMEMCMP(tests[x].pt, buf[1], 8) || XMEMCMP(tests[x].ct, buf[0], 8)) {
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          return CRYPT_FAIL_TESTVECTOR;
308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       }
309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   }
310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/ciphers/kasumi.c,v $ */
317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.7 $ */
318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/09 03:05:44 $ */
319