1 /* =========================================================================
2 * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_crypto.c $
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.
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.
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
35 * ========================================================================= */
38 * This file contains the WUSB cryptographic routines.
43 #include "dwc_crypto.h"
47 static inline void dump_bytes(char *name, uint8_t *bytes, int len)
50 DWC_PRINTF("%s: ", name);
51 for (i=0; i<len; i++) {
52 DWC_PRINTF("%02x ", bytes[i]);
57 #define dump_bytes(x...)
61 void show_block(const u8 *blk, const char *prefix, const char *suffix, int a)
63 #ifdef DWC_DEBUG_CRYPTO
66 DWC_DEBUG("%s", prefix);
73 for (i = 0; i < blksize; i++)
74 DWC_PRINT("%02x%s", *blk++, ((i & 3) == 3) ? " " : " ");
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
84 * @return 0 on success, negative error code on error.
86 int dwc_wusb_aes_encrypt(u8 *src, u8 *key, u8 *dst)
89 DWC_MEMSET(block_t, 0, 16);
91 return DWC_AES_CBC(src, 16, key, 16, block_t, dst);
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
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.
106 void dwc_wusb_cmf(u8 *key, u8 *nonce,
107 char *label, u8 *bytes, int len, u8 *result)
113 u16 la = (u16)(len + 14);
115 /* Set the AES-128 key */
116 //dwc_aes_setkey(tfm, key, 16);
118 /* Fill block B0 from flags = 0x59, N, and l(m) = 0 */
120 for (idx = 0; idx < 13; idx++)
121 block_m[idx + 1] = nonce[idx];
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);
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);
137 dwc_wusb_aes_encrypt(block_x, key, block_x);
138 show_block(block_x, "After AES: ", "b1\n", 16);
143 /* Fill remaining blocks with B */
145 block_x[idx] ^= *bytes++;
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);
155 /* Handle partial last block */
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);
162 /* Save the MIC tag */
163 DWC_MEMCPY(block_t, block_x, 8);
164 show_block(block_t, "MIC tag : ", NULL, 8);
166 /* Fill block A0 from flags = 0x01, N, and counter = 0 */
171 /* Encrypt the counter */
172 dwc_wusb_aes_encrypt(block_m, key, block_x);
173 show_block(block_x, "CTR[MIC] : ", NULL, 8);
175 /* XOR with MIC tag */
176 for (idx = 0; idx < 8; idx++) {
177 block_t[idx] ^= block_x[idx];
180 /* Return result to caller */
181 DWC_MEMCPY(result, block_t, 8);
182 show_block(result, "CCM-MIC : ", NULL, 8);
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.
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.
195 void dwc_wusb_prf(int prf_len, u8 *key,
196 u8 *nonce, char *label, u8 *bytes, int len, u8 *result)
201 for (i = 0; i < prf_len >> 6; i++, nonce[0]++) {
202 dwc_wusb_cmf(key, nonce, label, bytes, len, result);
208 * Fills in CCM Nonce per the WUSB spec.
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.
215 void dwc_wusb_fill_ccm_nonce(uint16_t haddr, uint16_t daddr, uint8_t *tkid,
219 DWC_DEBUG("%s %x %x\n", __func__, daddr, haddr);
221 DWC_MEMSET(&nonce[0], 0, 16);
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;
229 dump_bytes("CCM nonce", nonce, 16);
233 * Generates a 16-byte cryptographic-grade random number for the Host/Device
236 void dwc_wusb_gen_nonce(uint16_t addr, uint8_t *nonce)
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];
248 /* Collect "randomness samples" */
249 DWC_RANDOM_BYTES((uint8_t *)temp, 16);
251 dwc_wusb_prf_128((uint8_t *)temp, nonce,
252 "Random Numbers", (uint8_t *)temp, sizeof(temp),
257 * Generates the Session Key (PTK) and Key Confirmation Key (KCK) per the
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.
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)
273 dump_bytes("ck", mk, 16);
274 dump_bytes("hnonce", hnonce, 16);
275 dump_bytes("dnonce", dnonce, 16);
277 /* The data is the HNonce and DNonce concatenated */
278 DWC_MEMCPY(&idata[0], hnonce, 16);
279 DWC_MEMCPY(&idata[16], dnonce, 16);
281 dwc_wusb_prf_256(mk, ccm_nonce, "Pair-wise keys", idata, 32, odata);
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);
287 dump_bytes("kck", kck, 16);
288 dump_bytes("ptk", ptk, 16);
292 * Generates the Message Integrity Code over the Handshake data per the
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.
300 void dwc_wusb_gen_mic(uint8_t *ccm_nonce, uint8_t *kck,
301 uint8_t *data, uint8_t *mic)
304 dwc_wusb_prf_64(kck, ccm_nonce, "out-of-bandMIC",
305 data, WUSB_HANDSHAKE_LEN_FOR_MIC, mic);
308 #endif /* DWC_CRYPTOLIB */