Branch data Line data Source code
1 : : /* session.c --- Data integrity/privacy protection of DIGEST-MD5.
2 : : * Copyright (C) 2002-2012 Simon Josefsson
3 : : *
4 : : * This file is part of GNU SASL Library.
5 : : *
6 : : * GNU SASL Library is free software; you can redistribute it and/or
7 : : * modify it under the terms of the GNU Lesser General Public License
8 : : * as published by the Free Software Foundation; either version 2.1 of
9 : : * the License, or (at your option) any later version.
10 : : *
11 : : * GNU SASL Library is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : : * Lesser General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU Lesser General Public
17 : : * License along with GNU SASL Library; if not, write to the Free
18 : : * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 : : * Boston, MA 02110-1301, USA.
20 : : *
21 : : */
22 : :
23 : : #ifdef HAVE_CONFIG_H
24 : : #include "config.h"
25 : : #endif
26 : :
27 : : /* Get specification. */
28 : : #include "session.h"
29 : :
30 : : /* Get malloc, free. */
31 : : #include <stdlib.h>
32 : :
33 : : /* Get memcpy, strdup, strlen. */
34 : : #include <string.h>
35 : :
36 : : /* Get gc_hmac_md5. */
37 : : #include <gc.h>
38 : :
39 : : #define MD5LEN 16
40 : : #define SASL_INTEGRITY_PREFIX_LENGTH 4
41 : : #define MAC_DATA_LEN 4
42 : : #define MAC_HMAC_LEN 10
43 : : #define MAC_MSG_TYPE "\x00\x01"
44 : : #define MAC_MSG_TYPE_LEN 2
45 : : #define MAC_SEQNUM_LEN 4
46 : :
47 : : int
48 : 10 : digest_md5_encode (const char *input, size_t input_len,
49 : : char **output, size_t * output_len,
50 : : digest_md5_qop qop,
51 : : unsigned long sendseqnum, char key[DIGEST_MD5_LENGTH])
52 : : {
53 : : int res;
54 : :
55 [ - + ]: 10 : if (qop & DIGEST_MD5_QOP_AUTH_CONF)
56 : : {
57 : 0 : return -1;
58 : : }
59 [ + + ]: 10 : else if (qop & DIGEST_MD5_QOP_AUTH_INT)
60 : : {
61 : : char *seqnumin;
62 : : char hash[GC_MD5_DIGEST_SIZE];
63 : : size_t len;
64 : :
65 : 2 : seqnumin = malloc (MAC_SEQNUM_LEN + input_len);
66 [ - + ]: 2 : if (seqnumin == NULL)
67 : 0 : return -1;
68 : :
69 : 2 : seqnumin[0] = (sendseqnum >> 24) & 0xFF;
70 : 2 : seqnumin[1] = (sendseqnum >> 16) & 0xFF;
71 : 2 : seqnumin[2] = (sendseqnum >> 8) & 0xFF;
72 : 2 : seqnumin[3] = sendseqnum & 0xFF;
73 : 2 : memcpy (seqnumin + MAC_SEQNUM_LEN, input, input_len);
74 : :
75 : 2 : res = gc_hmac_md5 (key, MD5LEN,
76 : : seqnumin, MAC_SEQNUM_LEN + input_len, hash);
77 : 2 : free (seqnumin);
78 [ - + ]: 2 : if (res)
79 : 0 : return -1;
80 : :
81 : 2 : *output_len = MAC_DATA_LEN + input_len + MAC_HMAC_LEN +
82 : 2 : MAC_MSG_TYPE_LEN + MAC_SEQNUM_LEN;
83 : 2 : *output = malloc (*output_len);
84 [ - + ]: 2 : if (!*output)
85 : 0 : return -1;
86 : :
87 : 2 : len = MAC_DATA_LEN;
88 : 2 : memcpy (*output + len, input, input_len);
89 : 2 : len += input_len;
90 : 2 : memcpy (*output + len, hash, MAC_HMAC_LEN);
91 : 2 : len += MAC_HMAC_LEN;
92 : 2 : memcpy (*output + len, MAC_MSG_TYPE, MAC_MSG_TYPE_LEN);
93 : 2 : len += MAC_MSG_TYPE_LEN;
94 : 2 : (*output + len)[0] = (sendseqnum >> 24) & 0xFF;
95 : 2 : (*output + len)[1] = (sendseqnum >> 16) & 0xFF;
96 : 2 : (*output + len)[2] = (sendseqnum >> 8) & 0xFF;
97 : 2 : (*output + len)[3] = sendseqnum & 0xFF;
98 : 2 : len += MAC_SEQNUM_LEN;
99 : 2 : (*output)[0] = ((len - MAC_DATA_LEN) >> 24) & 0xFF;
100 : 2 : (*output)[1] = ((len - MAC_DATA_LEN) >> 16) & 0xFF;
101 : 2 : (*output)[2] = ((len - MAC_DATA_LEN) >> 8) & 0xFF;
102 : 2 : (*output)[3] = (len - MAC_DATA_LEN) & 0xFF;
103 : : }
104 : : else
105 : : {
106 : 8 : *output_len = input_len;
107 : 8 : *output = malloc (input_len);
108 [ - + ]: 8 : if (!*output)
109 : 0 : return -1;
110 : 8 : memcpy (*output, input, input_len);
111 : : }
112 : :
113 : 10 : return 0;
114 : : }
115 : :
116 : : #define C2I(buf) ((buf[3] & 0xFF) | \
117 : : ((buf[2] & 0xFF) << 8) | \
118 : : ((buf[1] & 0xFF) << 16) | \
119 : : ((buf[0] & 0xFF) << 24))
120 : :
121 : : int
122 : 10 : digest_md5_decode (const char *input, size_t input_len,
123 : : char **output, size_t * output_len,
124 : : digest_md5_qop qop,
125 : : unsigned long readseqnum, char key[DIGEST_MD5_LENGTH])
126 : : {
127 [ - + ]: 10 : if (qop & DIGEST_MD5_QOP_AUTH_CONF)
128 : : {
129 : 0 : return -1;
130 : : }
131 [ + + ]: 10 : else if (qop & DIGEST_MD5_QOP_AUTH_INT)
132 : : {
133 : : char *seqnumin;
134 : : char hash[GC_MD5_DIGEST_SIZE];
135 : : unsigned long len;
136 : : char tmpbuf[SASL_INTEGRITY_PREFIX_LENGTH];
137 : : int res;
138 : :
139 [ - + ]: 2 : if (input_len < SASL_INTEGRITY_PREFIX_LENGTH)
140 : 0 : return -2;
141 : :
142 : 2 : len = C2I (input);
143 : :
144 [ - + ]: 2 : if (input_len < SASL_INTEGRITY_PREFIX_LENGTH + len)
145 : 0 : return -2;
146 : :
147 : 2 : len -= MAC_HMAC_LEN + MAC_MSG_TYPE_LEN + MAC_SEQNUM_LEN;
148 : :
149 : 2 : seqnumin = malloc (SASL_INTEGRITY_PREFIX_LENGTH + len);
150 [ - + ]: 2 : if (seqnumin == NULL)
151 : 0 : return -1;
152 : :
153 : 2 : tmpbuf[0] = (readseqnum >> 24) & 0xFF;
154 : 2 : tmpbuf[1] = (readseqnum >> 16) & 0xFF;
155 : 2 : tmpbuf[2] = (readseqnum >> 8) & 0xFF;
156 : 2 : tmpbuf[3] = readseqnum & 0xFF;
157 : :
158 : 2 : memcpy (seqnumin, tmpbuf, SASL_INTEGRITY_PREFIX_LENGTH);
159 : 2 : memcpy (seqnumin + SASL_INTEGRITY_PREFIX_LENGTH,
160 : 2 : input + MAC_DATA_LEN, len);
161 : :
162 : 2 : res = gc_hmac_md5 (key, MD5LEN, seqnumin, MAC_SEQNUM_LEN + len, hash);
163 : 2 : free (seqnumin);
164 [ - + ]: 2 : if (res)
165 : 0 : return -1;
166 : :
167 [ + - ]: 2 : if (memcmp
168 : 2 : (hash,
169 : 2 : input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN -
170 : : MAC_HMAC_LEN, MAC_HMAC_LEN) == 0
171 [ + - ]: 2 : && memcmp (MAC_MSG_TYPE,
172 : 2 : input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN,
173 : : MAC_MSG_TYPE_LEN) == 0
174 [ + - ]: 2 : && memcmp (tmpbuf, input + input_len - MAC_SEQNUM_LEN,
175 : : MAC_SEQNUM_LEN) == 0)
176 : : {
177 : 2 : *output_len = len;
178 : 2 : *output = malloc (*output_len);
179 [ - + ]: 2 : if (!*output)
180 : 0 : return -1;
181 : 2 : memcpy (*output, input + MAC_DATA_LEN, len);
182 : : }
183 : : else
184 : 0 : return -1;
185 : : }
186 : : else
187 : : {
188 : 8 : *output_len = input_len;
189 : 8 : *output = malloc (input_len);
190 [ - + ]: 8 : if (!*output)
191 : 0 : return -1;
192 : 8 : memcpy (*output, input, input_len);
193 : : }
194 : :
195 : 10 : return 0;
196 : : }
|