1 /*
2  *  DOCSIS configuration file encoder.
3  *  Copyright (c) 2001 Cornel Ciocirlan, ctrl@users.sourceforge.net.
4  *  Copyright (c) 2002, 2003 Evvolve Media SRL, office@evvolve.com
5  *  Copyright (c) 2014 - 2015 Adrian Simionov, daniel.simionov@gmail.com
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License along
18  *  with this program; if not, write to the Free Software Foundation, Inc.,
19  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  *  DOCSIS is a registered trademark of Cablelabs, http://www.cablelabs.com
22  */
23 
24 #include <string.h>
25 #include <stdio.h>
26 #include "docsis.h"
27 #include "md5.h"
28 
29 /*
30  * debugging function
31  * print the MD5 digest found in the arg buffer
32  */
33 
md5_print_digest(unsigned char * digest)34 void md5_print_digest ( unsigned char *digest )
35 {
36   int j;
37   /* TODO check that the buffer actually contains 16 chars ... */
38   fprintf(stderr, " --- MD5 DIGEST: 0x");
39   for (j=0;j<16;j++)
40 	fprintf(stderr, "%02x", digest[j] );
41   fprintf(stderr, "\n");
42 }
43 
44 /*
45 ** Function: hmac_md5
46 ** Mostly cut & paste from RFC 2104
47 */
48 
49 /* unsigned char*  text;                pointer to data stream 		*/
50 /* int             text_len;            length of data stream 		*/
51 /* unsigned char*  key;                 pointer to authentication key 	*/
52 /* int             key_len;             length of authentication key 	*/
53 /* unsigned char*  digest;              caller digest to be filled in 	*/
54 
55 void
hmac_md5(unsigned char * text,int text_len,unsigned char * key,size_t key_len,unsigned char * digest)56 hmac_md5(unsigned char *text, int text_len, unsigned char *key, size_t key_len, unsigned char *digest)
57 {
58         MD5_CTX context;
59         unsigned char k_ipad[65];    /* inner padding -
60                                       * key XORd with ipad
61                                       */
62         unsigned char k_opad[65];    /* outer padding -
63                                       * key XORd with opad
64                                       */
65         unsigned char tk[16];
66         int i;
67  	unsigned char tmpdigest[16];
68 
69         /* if key is longer than 64 bytes reset it to key=MD5(key) */
70         if (key_len > 64) {
71 
72                 MD5_CTX      tctx;
73 
74                 MD5_Init(&tctx);
75                 MD5_Update(&tctx, key, key_len);
76                 MD5_Final(tmpdigest,&tctx);
77 
78                 memcpy (tk, tmpdigest, 16);
79 		key = tk;
80                 key_len = 16;
81         }
82 
83         /*
84          * the HMAC_MD5 transform looks like:
85          *
86          * MD5(K XOR opad, MD5(K XOR ipad, text))
87          *
88          * where K is an n byte key
89          * ipad is the byte 0x36 repeated 64 times
90          * opad is the byte 0x5c repeated 64 times
91          * and text is the data being protected
92          */
93 
94         /* start out by storing key in pads */
95         memset ( k_ipad, 0, sizeof k_ipad);
96         memset ( k_opad, 0, sizeof k_opad);
97         memcpy ( k_ipad, key, key_len);
98         memcpy ( k_opad, key, key_len);
99 
100         /* XOR key with ipad and opad values */
101         for (i=0; i<64; i++) {
102                 k_ipad[i] ^= 0x36;
103                 k_opad[i] ^= 0x5c;
104         }
105         /*
106          * perform inner MD5
107          */
108         MD5_Init(&context);                   /* init context for 1st
109                                               * pass */
110         MD5_Update(&context, k_ipad, 64);      /* start with inner pad */
111         MD5_Update(&context, text, text_len); /* then text of datagram */
112         MD5_Final(digest, &context);          /* finish up 1st pass */
113         /*
114          * perform outer MD5
115          */
116         MD5_Init(&context);                   /* init context for 2nd
117                                               * pass */
118         MD5_Update(&context, k_opad, 64);     /* start with outer pad */
119         MD5_Update(&context, digest, 16);     /* then results of 1st
120                                               * hash */
121         MD5_Final(digest,&context);          /* finish up 2nd pass */
122 }
123