USB: support DWC_OTG Driver Version3.10 and used by default
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg_310 / common_port / dwc_crypto.c
1 /* =========================================================================
2  * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
3  * $Revision: #5 $
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
37 /** @file
38  * This file contains the WUSB cryptographic routines.
39  */
40
41 #ifdef DWC_CRYPTOLIB
42
43 #include "dwc_crypto.h"
44 #include "usb.h"
45
46 #ifdef DEBUG
47 static inline void dump_bytes(char *name, uint8_t *bytes, int len)
48 {
49         int i;
50         DWC_PRINTF("%s: ", name);
51         for (i=0; i<len; i++) {
52                 DWC_PRINTF("%02x ", bytes[i]);
53         }
54         DWC_PRINTF("\n");
55 }
56 #else
57 #define dump_bytes(x...)
58 #endif
59
60 /* Display a block */
61 void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
62 {
63 #ifdef DWC_DEBUG_CRYPTO
64         int i, blksize = 16;
65
66         DWC_DEBUG("%s", prefix);
67
68         if (suffix == NULL) {
69                 suffix = "\n";
70                 blksize = a;
71         }
72
73         for (i = 0; i < blksize; i++)
74                 DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? "  " : " ");
75         DWC_PRINT(suffix);
76 #endif
77 }
78
79 /**
80  * Encrypts an array of bytes using the AES encryption engine.
81  * If <code>dst</code> == <code>src</code>, then the bytes will be encrypted
82  * in-place.
83  *
84  * @return  0 on success, negative error code on error.
85  */
86 int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
87 {
88         u8 block_t[16];
89         DWC_MEMSET(block_t, 0, 16);
90
91         return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
92 }
93
94 /**
95  * The CCM-MAC-FUNCTION described in section 6.5 of the WUSB spec.
96  * This function takes a data string and returns the encrypted CBC
97  * Counter-mode MIC.
98  *
99  * @param key     The 128-bit symmetric key.
100  * @param nonce   The CCM nonce.
101  * @param label   The unique 14-byte ASCII text label.
102  * @param bytes   The byte array to be encrypted.
103  * @param len     Length of the byte array.
104  * @param result  Byte array to receive the 8-byte encrypted MIC.
105  */
106 void dwc_wusb_cmf(u8 *key, u8 *nonce,
107                   char *label, u8 *bytes, int len, u8 *result)
108 {
109         u8 block_m[16];
110         u8 block_x[16];
111         u8 block_t[8];
112         int idx, blkNum;
113         u16 la = (u16)(len + 14);
114
115         /* Set the AES-128 key */
116         //dwc_aes_setkey(tfm, key, 16);
117
118         /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
119         block_m[0] = 0x59;
120         for (idx = 0; idx < 13; idx++)
121                 block_m[idx + 1] = nonce[idx];
122         block_m[14] = 0;
123         block_m[15] = 0;
124
125         /* Produce the CBC IV */
126         dwc_wusb_aes_encrypt(block_m, key, block_x);
127         show_block(block_m, "CBC IV in: ", "\n", 0);
128         show_block(block_x, "CBC IV out:", "\n", 0);
129
130         /* Fill block B1 from l(a) = Blen + 14, and A */
131         block_x[0] ^= (u8)(la >> 8);
132         block_x[1] ^= (u8)la;
133         for (idx = 0; idx < 14; idx++)
134                 block_x[idx + 2] ^= label[idx];
135         show_block(block_x, "After xor: ", "b1\n", 16);
136
137         dwc_wusb_aes_encrypt(block_x, key, block_x);
138         show_block(block_x, "After AES: ", "b1\n", 16);
139
140         idx = 0;
141         blkNum = 0;
142
143         /* Fill remaining blocks with B */
144         while (len-- > 0) {
145                 block_x[idx] ^= *bytes++;
146                 if (++idx >= 16) {
147                         idx = 0;
148                         show_block(block_x, "After xor: ", "\n", blkNum);
149                         dwc_wusb_aes_encrypt(block_x, key, block_x);
150                         show_block(block_x, "After AES: ", "\n", blkNum);
151                         blkNum++;
152                 }
153         }
154
155         /* Handle partial last block */
156         if (idx > 0) {
157                 show_block(block_x, "After xor: ", "\n", blkNum);
158                 dwc_wusb_aes_encrypt(block_x, key, block_x);
159                 show_block(block_x, "After AES: ", "\n", blkNum);
160         }
161
162         /* Save the MIC tag */
163         DWC_MEMCPY(block_t, block_x, 8);
164         show_block(block_t, "MIC tag  : ", NULL, 8);
165
166         /* Fill block A0 from flags = 0x01, N, and counter = 0 */
167         block_m[0] = 0x01;
168         block_m[14] = 0;
169         block_m[15] = 0;
170
171         /* Encrypt the counter */
172         dwc_wusb_aes_encrypt(block_m, key, block_x);
173         show_block(block_x, "CTR[MIC] : ", NULL, 8);
174
175         /* XOR with MIC tag */
176         for (idx = 0; idx < 8; idx++) {
177                 block_t[idx] ^= block_x[idx];
178         }
179
180         /* Return result to caller */
181         DWC_MEMCPY(result, block_t, 8);
182         show_block(result, "CCM-MIC  : ", NULL, 8);
183
184 }
185
186 /**
187  * The PRF function described in section 6.5 of the WUSB spec. This function
188  * concatenates MIC values returned from dwc_cmf() to create a value of
189  * the requested length.
190  *
191  * @param prf_len  Length of the PRF function in bits (64, 128, or 256).
192  * @param key, nonce, label, bytes, len  Same as for dwc_cmf().
193  * @param result   Byte array to receive the result.
194  */
195 void dwc_wusb_prf(int prf_len, u8 *key,
196                   u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
197 {
198         int i;
199
200         nonce[0] = 0;
201         for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
202                 dwc_wusb_cmf(key, nonce, label, bytes, len, result);
203                 result += 8;
204         }
205 }
206
207 /**
208  * Fills in CCM Nonce per the WUSB spec.
209  *
210  * @param[in] haddr Host address.
211  * @param[in] daddr Device address.
212  * @param[in] tkid Session Key(PTK) identifier.
213  * @param[out] nonce Pointer to where the CCM Nonce output is to be written.
214  */
215 void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
216                              uint8_t *nonce)
217 {
218
219         DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
220
221         DWC_MEMSET(&nonce[0], 0, 16);
222
223         DWC_MEMCPY(&nonce[6], tkid, 3);
224         nonce[9] = daddr & 0xFF;
225         nonce[10] = (daddr >> 8) & 0xFF;
226         nonce[11] = haddr & 0xFF;
227         nonce[12] = (haddr >> 8) & 0xFF;
228
229         dump_bytes("CCM nonce", nonce, 16);
230 }
231
232 /**
233  * Generates a 16-byte cryptographic-grade random number for the Host/Device
234  * Nonce.
235  */
236 void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
237 {
238         uint8_t inonce[16];
239         uint32_t temp[4];
240
241         /* Fill in the Nonce */
242         DWC_MEMSET(&inonce[0], 0, sizeof(inonce));
243         inonce[9] = addr & 0xFF;
244         inonce[10] = (addr >> 8) & 0xFF;
245         inonce[11] = inonce[9];
246         inonce[12] = inonce[10];
247
248         /* Collect "randomness samples" */
249         DWC_RANDOM_BYTES((uint8_t *)temp, 16);
250
251         dwc_wusb_prf_128((uint8_t *)temp, nonce,
252                          "Random Numbers", (uint8_t *)temp, sizeof(temp),
253                          nonce);
254 }
255
256 /**
257  * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
258  * WUSB spec.
259  *
260  * @param[in] ccm_nonce Pointer to CCM Nonce.
261  * @param[in] mk Master Key to derive the session from
262  * @param[in] hnonce Pointer to Host Nonce.
263  * @param[in] dnonce Pointer to Device Nonce.
264  * @param[out] kck Pointer to where the KCK output is to be written.
265  * @param[out] ptk Pointer to where the PTK output is to be written.
266  */
267 void dwc_wusb_gen_key(uint8_t *ccm_nonce, uint8_t *mk, uint8_t *hnonce,
268                       uint8_t *dnonce, uint8_t *kck, uint8_t *ptk)
269 {
270         uint8_t idata[32];
271         uint8_t odata[32];
272
273         dump_bytes("ck", mk, 16);
274         dump_bytes("hnonce", hnonce, 16);
275         dump_bytes("dnonce", dnonce, 16);
276
277         /* The data is the HNonce and DNonce concatenated */
278         DWC_MEMCPY(&idata[0], hnonce, 16);
279         DWC_MEMCPY(&idata[16], dnonce, 16);
280
281         dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
282
283         /* Low 16 bytes of the result is the KCK, high 16 is the PTK */
284         DWC_MEMCPY(kck, &odata[0], 16);
285         DWC_MEMCPY(ptk, &odata[16], 16);
286
287         dump_bytes("kck", kck, 16);
288         dump_bytes("ptk", ptk, 16);
289 }
290
291 /**
292  * Generates the Message Integrity Code over the Handshake data per the
293  * WUSB spec.
294  *
295  * @param ccm_nonce Pointer to CCM Nonce.
296  * @param kck   Pointer to Key Confirmation Key.
297  * @param data  Pointer to Handshake data to be checked.
298  * @param mic   Pointer to where the MIC output is to be written.
299  */
300 void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
301                       uint8_t *data, uint8_t *mic)
302 {
303
304         dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
305                         data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
306 }
307
308 #endif  /* DWC_CRYPTOLIB */