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