1 /* =========================================================================
2 * $File: //dwh/usb_iip/dev/software/dwc_common_port_2/dwc_dh.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 #ifndef CONFIG_MACH_IPMATE
41 #include "dwc_modpow.h"
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)
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)
55 if (((i + 1) % 26) == 0)
62 #define dh_dump(_x...) do {; } while (0)
65 /* Constant g value */
66 static __u32 dh_g[] = {
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,
86 static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
91 for (i = 0; i < len; i++) {
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
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,
104 /* modpow() takes little endian numbers. AM uses big-endian. This
105 * function swaps bytes of numbers before passing onto modpow. */
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);
114 dh_swap_bytes(num, &bignum_num[1], num_len);
115 bignum_num[0] = num_len / 4;
117 dh_swap_bytes(exp, &bignum_exp[1], exp_len);
118 bignum_exp[0] = exp_len / 4;
120 dh_swap_bytes(mod, &bignum_mod[1], mod_len);
121 bignum_mod[0] = mod_len / 4;
123 result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
126 goto dh_modpow_nomem;
129 dh_swap_bytes(&result[1], out, result[0] * 4);
130 dwc_free(mem_ctx, result);
133 dwc_free(mem_ctx, bignum_num);
134 dwc_free(mem_ctx, bignum_exp);
135 dwc_free(mem_ctx, bignum_mod);
140 int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
145 #ifndef DH_TEST_VECTORS
146 DWC_RANDOM_BYTES(exp, 32);
149 /* Compute the pkd */
150 retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
158 DWC_MEMCPY(&m3[0], pk, 384);
159 DWC_SHA256(m3, 385, hash);
161 dh_dump("PK", pk, 384);
162 dh_dump("SHA-256(M3)", hash, 32);
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)
172 uint8_t sha_result[32];
174 uint8_t shared_secret[384];
186 retval = dwc_dh_modpow(mem_ctx, pk, 384,
188 dh_p, 384, shared_secret);
192 dh_dump("Shared Secret", shared_secret, 384);
194 DWC_SHA256(shared_secret, 384, dhkey);
195 dh_dump("DHKEY", dhkey, 384);
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);
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);
206 dh_swap_bytes(sha_result, &vd, 4);
208 DWC_PRINTF("Vd (decimal) = %d\n", vd);
214 DWC_SPRINTF(dd, "%02d", vd);
218 DWC_SPRINTF(dd, "%03d", vd);
222 DWC_SPRINTF(dd, "%04d", vd);
226 DWC_PRINTF("Display Digits: %s\n", dd);
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);
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);
243 #ifdef DH_TEST_VECTORS
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,
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,
267 void dwc_run_dh_test_vectors(void *mem_ctx)
277 DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
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);
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);
287 /* compute the dhkey */
288 dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
290 #endif /* DH_TEST_VECTORS */
292 #endif /* !CONFIG_MACH_IPMATE */
294 #endif /* DWC_CRYPTOLIB */