rk: restore file mode
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / common_port / dwc_dh.c
1 /* =========================================================================
2  * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.c $
3  * $Revision: #3 $
4  * $Date: 2010/09/28 $
5  * $Change: 1596182 $
6  *
7  * Synopsys Portability Library Software and documentation
8  * (hereinafter, "Software") is an Unsupported proprietary work of
9  * Synopsys, Inc. unless otherwise expressly agreed to in writing
10  * between Synopsys and you.
11  *
12  * The Software IS NOT an item of Licensed Software or Licensed Product
13  * under any End User Software License Agreement or Agreement for
14  * Licensed Product with Synopsys or any supplement thereto. You are
15  * permitted to use and redistribute this Software in source and binary
16  * forms, with or without modification, provided that redistributions
17  * of source code must retain this notice. You may not view, use,
18  * disclose, copy or distribute this file or any information contained
19  * herein except pursuant to this license grant from Synopsys. If you
20  * do not agree with this notice, including the disclaimer below, then
21  * you are not authorized to use the Software.
22  *
23  * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
24  * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL
27  * SYNOPSYS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
31  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
33  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34  * DAMAGE.
35  * ========================================================================= */
36 #ifdef DWC_CRYPTOLIB
37
38 #ifndef CONFIG_MACH_IPMATE
39
40 #include "dwc_dh.h"
41 #include "dwc_modpow.h"
42
43 #ifdef DEBUG
44 /* This function prints out a buffer in the format described in the Association
45  * Model specification. */
46 static void dh_dump(char *str, void *_num, int len)
47 {
48         uint8_t *num = _num;
49         int i;
50         DWC_PRINTF("%s\n", str);
51         for (i = 0; i < len; i++) {
52                 DWC_PRINTF("%02x", num[i]);
53                 if (((i + 1) % 2) == 0)
54                         DWC_PRINTF(" ");
55                 if (((i + 1) % 26) == 0)
56                         DWC_PRINTF("\n");
57         }
58
59         DWC_PRINTF("\n");
60 }
61 #else
62 #define dh_dump(_x...) do {; } while (0)
63 #endif
64
65 /* Constant g value */
66 static __u32 dh_g[] = {
67         0x02000000,
68 };
69
70 /* Constant p value */
71 static __u32 dh_p[] = {
72         0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
73         0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
74         0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
75         0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
76         0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
77         0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
78         0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
79         0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
80         0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
81         0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
82         0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
83         0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
84 };
85
86 static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
87 {
88         uint8_t *in = _in;
89         uint8_t *out = _out;
90         int i;
91         for (i = 0; i < len; i++) {
92                 out[i] = in[len-1-i];
93         }
94 }
95
96 /* Computes the modular exponentiation (num^exp % mod).  num, exp, and mod are
97  * big endian numbers of size len, in bytes.  Each len value must be a multiple
98  * of 4. */
99 int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
100                   void *exp, uint32_t exp_len,
101                   void *mod, uint32_t mod_len,
102                   void *out)
103 {
104         /* modpow() takes little endian numbers.  AM uses big-endian.  This
105          * function swaps bytes of numbers before passing onto modpow. */
106
107         int retval = 0;
108         uint32_t *result;
109
110         uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
111         uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
112         uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
113
114         dh_swap_bytes(num, &bignum_num[1], num_len);
115         bignum_num[0] = num_len / 4;
116
117         dh_swap_bytes(exp, &bignum_exp[1], exp_len);
118         bignum_exp[0] = exp_len / 4;
119
120         dh_swap_bytes(mod, &bignum_mod[1], mod_len);
121         bignum_mod[0] = mod_len / 4;
122
123         result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
124         if (!result) {
125                 retval = -1;
126                 goto dh_modpow_nomem;
127         }
128
129         dh_swap_bytes(&result[1], out, result[0] * 4);
130         dwc_free(mem_ctx, result);
131
132  dh_modpow_nomem:
133         dwc_free(mem_ctx, bignum_num);
134         dwc_free(mem_ctx, bignum_exp);
135         dwc_free(mem_ctx, bignum_mod);
136         return retval;
137 }
138
139
140 int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
141 {
142         int retval;
143         uint8_t m3[385];
144
145 #ifndef DH_TEST_VECTORS
146         DWC_RANDOM_BYTES(exp, 32);
147 #endif
148
149         /* Compute the pkd */
150         retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
151                                exp, 32,
152                                dh_p, 384, pk);
153         if (retval) {
154                 return retval;
155         }
156
157         m3[384] = nd;
158         DWC_MEMCPY(&m3[0], pk, 384);
159         DWC_SHA256(m3, 385, hash);
160
161         dh_dump("PK", pk, 384);
162         dh_dump("SHA-256(M3)", hash, 32);
163         return 0;
164 }
165
166 int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
167                        uint8_t *exp, int is_host,
168                        char *dd, uint8_t *ck, uint8_t *kdk)
169 {
170         int retval;
171         uint8_t mv[784];
172         uint8_t sha_result[32];
173         uint8_t dhkey[384];
174         uint8_t shared_secret[384];
175         char *message;
176         uint32_t vd;
177
178         uint8_t *pk;
179
180         if (is_host) {
181                 pk = pkd;
182         } else {
183                 pk = pkh;
184         }
185
186         retval = dwc_dh_modpow(mem_ctx, pk, 384,
187                                exp, 32,
188                                dh_p, 384, shared_secret);
189         if (retval) {
190                 return retval;
191         }
192         dh_dump("Shared Secret", shared_secret, 384);
193
194         DWC_SHA256(shared_secret, 384, dhkey);
195         dh_dump("DHKEY", dhkey, 384);
196
197         DWC_MEMCPY(&mv[0], pkd, 384);
198         DWC_MEMCPY(&mv[384], pkh, 384);
199         DWC_MEMCPY(&mv[768], "displayed digest", 16);
200         dh_dump("MV", mv, 784);
201
202         DWC_SHA256(mv, 784, sha_result);
203         dh_dump("SHA-256(MV)", sha_result, 32);
204         dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
205
206         dh_swap_bytes(sha_result, &vd, 4);
207 #ifdef DEBUG
208         DWC_PRINTF("Vd (decimal) = %d\n", vd);
209 #endif
210
211         switch (nd) {
212         case 2:
213                 vd = vd % 100;
214                 DWC_SPRINTF(dd, "%02d", vd);
215                 break;
216         case 3:
217                 vd = vd % 1000;
218                 DWC_SPRINTF(dd, "%03d", vd);
219                 break;
220         case 4:
221                 vd = vd % 10000;
222                 DWC_SPRINTF(dd, "%04d", vd);
223                 break;
224         }
225 #ifdef DEBUG
226         DWC_PRINTF("Display Digits: %s\n", dd);
227 #endif
228
229         message = "connection key";
230         DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
231         dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
232         DWC_MEMCPY(ck, sha_result, 16);
233
234         message = "key derivation key";
235         DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
236         dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
237         DWC_MEMCPY(kdk, sha_result, 32);
238
239         return 0;
240 }
241
242
243 #ifdef DH_TEST_VECTORS
244
245 static __u8 dh_a[] = {
246         0x44, 0x00, 0x51, 0xd6,
247         0xf0, 0xb5, 0x5e, 0xa9,
248         0x67, 0xab, 0x31, 0xc6,
249         0x8a, 0x8b, 0x5e, 0x37,
250         0xd9, 0x10, 0xda, 0xe0,
251         0xe2, 0xd4, 0x59, 0xa4,
252         0x86, 0x45, 0x9c, 0xaa,
253         0xdf, 0x36, 0x75, 0x16,
254 };
255
256 static __u8 dh_b[] = {
257         0x5d, 0xae, 0xc7, 0x86,
258         0x79, 0x80, 0xa3, 0x24,
259         0x8c, 0xe3, 0x57, 0x8f,
260         0xc7, 0x5f, 0x1b, 0x0f,
261         0x2d, 0xf8, 0x9d, 0x30,
262         0x6f, 0xa4, 0x52, 0xcd,
263         0xe0, 0x7a, 0x04, 0x8a,
264         0xde, 0xd9, 0x26, 0x56,
265 };
266
267 void dwc_run_dh_test_vectors(void *mem_ctx)
268 {
269         uint8_t pkd[384];
270         uint8_t pkh[384];
271         uint8_t hashd[32];
272         uint8_t hashh[32];
273         uint8_t ck[16];
274         uint8_t kdk[32];
275         char dd[5];
276
277         DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
278
279         /* compute the PKd and SHA-256(PKd || Nd) */
280         DWC_PRINTF("Computing PKd\n");
281         dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
282
283         /* compute the PKd and SHA-256(PKh || Nd) */
284         DWC_PRINTF("Computing PKh\n");
285         dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
286
287         /* compute the dhkey */
288         dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
289 }
290 #endif /* DH_TEST_VECTORS */
291
292 #endif /* !CONFIG_MACH_IPMATE */
293
294 #endif /* DWC_CRYPTOLIB */