1 /* session.c --- Data integrity/privacy protection of DIGEST-MD5.
2 * Copyright (C) 2002, 2003, 2004, 2005 Simon Josefsson
4 * This file is part of GNU SASL Library.
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.
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.
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.
27 /* Get specification. */
30 /* Get malloc, free. */
33 /* Get memcpy, strdup, strlen. */
36 /* Get gc_hmac_md5. */
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
48 digest_md5_encode (const char *input
, size_t input_len
,
49 char **output
, size_t * output_len
,
51 unsigned long sendseqnum
, char key
[DIGEST_MD5_LENGTH
])
55 if (qop
& DIGEST_MD5_QOP_AUTH_CONF
)
59 else if (qop
& DIGEST_MD5_QOP_AUTH_INT
)
62 char hash
[GC_MD5_DIGEST_SIZE
];
65 seqnumin
= malloc (MAC_SEQNUM_LEN
+ input_len
);
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
);
75 res
= gc_hmac_md5 (key
, MD5LEN
,
76 seqnumin
, MAC_SEQNUM_LEN
+ input_len
, hash
);
81 *output_len
= MAC_DATA_LEN
+ input_len
+ MAC_HMAC_LEN
+
82 MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
;
83 *output
= malloc (*output_len
);
88 memcpy (*output
+ len
, input
, input_len
);
90 memcpy (*output
+ len
, hash
, 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;
106 *output_len
= input_len
;
107 *output
= malloc (input_len
);
110 memcpy (*output
, input
, input_len
);
116 #define C2I(buf) ((buf[0] & 0xFF) | \
117 ((buf[1] & 0xFF) << 8) | \
118 ((buf[2] & 0xFF) << 16) | \
119 ((buf[3] & 0xFF) << 24))
122 digest_md5_decode (const char *input
, size_t input_len
,
123 char **output
, size_t * output_len
,
125 unsigned long readseqnum
, char key
[DIGEST_MD5_LENGTH
])
127 if (qop
& DIGEST_MD5_QOP_AUTH_CONF
)
131 else if (qop
& DIGEST_MD5_QOP_AUTH_INT
)
134 char hash
[GC_MD5_DIGEST_SIZE
];
136 char tmpbuf
[SASL_INTEGRITY_PREFIX_LENGTH
];
139 if (input_len
< SASL_INTEGRITY_PREFIX_LENGTH
)
144 if (input_len
< SASL_INTEGRITY_PREFIX_LENGTH
+ len
)
147 len
-= MAC_HMAC_LEN
+ MAC_MSG_TYPE_LEN
+ MAC_SEQNUM_LEN
;
149 seqnumin
= malloc (SASL_INTEGRITY_PREFIX_LENGTH
+ len
);
150 if (seqnumin
== NULL
)
153 tmpbuf
[0] = (readseqnum
>> 24) & 0xFF;
154 tmpbuf
[1] = (readseqnum
>> 16) & 0xFF;
155 tmpbuf
[2] = (readseqnum
>> 8) & 0xFF;
156 tmpbuf
[3] = readseqnum
& 0xFF;
158 memcpy (seqnumin
, tmpbuf
, SASL_INTEGRITY_PREFIX_LENGTH
);
159 memcpy (seqnumin
+ SASL_INTEGRITY_PREFIX_LENGTH
,
160 input
+ MAC_DATA_LEN
, len
);
162 res
= gc_hmac_md5 (key
, MD5LEN
, seqnumin
, MAC_SEQNUM_LEN
+ len
, hash
);
169 input
+ input_len
- MAC_SEQNUM_LEN
- MAC_MSG_TYPE_LEN
-
170 MAC_HMAC_LEN
, MAC_HMAC_LEN
) == 0
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)
178 *output
= malloc (*output_len
);
181 memcpy (*output
, input
+ MAC_DATA_LEN
, len
);
188 *output_len
= input_len
;
189 *output
= malloc (input_len
);
192 memcpy (*output
, input
, input_len
);