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) DWC_PRINTF(" ");
54 if (((i + 1) % 26) == 0) DWC_PRINTF("\n");
60 #define dh_dump(_x...) do {; } while(0)
63 /* Constant g value */
64 static __u32 dh_g[] = {
68 /* Constant p value */
69 static __u32 dh_p[] = {
70 0xFFFFFFFF, 0xFFFFFFFF, 0xA2DA0FC9, 0x34C26821, 0x8B62C6C4, 0xD11CDC80, 0x084E0229, 0x74CC678A,
71 0xA6BE0B02, 0x229B133B, 0x79084A51, 0xDD04348E, 0xB31995EF, 0x1B433ACD, 0x6D0A2B30, 0x37145FF2,
72 0x6D35E14F, 0x45C2516D, 0x76B585E4, 0xC67E5E62, 0xE9424CF4, 0x6BED37A6, 0xB65CFF0B, 0xEDB706F4,
73 0xFB6B38EE, 0xA59F895A, 0x11249FAE, 0xE61F4B7C, 0x51662849, 0x3D5BE4EC, 0xB87C00C2, 0x05BF63A1,
74 0x3648DA98, 0x9AD3551C, 0xA83F1669, 0x5FCF24FD, 0x235D6583, 0x96ADA3DC, 0x56F3621C, 0xBB528520,
75 0x0729D59E, 0x6D969670, 0x4E350C67, 0x0498BC4A, 0x086C74F1, 0x7C2118CA, 0x465E9032, 0x3BCE362E,
76 0x2C779EE3, 0x03860E18, 0xA283279B, 0x8FA207EC, 0xF05DC5B5, 0xC9524C6F, 0xF6CB2BDE, 0x18175895,
77 0x7C499539, 0xE56A95EA, 0x1826D215, 0x1005FA98, 0x5A8E7215, 0x2DC4AA8A, 0x0D1733AD, 0x337A5004,
78 0xAB2155A8, 0x64BA1CDF, 0x0485FBEC, 0x0AEFDB58, 0x5771EA8A, 0x7D0C065D, 0x850F97B3, 0xC7E4E1A6,
79 0x8CAEF5AB, 0xD73309DB, 0xE0948C1E, 0x9D61254A, 0x26D2E3CE, 0x6BEED21A, 0x06FA2FF1, 0x64088AD9,
80 0x730276D8, 0x646AC83E, 0x182B1F52, 0x0C207B17, 0x5717E1BB, 0x6C5D617A, 0xC0880977, 0xE246D9BA,
81 0xA04FE208, 0x31ABE574, 0xFC5BDB43, 0x8E10FDE0, 0x20D1824B, 0xCAD23AA9, 0xFFFFFFFF, 0xFFFFFFFF,
84 static void dh_swap_bytes(void *_in, void *_out, uint32_t len)
89 for (i=0; i<len; i++) {
94 /* Computes the modular exponentiation (num^exp % mod). num, exp, and mod are
95 * big endian numbers of size len, in bytes. Each len value must be a multiple
97 int dwc_dh_modpow(void *mem_ctx, void *num, uint32_t num_len,
98 void *exp, uint32_t exp_len,
99 void *mod, uint32_t mod_len,
102 /* modpow() takes little endian numbers. AM uses big-endian. This
103 * function swaps bytes of numbers before passing onto modpow. */
108 uint32_t *bignum_num = dwc_alloc(mem_ctx, num_len + 4);
109 uint32_t *bignum_exp = dwc_alloc(mem_ctx, exp_len + 4);
110 uint32_t *bignum_mod = dwc_alloc(mem_ctx, mod_len + 4);
112 dh_swap_bytes(num, &bignum_num[1], num_len);
113 bignum_num[0] = num_len / 4;
115 dh_swap_bytes(exp, &bignum_exp[1], exp_len);
116 bignum_exp[0] = exp_len / 4;
118 dh_swap_bytes(mod, &bignum_mod[1], mod_len);
119 bignum_mod[0] = mod_len / 4;
121 result = dwc_modpow(mem_ctx, bignum_num, bignum_exp, bignum_mod);
124 goto dh_modpow_nomem;
127 dh_swap_bytes(&result[1], out, result[0] * 4);
128 dwc_free(mem_ctx, result);
131 dwc_free(mem_ctx, bignum_num);
132 dwc_free(mem_ctx, bignum_exp);
133 dwc_free(mem_ctx, bignum_mod);
138 int dwc_dh_pk(void *mem_ctx, uint8_t nd, uint8_t *exp, uint8_t *pk, uint8_t *hash)
143 #ifndef DH_TEST_VECTORS
144 DWC_RANDOM_BYTES(exp, 32);
147 /* Compute the pkd */
148 if ((retval = dwc_dh_modpow(mem_ctx, dh_g, 4,
155 DWC_MEMCPY(&m3[0], pk, 384);
156 DWC_SHA256(m3, 385, hash);
158 dh_dump("PK", pk, 384);
159 dh_dump("SHA-256(M3)", hash, 32);
163 int dwc_dh_derive_keys(void *mem_ctx, uint8_t nd, uint8_t *pkh, uint8_t *pkd,
164 uint8_t *exp, int is_host,
165 char *dd, uint8_t *ck, uint8_t *kdk)
169 uint8_t sha_result[32];
171 uint8_t shared_secret[384];
184 if ((retval = dwc_dh_modpow(mem_ctx, pk, 384,
186 dh_p, 384, shared_secret))) {
189 dh_dump("Shared Secret", shared_secret, 384);
191 DWC_SHA256(shared_secret, 384, dhkey);
192 dh_dump("DHKEY", dhkey, 384);
194 DWC_MEMCPY(&mv[0], pkd, 384);
195 DWC_MEMCPY(&mv[384], pkh, 384);
196 DWC_MEMCPY(&mv[768], "displayed digest", 16);
197 dh_dump("MV", mv, 784);
199 DWC_SHA256(mv, 784, sha_result);
200 dh_dump("SHA-256(MV)", sha_result, 32);
201 dh_dump("First 32-bits of SHA-256(MV)", sha_result, 4);
203 dh_swap_bytes(sha_result, &vd, 4);
205 DWC_PRINTF("Vd (decimal) = %d\n", vd);
211 DWC_SPRINTF(dd, "%02d", vd);
215 DWC_SPRINTF(dd, "%03d", vd);
219 DWC_SPRINTF(dd, "%04d", vd);
223 DWC_PRINTF("Display Digits: %s\n", dd);
226 message = "connection key";
227 DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
228 dh_dump("HMAC(SHA-256, DHKey, connection key)", sha_result, 32);
229 DWC_MEMCPY(ck, sha_result, 16);
231 message = "key derivation key";
232 DWC_HMAC_SHA256(message, DWC_STRLEN(message), dhkey, 32, sha_result);
233 dh_dump("HMAC(SHA-256, DHKey, key derivation key)", sha_result, 32);
234 DWC_MEMCPY(kdk, sha_result, 32);
240 #ifdef DH_TEST_VECTORS
242 static __u8 dh_a[] = {
243 0x44, 0x00, 0x51, 0xd6,
244 0xf0, 0xb5, 0x5e, 0xa9,
245 0x67, 0xab, 0x31, 0xc6,
246 0x8a, 0x8b, 0x5e, 0x37,
247 0xd9, 0x10, 0xda, 0xe0,
248 0xe2, 0xd4, 0x59, 0xa4,
249 0x86, 0x45, 0x9c, 0xaa,
250 0xdf, 0x36, 0x75, 0x16,
253 static __u8 dh_b[] = {
254 0x5d, 0xae, 0xc7, 0x86,
255 0x79, 0x80, 0xa3, 0x24,
256 0x8c, 0xe3, 0x57, 0x8f,
257 0xc7, 0x5f, 0x1b, 0x0f,
258 0x2d, 0xf8, 0x9d, 0x30,
259 0x6f, 0xa4, 0x52, 0xcd,
260 0xe0, 0x7a, 0x04, 0x8a,
261 0xde, 0xd9, 0x26, 0x56,
264 void dwc_run_dh_test_vectors(void *mem_ctx)
274 DWC_PRINTF("\n\n\nDH_TEST_VECTORS\n\n");
276 /* compute the PKd and SHA-256(PKd || Nd) */
277 DWC_PRINTF("Computing PKd\n");
278 dwc_dh_pk(mem_ctx, 2, dh_a, pkd, hashd);
280 /* compute the PKd and SHA-256(PKh || Nd) */
281 DWC_PRINTF("Computing PKh\n");
282 dwc_dh_pk(mem_ctx, 2, dh_b, pkh, hashh);
284 /* compute the dhkey */
285 dwc_dh_derive_keys(mem_ctx, 2, pkh, pkd, dh_a, 0, dd, ck, kdk);
287 #endif /* DH_TEST_VECTORS */
289 #endif /* !CONFIG_MACH_IPMATE */
291 #endif /* DWC_CRYPTOLIB */