gsasl  1.10.0
About: GNU SASL is an implementation of the Simple Authentication and Security Layer (SASL). Development version.
  Fossies Dox: gsasl-1.10.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

session.c
Go to the documentation of this file.
1 /* session.c --- Data integrity/privacy protection of DIGEST-MD5.
2  * Copyright (C) 2002-2021 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 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  if (qop & DIGEST_MD5_QOP_AUTH_CONF)
56  {
57  return -1;
58  }
59  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  seqnumin = malloc (MAC_SEQNUM_LEN + input_len);
66  if (seqnumin == NULL)
67  return -1;
68 
69  seqnumin[0] = (sendseqnum >> 24) & 0xFF;
70  seqnumin[1] = (sendseqnum >> 16) & 0xFF;
71  seqnumin[2] = (sendseqnum >> 8) & 0xFF;
72  seqnumin[3] = sendseqnum & 0xFF;
73  memcpy (seqnumin + MAC_SEQNUM_LEN, input, input_len);
74 
75  res = gc_hmac_md5 (key, MD5LEN,
76  seqnumin, MAC_SEQNUM_LEN + input_len, hash);
77  free (seqnumin);
78  if (res)
79  return -1;
80 
81  *output_len = MAC_DATA_LEN + input_len + MAC_HMAC_LEN +
83  *output = malloc (*output_len);
84  if (!*output)
85  return -1;
86 
87  len = MAC_DATA_LEN;
88  memcpy (*output + len, input, input_len);
89  len += input_len;
90  memcpy (*output + len, hash, MAC_HMAC_LEN);
91  len += MAC_HMAC_LEN;
92  memcpy (*output + len, MAC_MSG_TYPE, MAC_MSG_TYPE_LEN);
93  len += MAC_MSG_TYPE_LEN;
94  (*output + len)[0] = (sendseqnum >> 24) & 0xFF;
95  (*output + len)[1] = (sendseqnum >> 16) & 0xFF;
96  (*output + len)[2] = (sendseqnum >> 8) & 0xFF;
97  (*output + len)[3] = sendseqnum & 0xFF;
98  len += MAC_SEQNUM_LEN;
99  (*output)[0] = ((len - MAC_DATA_LEN) >> 24) & 0xFF;
100  (*output)[1] = ((len - MAC_DATA_LEN) >> 16) & 0xFF;
101  (*output)[2] = ((len - MAC_DATA_LEN) >> 8) & 0xFF;
102  (*output)[3] = (len - MAC_DATA_LEN) & 0xFF;
103  }
104  else
105  {
106  *output_len = input_len;
107  *output = malloc (input_len);
108  if (!*output)
109  return -1;
110  memcpy (*output, input, input_len);
111  }
112 
113  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 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  if (qop & DIGEST_MD5_QOP_AUTH_CONF)
128  {
129  return -1;
130  }
131  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  if (input_len < SASL_INTEGRITY_PREFIX_LENGTH)
140  return -2;
141 
142  len = C2I (input);
143 
144  if (input_len < SASL_INTEGRITY_PREFIX_LENGTH + len)
145  return -2;
146 
148 
149  seqnumin = malloc (SASL_INTEGRITY_PREFIX_LENGTH + len);
150  if (seqnumin == NULL)
151  return -1;
152 
153  tmpbuf[0] = (readseqnum >> 24) & 0xFF;
154  tmpbuf[1] = (readseqnum >> 16) & 0xFF;
155  tmpbuf[2] = (readseqnum >> 8) & 0xFF;
156  tmpbuf[3] = readseqnum & 0xFF;
157 
158  memcpy (seqnumin, tmpbuf, SASL_INTEGRITY_PREFIX_LENGTH);
159  memcpy (seqnumin + SASL_INTEGRITY_PREFIX_LENGTH,
160  input + MAC_DATA_LEN, len);
161 
162  res = gc_hmac_md5 (key, MD5LEN, seqnumin, MAC_SEQNUM_LEN + len, hash);
163  free (seqnumin);
164  if (res)
165  return -1;
166 
167  if (memcmp
168  (hash,
169  input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN -
171  && memcmp (MAC_MSG_TYPE,
172  input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN,
173  MAC_MSG_TYPE_LEN) == 0
174  && memcmp (tmpbuf, input + input_len - MAC_SEQNUM_LEN,
175  MAC_SEQNUM_LEN) == 0)
176  {
177  *output_len = len;
178  *output = malloc (*output_len);
179  if (!*output)
180  return -1;
181  memcpy (*output, input + MAC_DATA_LEN, len);
182  }
183  else
184  return -1;
185  }
186  else
187  {
188  *output_len = input_len;
189  *output = malloc (input_len);
190  if (!*output)
191  return -1;
192  memcpy (*output, input, input_len);
193  }
194 
195  return 0;
196 }
digest_md5_qop
Definition: tokens.h:34
@ DIGEST_MD5_QOP_AUTH_INT
Definition: tokens.h:36
@ DIGEST_MD5_QOP_AUTH_CONF
Definition: tokens.h:37
#define DIGEST_MD5_LENGTH
Definition: tokens.h:30
Gc_rc gc_hmac_md5(const void *key, size_t keylen, const void *in, size_t inlen, char *resbuf)
Definition: gc-gnulib.c:1027
#define GC_MD5_DIGEST_SIZE
Definition: gc.h:66
#define NULL
Definition: stddef.in.h:72
int res
Definition: mbrtowc-impl.h:45
#define MAC_MSG_TYPE_LEN
Definition: session.c:44
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[16])
Definition: session.c:122
#define MAC_SEQNUM_LEN
Definition: session.c:45
#define MD5LEN
Definition: session.c:39
#define MAC_DATA_LEN
Definition: session.c:41
#define SASL_INTEGRITY_PREFIX_LENGTH
Definition: session.c:40
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[16])
Definition: session.c:48
#define C2I(buf)
Definition: session.c:116
#define MAC_MSG_TYPE
Definition: session.c:43
#define MAC_HMAC_LEN
Definition: session.c:42