gsasl  2.2.1
session.c
Go to the documentation of this file.
1 /* session.c --- Data integrity/privacy protection of DIGEST-MD5.
2  * Copyright (C) 2002-2024 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 #include <config.h>
24 
25 /* Get specification. */
26 #include "session.h"
27 
28 /* Get malloc, free. */
29 #include <stdlib.h>
30 
31 /* Get memcpy, strdup, strlen. */
32 #include <string.h>
33 
34 /* Get gc_hmac_md5. */
35 #include <gc.h>
36 
37 #define MD5LEN 16
38 #define SASL_INTEGRITY_PREFIX_LENGTH 4
39 #define MAC_DATA_LEN 4
40 #define MAC_HMAC_LEN 10
41 #define MAC_MSG_TYPE "\x00\x01"
42 #define MAC_MSG_TYPE_LEN 2
43 #define MAC_SEQNUM_LEN 4
44 
45 int
46 digest_md5_encode (const char *input, size_t input_len,
47  char **output, size_t *output_len,
48  digest_md5_qop qop,
49  unsigned long sendseqnum, char key[DIGEST_MD5_LENGTH])
50 {
51  int res;
52 
53  if (qop & DIGEST_MD5_QOP_AUTH_CONF)
54  {
55  return -1;
56  }
57  else if (qop & DIGEST_MD5_QOP_AUTH_INT)
58  {
59  char *seqnumin;
60  char hash[GC_MD5_DIGEST_SIZE];
61  size_t len;
62 
63  seqnumin = malloc (MAC_SEQNUM_LEN + input_len);
64  if (seqnumin == NULL)
65  return -1;
66 
67  seqnumin[0] = (sendseqnum >> 24) & 0xFF;
68  seqnumin[1] = (sendseqnum >> 16) & 0xFF;
69  seqnumin[2] = (sendseqnum >> 8) & 0xFF;
70  seqnumin[3] = sendseqnum & 0xFF;
71  memcpy (seqnumin + MAC_SEQNUM_LEN, input, input_len);
72 
73  res = gc_hmac_md5 (key, MD5LEN,
74  seqnumin, MAC_SEQNUM_LEN + input_len, hash);
75  free (seqnumin);
76  if (res)
77  return -1;
78 
79  *output_len = MAC_DATA_LEN + input_len + MAC_HMAC_LEN +
81  *output = malloc (*output_len);
82  if (!*output)
83  return -1;
84 
85  len = MAC_DATA_LEN;
86  memcpy (*output + len, input, input_len);
87  len += input_len;
88  memcpy (*output + len, hash, MAC_HMAC_LEN);
89  len += MAC_HMAC_LEN;
90  memcpy (*output + len, MAC_MSG_TYPE, MAC_MSG_TYPE_LEN);
91  len += MAC_MSG_TYPE_LEN;
92  (*output + len)[0] = (sendseqnum >> 24) & 0xFF;
93  (*output + len)[1] = (sendseqnum >> 16) & 0xFF;
94  (*output + len)[2] = (sendseqnum >> 8) & 0xFF;
95  (*output + len)[3] = sendseqnum & 0xFF;
96  len += MAC_SEQNUM_LEN;
97  (*output)[0] = ((len - MAC_DATA_LEN) >> 24) & 0xFF;
98  (*output)[1] = ((len - MAC_DATA_LEN) >> 16) & 0xFF;
99  (*output)[2] = ((len - MAC_DATA_LEN) >> 8) & 0xFF;
100  (*output)[3] = (len - MAC_DATA_LEN) & 0xFF;
101  }
102  else
103  {
104  *output_len = input_len;
105  *output = malloc (input_len);
106  if (!*output)
107  return -1;
108  memcpy (*output, input, input_len);
109  }
110 
111  return 0;
112 }
113 
114 #define C2I(buf) ((buf[3] & 0xFF) | \
115  ((buf[2] & 0xFF) << 8) | \
116  ((buf[1] & 0xFF) << 16) | \
117  ((buf[0] & 0xFF) << 24))
118 
119 int
120 digest_md5_decode (const char *input, size_t input_len,
121  char **output, size_t *output_len,
122  digest_md5_qop qop,
123  unsigned long readseqnum, char key[DIGEST_MD5_LENGTH])
124 {
125  if (qop & DIGEST_MD5_QOP_AUTH_CONF)
126  {
127  return -1;
128  }
129  else if (qop & DIGEST_MD5_QOP_AUTH_INT)
130  {
131  char *seqnumin;
132  char hash[GC_MD5_DIGEST_SIZE];
133  unsigned long len;
134  char tmpbuf[SASL_INTEGRITY_PREFIX_LENGTH];
135  int res;
136 
137  if (input_len < SASL_INTEGRITY_PREFIX_LENGTH)
138  return -2;
139 
140  len = C2I (input);
141 
142  if (input_len < SASL_INTEGRITY_PREFIX_LENGTH + len)
143  return -2;
144 
146 
147  seqnumin = malloc (SASL_INTEGRITY_PREFIX_LENGTH + len);
148  if (seqnumin == NULL)
149  return -1;
150 
151  tmpbuf[0] = (readseqnum >> 24) & 0xFF;
152  tmpbuf[1] = (readseqnum >> 16) & 0xFF;
153  tmpbuf[2] = (readseqnum >> 8) & 0xFF;
154  tmpbuf[3] = readseqnum & 0xFF;
155 
156  memcpy (seqnumin, tmpbuf, SASL_INTEGRITY_PREFIX_LENGTH);
157  memcpy (seqnumin + SASL_INTEGRITY_PREFIX_LENGTH,
158  input + MAC_DATA_LEN, len);
159 
160  res = gc_hmac_md5 (key, MD5LEN, seqnumin, MAC_SEQNUM_LEN + len, hash);
161  free (seqnumin);
162  if (res)
163  return -1;
164 
165  if (memcmp
166  (hash,
167  input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN -
169  && memcmp (MAC_MSG_TYPE,
170  input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN,
171  MAC_MSG_TYPE_LEN) == 0
172  && memcmp (tmpbuf, input + input_len - MAC_SEQNUM_LEN,
173  MAC_SEQNUM_LEN) == 0)
174  {
175  *output_len = len;
176  *output = malloc (*output_len);
177  if (!*output)
178  return -1;
179  memcpy (*output, input + MAC_DATA_LEN, len);
180  }
181  else
182  return -1;
183  }
184  else
185  {
186  *output_len = input_len;
187  *output = malloc (input_len);
188  if (!*output)
189  return -1;
190  memcpy (*output, input, input_len);
191  }
192 
193  return 0;
194 }
digest_md5_qop
@ DIGEST_MD5_QOP_AUTH_INT
@ DIGEST_MD5_QOP_AUTH_CONF
#define DIGEST_MD5_LENGTH
#define MAC_MSG_TYPE_LEN
Definition: session.c:42
#define MAC_SEQNUM_LEN
Definition: session.c:43
#define MD5LEN
Definition: session.c:37
int digest_md5_decode(const char *input, size_t input_len, char **output, size_t *output_len, digest_md5_qop qop, unsigned long readseqnum, char key[DIGEST_MD5_LENGTH])
Definition: session.c:120
#define MAC_DATA_LEN
Definition: session.c:39
#define SASL_INTEGRITY_PREFIX_LENGTH
Definition: session.c:38
int digest_md5_encode(const char *input, size_t input_len, char **output, size_t *output_len, digest_md5_qop qop, unsigned long sendseqnum, char key[DIGEST_MD5_LENGTH])
Definition: session.c:46
#define C2I(buf)
Definition: session.c:114
#define MAC_MSG_TYPE
Definition: session.c:41
#define MAC_HMAC_LEN
Definition: session.c:40