blob: c0016416f6fa4a34eda86be5d22ff803663c3aae [file] [log] [blame]
anjana_sreekumar@infosys.com991c2062020-01-08 11:42:57 +05301#include <stdio.h>
2#include <math.h>
3#include <string.h>
4
5#include "f9.h"
6
7/* The code has been referred from
8 * 1.https://www.gsma.com/aboutus/wp-content/uploads/2014/12/uea2uia2d1v21.pdf
9 * 2.https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf
10 *
11 */
12
13
14/* MUL64x.
15 * Input V: a 64-bit input.
16 * Input c: a 64-bit input.
17 * Output : a 64-bit output.
18 * A 64-bit memory is allocated which is to be freed by the calling
19 * function.
20 * See section 4.3.2
21 * (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf)
22 * for more details.
23 */
24
25
26u64 MUL64x(u64 V, u64 c)
27{
28 if ( V & 0x8000000000000000 )
29 return (V << 1) ^ c;
30 else
31 return V << 1;
32}
33
34/* MUL64xPOW.
35 * Input V: a 64-bit input.
36 * Input i: a positive integer.
37 * Input c: a 64-bit input.
38 * Output : a 64-bit output.
39 * A 64-bit memory is allocated which is to be freed by the calling
40 function.
41 * See section 4.3.3
42 * (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf)
43 * for more details.
44 */
45
46u64 MUL64xPOW(u64 V, u8 i, u64 c)
47{
48 if ( i == 0)
49 return V;
50 else
51 return MUL64x( MUL64xPOW(V,i-1,c) , c);
52
53 return V;
54}
55
56/* MUL64.
57 * Input V: a 64-bit input.
58 * Input P: a 64-bit input.
59 * Input c: a 64-bit input.
60 * Output : a 64-bit output.
61 * A 64-bit memory is allocated which is to be freed by the calling
62 * function.
63 * See section 4.3.4
64 * (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf)
65 * for more details.
66 */
67
68
69u64 MUL64(u64 V, u64 P, u64 c)
70{
71 u64 result = 0;
72 int i = 0;
73 for ( i=0; i<64; i++)
74 {
75 if( ( P>>i ) & 0x1 )
76 result ^= MUL64xPOW(V,i,c);
77 }
78
79 return result;
80}
81
82
83/* mask8bit.
84 * Input n: an integer in 1-7.
85 * Output : an 8 bit mask.
86 * Prepares an 8 bit mask with required number of 1 bits on the MSB side.
87 */
88
89u8 mask8bit(int n)
90{
91 return 0xFF ^ ((1<<(8-n)) - 1);
92}
93
94/* f9.
95 * Input key: 128 bit Integrity Key.
96 * Input count:32-bit Count, Frame dependent input.
97 * Input fresh: 32-bit Random number.
98 * Input dir:1 bit, direction of transmission (in the LSB).
99 * Input data: length number of bits, input bit stream.
100 * Input length: 64 bit Length, i.e., the number of bits to be MAC'd.
101 * Output : 32 bit block used as MAC
102 * Generates 32-bit MAC using UIA2 algorithm as defined in Section 4.
103 */
104
105u8* f9( u8* key, u32 count, u32 fresh, u32 dir, u8 *data, u64 length)
106{
107 u32 K[4],IV[4], z[5];
108 u32 i=0,D;
109 static u8 MAC_I[4] = {0,0,0,0}; /* static memory for the result */
110 u64 EVAL;
111 u64 V;
112 u64 P;
113 u64 Q;
114 u64 c;
115 u64 M_D_2;
116 int rem_bits = 0;
117
118 /* Load the Integrity Key for SNOW3G initialization as in section 4.4. */
119
120 for (i=0; i<4; i++)
121 K[3-i] = (key[4*i] << 24) ^ (key[4*i+1] << 16) ^ (key[4*i+2] << 8) ^
122 (key[4*i+3]);
123
124
125 /* Prepare the Initialization Vector (IV) for SNOW3G initialization as in
126 section 4.4 of
127 (https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf).
128 */
129
130 IV[3] = count;
131 IV[2] = fresh;
132 IV[1] = count ^ ( dir << 31 ) ;
133 IV[0] = fresh ^ (dir << 15);
134 z[0] = z[1] = z[2] = z[3] = z[4] = 0;
135
136 /* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */
137
138 Initialize(K,IV);
139 GenerateKeystream(5,z);
140
141 P = (u64)z[0] << 32 | (u64)z[1];
142 Q = (u64)z[2] << 32 | (u64)z[3];
143
144 /* Calculation */
145
146 if ((length % 64) == 0)
147 D = (length>>6) + 1;
148 else
149 D = (length>>6) + 2;
150
151 EVAL = 0;
152 c = 0x1b;
153
154 /* for 0 <= i <= D-3 */
155
156 for (i=0;i<D-2;i++)
157 {
158 V = EVAL ^ ( (u64)data[8*i ]<<56 | (u64)data[8*i+1]<<48 |
159 (u64)data[8*i+2]<<40 | (u64)data[8*i+3]<<32 |
160 (u64)data[8*i+4]<<24 | (u64)data[8*i+5]<<16 |
161 (u64)data[8*i+6]<< 8 | (u64)data[8*i+7] );
162
163 EVAL = MUL64(V,P,c);
164 }
165
166 /* for D-2 */
167
168 rem_bits = length % 64;
169 if (rem_bits == 0)
170 rem_bits = 64;
171
172 M_D_2 = 0;
173 i = 0;
174
175 while (rem_bits > 7)
176 {
177 M_D_2 |= (u64)data[8*(D-2)+i] << (8*(7-i));
178 rem_bits -= 8;
179 i++;
180 }
181
182 if (rem_bits > 0)
183 M_D_2 |= (u64)(data[8*(D-2)+i] & mask8bit(rem_bits)) << (8*(7-i));
184
185 V = EVAL ^ M_D_2;
186 EVAL = MUL64(V,P,c);
187
188 /* for D-1 */
189
190 EVAL ^= length;
191
192 /* Multiply by Q */
193
194 EVAL = MUL64(EVAL,Q,c);
195
196 for (i=0; i<4; i++) {
197
198 /* GSLab-Intel modification to the specs reference code
199 * https://www.gsma.com/aboutus/wp-content/uploads/2014/12/uea2uia2d1v21.pdf
200 * which forgot to XOR z[5]
201 */
202
203 MAC_I[i] = ((EVAL >> (8 * (7-i))) ^ (z[4] >> (8 * (3-i)))) & 0xff;
204
205 }
206 return MAC_I;
207
208}
209/* End of f9.c */
210/*------------------------------------------------------------------------*/