1/*
2 * Function: hmac_md5
3 * From rfc2104.txt
4 *
5 * $Id: hmac.c 241182 2011-02-17 21:50:03Z $
6 */
7
8/*
9 *   Copyright (C) The Internet Society (2001).  All Rights Reserved.
10 *
11 *   This document and translations of it may be copied and furnished to
12 *   others, and derivative works that comment on or otherwise explain it
13 *   or assist in its implementation may be prepared, copied, published
14 *   and distributed, in whole or in part, without restriction of any
15 *   kind, provided that the above copyright notice and this paragraph are
16 *   included on all such copies and derivative works.  However, this
17 *   document itself may not be modified in any way, such as by removing
18 *   the copyright notice or references to the Internet Society or other
19 *   Internet organizations, except as needed for the purpose of
20 *   developing Internet standards in which case the procedures for
21 *   copyrights defined in the Internet Standards process must be
22 *   followed, or as required to translate it into languages other than
23 *   English.
24 *
25 *   The limited permissions granted above are perpetual and will not be
26 *   revoked by the Internet Society or its successors or assigns.
27 *
28 *   This document and the information contained herein is provided on an
29 *   "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
30 *   TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
31 *   BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
32 *   HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
33 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
34 *
35 * Copyright (C) 2015, Broadcom Corporation
36 * All Rights Reserved.
37 *
38 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
39 * the contents of this file may not be disclosed to third parties, copied
40 * or duplicated in any form, in whole or in part, without the prior
41 * written permission of Broadcom Corporation.
42 *
43 * $Id: hmac.c 241182 2011-02-17 21:50:03Z $
44 */
45
46
47#include <bcmcrypto/md5.h>
48
49#ifdef BCMDRIVER
50#include <osl.h>
51#else
52#include <string.h>
53#endif	/* BCMDRIVER */
54
55#if defined(BCMDRIVER) && defined(HNDRTE) && !defined(BCMSUP_PSK)
56#error "BCMSUP_PSK or BCMCCX must be defined to compile hmac.c for driver!"
57#endif
58
59extern void BCMROMFN(hmac_md5)(unsigned char *text, int text_len, unsigned char *key,
60                               int key_len, unsigned char *digest);
61
62/* text		pointer to data stream */
63/* text_len	length of data stream */
64/* key		pointer to authentication key */
65/* key_len	length of authentication key */
66/* digest	caller digest to be filled in */
67void
68BCMROMFN(hmac_md5)(unsigned char *text, int text_len, unsigned char *key,
69                   int key_len, unsigned char *digest)
70{
71	MD5_CTX context;
72	unsigned char k_ipad[65];    /* inner padding -
73				      * key XORd with ipad
74				      */
75	unsigned char k_opad[65];    /* outer padding -
76				      * key XORd with opad
77				      */
78	unsigned char tk[16];
79	int i;
80
81	/* if key is longer than 64 bytes reset it to key=MD5(key) */
82	if (key_len > 64) {
83		MD5_CTX      tctx;
84
85		MD5Init(&tctx);
86		MD5Update(&tctx, key, key_len);
87		MD5Final(tk, &tctx);
88
89		key = tk;
90		key_len = 16;
91	}
92
93	/*
94	 * the HMAC_MD5 transform looks like:
95	 *
96	 * MD5(K XOR opad, MD5(K XOR ipad, text))
97	 *
98	 * where K is an n byte key
99	 * ipad is the byte 0x36 repeated 64 times
100
101	 * opad is the byte 0x5c repeated 64 times
102	 * and text is the data being protected
103	 */
104
105	/* start out by storing key in pads */
106	memset(k_ipad, 0, sizeof(k_ipad));
107	memset(k_opad, 0, sizeof(k_opad));
108	memcpy(k_ipad, key, key_len);
109	memcpy(k_opad, key, key_len);
110
111	/* XOR key with ipad and opad values */
112	for (i = 0; i < 64; i++) {
113		k_ipad[i] ^= 0x36;
114		k_opad[i] ^= 0x5c;
115	}
116	/*
117	 * perform inner MD5
118	 */
119	MD5Init(&context);                   /* init context for 1st pass */
120	MD5Update(&context, k_ipad, 64);     /* start with inner pad */
121	MD5Update(&context, text, text_len); /* then text of datagram */
122	MD5Final(digest, &context);          /* finish up 1st pass */
123	/*
124	 * perform outer MD5
125	 */
126	MD5Init(&context);                   /* init context for 2nd pass */
127	MD5Update(&context, k_opad, 64);     /* start with outer pad */
128	MD5Update(&context, digest, 16);     /* then results of 1st hash */
129	MD5Final(digest, &context);          /* finish up 2nd pass */
130}
131