Home | History | Annotate | Line # | Download | only in src
      1 /* $NetBSD: mech_digestmd5.c,v 1.15 2025/12/17 15:58:36 nia Exp $ */
      2 
      3 /* Copyright (c) 2010 The NetBSD Foundation, Inc.
      4  * All rights reserved.
      5  *
      6  * This code is derived from software contributed to The NetBSD Foundation
      7  * by Mateusz Kocielski.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. Neither the name of The NetBSD Foundation nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED.	IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 #include <sys/cdefs.h>
     34 __RCSID("$NetBSD: mech_digestmd5.c,v 1.15 2025/12/17 15:58:36 nia Exp $");
     35 
     36 #include <sys/param.h>
     37 
     38 #include <assert.h>
     39 #include <endian.h>
     40 #include <ctype.h>
     41 #include <md5.h>
     42 #include <saslc.h>
     43 #include <stdbool.h>
     44 #include <stdio.h>
     45 #include <string.h>
     46 
     47 #include <openssl/evp.h>
     48 
     49 #include "buffer.h"
     50 #include "crypto.h"
     51 #include "error.h"
     52 #include "list.h"
     53 #include "mech.h"
     54 #include "msg.h"
     55 #include "saslc_private.h"
     56 
     57 /* See RFC 2831. */
     58 
     59 /*
     60  * TODO:
     61  *
     62  * 1) Add support for Subsequent Authentication (see RFC 2831 section 2.2).
     63  */
     64 
     65 /* properties */
     66 #define SASLC_DIGESTMD5_AUTHCID		SASLC_PROP_AUTHCID
     67 #define SASLC_DIGESTMD5_AUTHZID		SASLC_PROP_AUTHZID
     68 #define SASLC_DIGESTMD5_CIPHERMASK	SASLC_PROP_CIPHERMASK
     69 #define SASLC_DIGESTMD5_HOSTNAME	SASLC_PROP_HOSTNAME
     70 #define SASLC_DIGESTMD5_MAXBUF		SASLC_PROP_MAXBUF
     71 #define SASLC_DIGESTMD5_PASSWD		SASLC_PROP_PASSWD
     72 #define SASLC_DIGESTMD5_QOPMASK		SASLC_PROP_QOPMASK
     73 #define SASLC_DIGESTMD5_REALM		SASLC_PROP_REALM
     74 #define SASLC_DIGESTMD5_SERVICE		SASLC_PROP_SERVICE
     75 #define SASLC_DIGESTMD5_SERVNAME	SASLC_PROP_SERVNAME
     76 /*
     77  * XXX: define this if you want to be able to set a fixed cnonce for
     78  * debugging purposes.
     79  */
     80 #define SASLC_DIGESTMD5_CNONCE		"CNONCE"
     81 /*
     82  * XXX: define this if you want to test the saslc_sess_encode() and
     83  * saslc_sess_decode() routines against themselves, i.e., have them
     84  * use the same key.
     85  */
     86 #define SASLC_DIGESTMD5_SELFTEST	"SELFTEST"
     87 
     88 #define DEFAULT_QOP_MASK	(F_QOP_NONE | F_QOP_INT | F_QOP_CONF)
     89 #define DEFAULT_CIPHER_MASK	(F_CIPHER_DES | F_CIPHER_3DES | \
     90 				 F_CIPHER_RC4 | F_CIPHER_RC4_40 | \
     91 				 F_CIPHER_RC4_56 | F_CIPHER_AES)
     92 
     93 #define DEFAULT_MAXBUF		0x10000
     94 #define MAX_MAXBUF		0xffffff
     95 #define INVALID_MAXBUF(m)	((m) <= sizeof(md5hash_t) && (m) > MAX_MAXBUF)
     96 
     97 #define NONCE_LEN 33	/* Minimum recommended length is 64bits (rfc2831).
     98 			   cyrus-sasl uses 33 bytes. */
     99 
    100 typedef enum {
    101 	CHALLENGE_IGNORE	= -1,	/* must be -1 */
    102 	CHALLENGE_REALM		= 0,
    103 	CHALLENGE_NONCE		= 1,
    104 	CHALLENGE_QOP		= 2,
    105 	CHALLENGE_STALE		= 3,
    106 	CHALLENGE_MAXBUF	= 4,
    107 	CHALLENGE_CHARSET	= 5,
    108 	CHALLENGE_ALGORITHM	= 6,
    109 	CHALLENGE_CIPHER	= 7
    110 } challenge_t;
    111 
    112 typedef enum {
    113 	/*
    114 	 * NB: Values used to index cipher_tbl[] and cipher_ctx_tbl[]
    115 	 *     in cipher_context_create().
    116 	 */
    117 	CIPHER_DES	= 0,
    118 	CIPHER_3DES	= 1,
    119 	CIPHER_RC4	= 2,
    120 	CIPHER_RC4_40	= 3,
    121 	CIPHER_RC4_56	= 4,
    122 	CIPHER_AES	= 5
    123 } cipher_t;
    124 
    125 #define F_CIPHER_DES		(1 << CIPHER_DES)
    126 #define F_CIPHER_3DES		(1 << CIPHER_3DES)
    127 #define F_CIPHER_RC4		(1 << CIPHER_RC4)
    128 #define F_CIPHER_RC4_40		(1 << CIPHER_RC4_40)
    129 #define F_CIPHER_RC4_56		(1 << CIPHER_RC4_56)
    130 #define F_CIPHER_AES		(1 << CIPHER_AES)
    131 
    132 static const named_flag_t cipher_tbl[] = {
    133 	/* NB: to be indexed by cipher_t values */
    134 	{ "des",	F_CIPHER_DES    },
    135 	{ "3des",	F_CIPHER_3DES   },
    136 	{ "rc4",	F_CIPHER_RC4    },
    137 	{ "rc4-40",	F_CIPHER_RC4_40 },
    138 	{ "rc4-56",	F_CIPHER_RC4_56 },
    139 	{ "aes",	F_CIPHER_AES    },
    140 	{ NULL,		0               }
    141 };
    142 
    143 static inline const char *
    144 cipher_name(cipher_t cipher)
    145 {
    146 
    147 	assert(cipher < __arraycount(cipher_tbl) - 1); /* NULL terminated */
    148 	if (cipher < __arraycount(cipher_tbl) - 1)
    149 		return cipher_tbl[cipher].name;
    150 	return NULL;
    151 }
    152 
    153 static inline unsigned int
    154 cipher_list_flags(list_t *list)
    155 {
    156 
    157 	return saslc__list_flags(list, cipher_tbl);
    158 }
    159 
    160 typedef struct { /* data parsed from challenge */
    161 	bool		utf8;
    162 	bool	 	algorithm;
    163 	bool	 	stale;
    164 	char *		nonce;
    165 	list_t *	realm;
    166 	uint32_t	cipher_flags;
    167 	uint32_t	qop_flags;
    168 	size_t		maxbuf;
    169 } cdata_t;
    170 
    171 typedef struct { /* response data */
    172 	/* NB: the qop is in saslc__mech_sess_t */
    173 	char *authcid;
    174 	char *authzid;
    175 	char *cnonce;
    176 	char *digesturi;
    177 	char *passwd;
    178 	char *realm;
    179 	cipher_t cipher;
    180 	int nonce_cnt;
    181 	size_t maxbuf;
    182 } rdata_t;
    183 
    184 typedef uint8_t md5hash_t[MD5_DIGEST_LENGTH];
    185 
    186 typedef struct {
    187 	md5hash_t kic;			/* client->server integrity key */
    188 	md5hash_t kis;			/* server->client integrity key */
    189 	md5hash_t kcc;			/* client->server confidentiality key */
    190 	md5hash_t kcs;			/* server->client confidentiality key */
    191 } keys_t;
    192 
    193 typedef struct cipher_context_t {
    194 	size_t blksize;			/* block size for cipher */
    195 	EVP_CIPHER_CTX *evp_ctx;	/* openssl EVP context */
    196 } cipher_context_t;
    197 
    198 typedef struct coder_context_t {
    199 	uint8_t *key;			/* key for coding */
    200 	uint32_t seqnum;		/* 4 byte sequence number */
    201 
    202 	void *buf_ctx;			/* buffer context */
    203 	cipher_context_t *cph_ctx;	/* cipher context */
    204 	saslc_sess_t *sess;		/* session: for error setting */
    205 } coder_context_t;
    206 
    207 /* mech state */
    208 typedef struct {
    209 	saslc__mech_sess_t mech_sess;	/* must be first */
    210 	cdata_t cdata;			/* data parsed from challenge string */
    211 	rdata_t rdata;			/* data used for response string */
    212 	keys_t keys;			/* keys */
    213 	coder_context_t dec_ctx;	/* decode context */
    214 	coder_context_t enc_ctx;	/* encode context */
    215 } saslc__mech_digestmd5_sess_t;
    216 
    217 /**
    218  * @brief if possible convert a UTF-8 string to a ISO8859-1 string.
    219  * @param utf8 original UTF-8 string.
    220  * @param iso8859 pointer to pointer to the malloced ISO8859-1 string.
    221  * @return -1 if the string cannot be translated.
    222  *
    223  * NOTE: this allocates memory for its output and the caller is
    224  * responsible for freeing it.
    225  */
    226 static int
    227 utf8_to_8859_1(char *utf8, char **iso8859)
    228 {
    229 	unsigned char *s, *d, *end, *src;
    230 	size_t cnt;
    231 
    232 	src = (unsigned char *)utf8;
    233 	cnt = 0;
    234 	end = src + strlen(utf8);
    235 	for (s = src; s < end; ++s) {
    236 		if (*s > 0xC3) /* abort if outside 8859-1 range */
    237 			return -1;
    238 		/*
    239 		 * Look for valid 2 byte UTF-8 encoding with, 8 bits
    240 		 * of info.  Quit if invalid pair found.
    241 		 */
    242 		if (*s >= 0xC0 && *s <= 0xC3) { /* 2 bytes, 8 bits */
    243 			if (++s == end || *s < 0x80 || *s > 0xBF)
    244 				return -1;	/* broken utf-8 encoding */
    245 		}
    246 		cnt++;
    247 	}
    248 
    249 	/* Allocate adequate space. */
    250 	d = malloc(cnt + 1);
    251 	if (d == NULL)
    252 		return -1;
    253 
    254 	*iso8859 = (char *)d;
    255 
    256 	/* convert to 8859-1 */
    257 	do {
    258 		for (s = src; s < end && *s < 0xC0; ++s)
    259 			*d++ = *s;
    260 		if (s + 1 >= end)
    261 			break;
    262 		*d++ = ((s[0] & 0x3) << 6) | (s[1] & 0x3f);
    263 		src = s + 2;
    264 	} while (src < end);
    265 
    266 	*d = '\0';
    267 	return 0;
    268 }
    269 
    270 /**
    271  * @brief unquote a string by removing escapes.
    272  * @param str string to unquote.
    273  * @return NULL on failure
    274  *
    275  * NOTE: this allocates memory for its output and the caller is
    276  * responsible for freeing it.
    277  */
    278 static char *
    279 unq(const char *str)
    280 {
    281 	const char *s;
    282 	char *unq_str, *d;
    283 	int escaped;
    284 
    285 	unq_str = malloc(strlen(str) + 1);
    286 	if (unq_str == NULL)
    287 		return NULL;
    288 
    289 	escaped = 0;
    290 	d = unq_str;
    291 	for (s = str; *s != '\0'; s++) {
    292 		switch (*s) {
    293 		case '\\':
    294 			if (escaped)
    295 				*d++ = *s;
    296 			escaped = !escaped;
    297 			break;
    298 		default:
    299 			*d++ = *s;
    300 			escaped = 0;
    301 		}
    302 	}
    303 	*d = '\0';
    304 
    305 	return unq_str;
    306 }
    307 
    308 /**
    309  * @brief computing MD5(username:realm:password).
    310  * @param ms mechanism session
    311  * @param buf buffer for hash
    312  * @return 0 on success, -1 on failure
    313  */
    314 static int
    315 saslc__mech_digestmd5_userhash(saslc__mech_digestmd5_sess_t *ms, uint8_t *buf)
    316 {
    317 	char *tmp;
    318 	char *unq_username, *unq_realm;
    319 	ssize_t len;
    320 
    321 	if ((unq_username = unq(ms->rdata.authcid)) == NULL)
    322 		return -1;
    323 
    324 	/********************************************************/
    325 	/* RFC 2831 section 2.1.2				*/
    326 	/* ...  If the directive is missing, "realm-value" will */
    327 	/* set to the empty string when computing A1.	  	*/
    328 	/********************************************************/
    329 	if (ms->rdata.realm == NULL)
    330 		unq_realm = strdup("");
    331 	else
    332 		unq_realm = unq(ms->rdata.realm);
    333 
    334 	if (unq_realm == NULL) {
    335 		free(unq_username);
    336 		return -1;
    337 	}
    338 	len = asprintf(&tmp, "%s:%s:%s",
    339 			unq_username, unq_realm, ms->rdata.passwd);
    340 	free(unq_realm);
    341 	free(unq_username);
    342 
    343 	if (len == -1)
    344 		return -1;
    345 
    346 	saslc__crypto_md5_hash(tmp, (size_t)len, buf);
    347 	memset(tmp, 0, (size_t)len);
    348 	free(tmp);
    349 	return 0;
    350 }
    351 
    352 /**
    353  * @brief setup the appropriate QOP keys as determined by the chosen
    354  * QOP type (see RFC2831 sections 2.3 and 2.4).
    355  * @param ms mechanism session
    356  * @param a1hash MD5(a1)
    357  * @return 0 on success, -1 on failure
    358  */
    359 static int
    360 setup_qop_keys(saslc__mech_digestmd5_sess_t *ms, md5hash_t a1hash)
    361 {
    362 #define KIC_MAGIC "Digest session key to client-to-server signing key magic constant"
    363 #define KIS_MAGIC "Digest session key to server-to-client signing key magic constant"
    364 #define KCC_MAGIC "Digest H(A1) to client-to-server sealing key magic constant"
    365 #define KCS_MAGIC "Digest H(A1) to server-to-client sealing key magic constant"
    366 #define KIC_MAGIC_LEN (sizeof(KIC_MAGIC) - 1)
    367 #define KIS_MAGIC_LEN (sizeof(KIS_MAGIC) - 1)
    368 #define KCC_MAGIC_LEN (sizeof(KCC_MAGIC) - 1)
    369 #define KCS_MAGIC_LEN (sizeof(KCS_MAGIC) - 1)
    370 #define MAX_MAGIC_LEN KIC_MAGIC_LEN
    371 
    372 	char buf[MD5_DIGEST_LENGTH + MAX_MAGIC_LEN];
    373 	size_t buflen;
    374 	size_t n;
    375 
    376 	switch (ms->mech_sess.qop) {
    377 	case QOP_NONE:
    378 		/* nothing to do */
    379 		break;
    380 
    381 	case QOP_CONF:
    382     /*************************************************************************/
    383     /* See RFC2831 section 2.4 (Confidentiality Protection)                  */
    384     /*                                                                       */
    385     /* The key for confidentiality protecting messages from client to server */
    386     /* is:                                                                   */
    387     /*                                                                       */
    388     /* Kcc = MD5({H(A1)[0..n],                                               */
    389     /* "Digest H(A1) to client-to-server sealing key magic constant"})       */
    390     /*                                                                       */
    391     /* The key for confidentiality protecting messages from server to client */
    392     /* is:                                                                   */
    393     /*                                                                       */
    394     /* Kcs = MD5({H(A1)[0..n],                                               */
    395     /* "Digest H(A1) to server-to-client sealing key magic constant"})       */
    396     /*                                                                       */
    397     /* where MD5 is as specified in [RFC 1321]. For cipher "rc4-40" n is 5;  */
    398     /* for "rc4-56" n is 7; for the rest n is 16.                            */
    399     /*************************************************************************/
    400 
    401 		switch (ms->rdata.cipher) {
    402 		case CIPHER_RC4_40:	n = 5;			break;
    403 		case CIPHER_RC4_56:	n = 7;			break;
    404 		default:		n = MD5_DIGEST_LENGTH;	break;
    405 		}
    406 		memcpy(buf, a1hash, n);
    407 
    408 		memcpy(buf + n, KCC_MAGIC, KCC_MAGIC_LEN);
    409 		buflen = n + KCC_MAGIC_LEN;
    410 		saslc__crypto_md5_hash(buf, buflen, ms->keys.kcc);
    411 
    412 		memcpy(buf + n, KCS_MAGIC, KCS_MAGIC_LEN);
    413 		buflen = n + KCS_MAGIC_LEN;
    414 		saslc__crypto_md5_hash(buf, buflen, ms->keys.kcs);
    415 
    416 		/*FALLTHROUGH*/
    417 
    418 	case QOP_INT:
    419     /*************************************************************************/
    420     /* See RFC2831 section 2.3 (Integrity Protection)                        */
    421     /* The key for integrity protecting messages from client to server is:   */
    422     /*                                                                       */
    423     /* Kic = MD5({H(A1),                                                     */
    424     /* "Digest session key to client-to-server signing key magic constant"}) */
    425     /*                                                                       */
    426     /* The key for integrity protecting messages from server to client is:   */
    427     /*                                                                       */
    428     /* Kis = MD5({H(A1),                                                     */
    429     /* "Digest session key to server-to-client signing key magic constant"}) */
    430     /*************************************************************************/
    431 		memcpy(buf, a1hash, MD5_DIGEST_LENGTH);
    432 
    433 		memcpy(buf + MD5_DIGEST_LENGTH, KIC_MAGIC, KIC_MAGIC_LEN);
    434 		buflen = MD5_DIGEST_LENGTH + KIC_MAGIC_LEN;
    435 		saslc__crypto_md5_hash(buf, buflen, ms->keys.kic);
    436 
    437 		memcpy(buf + MD5_DIGEST_LENGTH, KIS_MAGIC, KIS_MAGIC_LEN);
    438 		buflen = MD5_DIGEST_LENGTH + KIS_MAGIC_LEN;
    439 		saslc__crypto_md5_hash(buf, buflen, ms->keys.kis);
    440 		break;
    441 	}
    442 	return 0;
    443 
    444 #undef KIC_MAGIC
    445 #undef KIS_MAGIC
    446 #undef KCC_MAGIC
    447 #undef KCS_MAGIC
    448 #undef KIC_MAGIC_LEN
    449 #undef KIS_MAGIC_LEN
    450 #undef KCC_MAGIC_LEN
    451 #undef KCS_MAGIC_LEN
    452 #undef MAX_MAGIC_LEN
    453 }
    454 
    455 /**
    456  * @brief computes A1 hash value (see: RFC2831)
    457  * @param ms mechanism session
    458  * @return hash in hex form
    459  */
    460 static char *
    461 saslc__mech_digestmd5_a1(saslc__mech_digestmd5_sess_t *ms)
    462 {
    463 	char *tmp1, *tmp2, *r;
    464 	char *unq_authzid;
    465 	md5hash_t a1hash, userhash;
    466 	int plen;
    467 	size_t len;
    468  /*****************************************************************************/
    469  /* If authzid is specified, then A1 is                                       */
    470  /*                                                                           */
    471  /*    A1 = { H({ unq(username-value), ":", unq(realm-value), ":", passwd }), */
    472  /*         ":", nonce-value, ":", cnonce-value, ":", unq(authzid-value) }    */
    473  /*                                                                           */
    474  /* If authzid is not specified, then A1 is                                   */
    475  /*                                                                           */
    476  /*    A1 = { H({ unq(username-value), ":", unq(realm-value), ":", passwd }), */
    477  /*         ":", nonce-value, ":", cnonce-value }                             */
    478  /*****************************************************************************/
    479 
    480 	if (saslc__mech_digestmd5_userhash(ms, userhash) == -1)
    481 		return NULL;
    482 
    483 	if (ms->rdata.authzid == NULL)
    484 		plen = asprintf(&tmp1, ":%s:%s",
    485 		    ms->cdata.nonce, ms->rdata.cnonce);
    486 	else {
    487 		if ((unq_authzid = unq(ms->rdata.authzid)) == NULL)
    488 			return NULL;
    489 
    490 		plen = asprintf(&tmp1, ":%s:%s:%s",
    491 		    ms->cdata.nonce, ms->rdata.cnonce, unq_authzid);
    492 		free(unq_authzid);
    493 	}
    494 	if (plen == -1)
    495 		return NULL;
    496 	len = plen;
    497 
    498 	tmp2 = malloc(MD5_DIGEST_LENGTH + len);
    499 	if (tmp2 == NULL) {
    500 		free(tmp1);
    501 		return NULL;
    502 	}
    503 	memcpy(tmp2, userhash, MD5_DIGEST_LENGTH);
    504 	memcpy(tmp2 + MD5_DIGEST_LENGTH, tmp1, len);
    505 	free(tmp1);
    506 
    507 	saslc__crypto_md5_hash(tmp2, MD5_DIGEST_LENGTH + len, a1hash);
    508 	free(tmp2);
    509 
    510 	r = saslc__crypto_hash_to_hex(a1hash);
    511 	setup_qop_keys(ms, a1hash);
    512 	return r;
    513 }
    514 
    515 /**
    516  * @brief computes A2 hash value (see: RFC2831)
    517  * @param ms mechanism session
    518  * @param method string indicating method "AUTHENTICATE" or ""
    519  * @return hash converted to ascii
    520  */
    521 static char *
    522 saslc__mech_digestmd5_a2(saslc__mech_digestmd5_sess_t *ms,
    523     const char *method)
    524 {
    525 	char *tmp, *r;
    526 	int rval;
    527 	/*****************************************************************/
    528 	/* If the "qop" directive's value is "auth", then A2 is:         */
    529 	/*                                                               */
    530 	/*    A2       = { "AUTHENTICATE:", digest-uri-value }           */
    531 	/*                                                               */
    532 	/* If the "qop" value is "auth-int" or "auth-conf" then A2 is:   */
    533 	/*                                                               */
    534 	/*    A2       = { "AUTHENTICATE:", digest-uri-value,            */
    535 	/*               ":00000000000000000000000000000000" }           */
    536 	/*****************************************************************/
    537 
    538 	rval = -1;
    539 	switch(ms->mech_sess.qop) {
    540 	case QOP_NONE:
    541 		rval = asprintf(&tmp, "%s:%s", method,
    542 		    ms->rdata.digesturi);
    543 		break;
    544 	case QOP_INT:
    545 	case QOP_CONF:
    546 		rval = asprintf(&tmp,
    547 		    "%s:%s:00000000000000000000000000000000",
    548 		    method, ms->rdata.digesturi);
    549 		break;
    550 	}
    551 	if (rval == -1)
    552 		return NULL;
    553 
    554 	r = saslc__crypto_md5_hex(tmp, strlen(tmp));
    555 	free(tmp);
    556 	return r;
    557 }
    558 
    559 /**
    560  * @brief computes result hash.
    561  * @param ms mechanism session
    562  * @param a1 A1 hash value
    563  * @param a2 A2 hash value
    564  * @return hash converted to ascii, NULL on failure.
    565  */
    566 static char *
    567 saslc__mech_digestmd5_rhash(saslc__mech_digestmd5_sess_t *ms,
    568     const char *a1, const char *a2)
    569 {
    570 	char *tmp, *r;
    571 	/******************************************************************/
    572 	/* response-value  =                                              */
    573 	/*    HEX( KD ( HEX(H(A1)),                                       */
    574 	/*            { nonce-value, ":" nc-value, ":",                   */
    575 	/*              cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) */
    576 	/******************************************************************/
    577 
    578 	if (asprintf(&tmp, "%s:%s:%08x:%s:%s:%s", a1, ms->cdata.nonce,
    579 		ms->rdata.nonce_cnt, ms->rdata.cnonce,
    580 		saslc__mech_qop_name(ms->mech_sess.qop), a2)
    581 	    == -1)
    582 		return NULL;
    583 
    584 	r = saslc__crypto_md5_hex(tmp, strlen(tmp));
    585 	free(tmp);
    586 	return r;
    587 }
    588 
    589 /**
    590  * @brief building response string. Basing on
    591  * session and mechanism properties.
    592  * @param ms mechanism session
    593  * @param method string indicating method: "AUTHENTICATE" or ""
    594  * @return response string, NULL on failure.
    595  */
    596 static char *
    597 saslc__mech_digestmd5_response(saslc__mech_digestmd5_sess_t *ms,
    598     const char *method)
    599 {
    600 	char *r, *a1, *a2;
    601 
    602 	/******************************************************************/
    603 	/* charset = "charset" "=" "utf-8"                                */
    604 	/*                                                                */
    605 	/* This directive, if present, specifies that the client has used */
    606 	/* UTF-8 [UTF-8] encoding for the username, realm and             */
    607 	/* password. If present, the username, realm and password are in  */
    608 	/* Unicode, prepared using the "SASLPrep" profile [SASLPrep] of   */
    609 	/* the "stringprep" algorithm [StringPrep] and than encoded as    */
    610 	/* UTF-8 [UTF-8].  If not present, the username and password must */
    611 	/* be encoded in ISO 8859-1 [ISO-8859] (of which US-ASCII         */
    612 	/* [USASCII] is a subset). The client should send this directive  */
    613 	/* only if the server has indicated it supports UTF-8             */
    614 	/* [UTF-8]. The directive is needed for backwards compatibility   */
    615 	/* with HTTP Digest, which only supports ISO 8859-1.              */
    616 	/******************************************************************/
    617 	/*
    618 	 * NOTE: We don't set charset in the response, so this is not
    619 	 * an issue here.  However, see the note in stringprep_realms()
    620 	 * which is called when processing the challenge.
    621 	 */
    622 	/******************************************************************/
    623 	/* response-value  =                                              */
    624 	/*    HEX( KD ( HEX(H(A1)),                                       */
    625 	/*            { nonce-value, ":" nc-value, ":",                   */
    626 	/*              cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) */
    627 	/******************************************************************/
    628 
    629 	r = NULL;
    630 
    631 	a1 = saslc__mech_digestmd5_a1(ms);
    632 	if (a1 == NULL)
    633 		return NULL;
    634 
    635 	a2 = saslc__mech_digestmd5_a2(ms, method);
    636 	if (a2 != NULL) {
    637 		r = saslc__mech_digestmd5_rhash(ms, a1, a2);
    638 		free(a2);
    639 	}
    640 	free(a1);
    641 	return r;
    642 }
    643 
    644 /**
    645  * @brief Choose a string from a user provided host qualified list,
    646  * i.e., a comma delimited list with possible hostname qualifiers on
    647  * the elements.
    648  * @param hqlist a comma delimited list with entries of the form
    649  * "[hostname:]string".
    650  * @param hostname the hostname to use in the selection.
    651  * @param rval pointer to location for returned string.  Set to NULL
    652  * if none found, otherwise set to strdup(3) of the string found.
    653  * @return 0 on success, -1 on failure (no memory).
    654  *
    655  * NOTE: hqlist and rval must not be NULL.
    656  * NOTE: this allocates memory for its output and the caller is
    657  * responsible for freeing it.
    658  */
    659 static int
    660 choose_from_hqlist(const char *hqlist, const char *hostname, char **rval)
    661 {
    662 	list_t *l, *list;
    663 	size_t len;
    664 	char *p;
    665 
    666 	if (saslc__list_parse(&list, hqlist) == -1)
    667 		return -1;	/* no memory */
    668 
    669 	/*
    670 	 * If the user provided a list and the caller provided a
    671 	 * hostname, pick the first string from the list that
    672 	 * corresponds to the hostname.
    673 	 */
    674 	if (hostname != NULL) {
    675 		len = strlen(hostname);
    676 		for (l = list; l != NULL; l = l->next) {
    677 			p = l->value + len;
    678 			if (*p != ':' ||
    679 			    strncasecmp(l->value, hostname, len) != 0)
    680 				continue;
    681 
    682 			if (*(++p) != '\0' && isalnum((unsigned char)*p)) {
    683 				if ((p = strdup(p)) == NULL)
    684 					goto nomem;
    685 				goto done;
    686 			}
    687 		}
    688 	}
    689 	/*
    690 	 * If one couldn't be found, look for first string in the list
    691 	 * without a hostname specifier.
    692 	 */
    693 	p = NULL;
    694 	for (l = list; l != NULL; l = l->next) {
    695 		if (strchr(l->value, ':') == NULL) {
    696 			if ((p = strdup(l->value)) == NULL)
    697 				goto nomem;
    698 			goto done;
    699 		}
    700 	}
    701  done:
    702 	saslc__list_free(list);
    703 	*rval = p;
    704 	return 0;
    705  nomem:
    706 	saslc__list_free(list);
    707 	return -1;
    708 }
    709 
    710 /**
    711  * @brief builds digesturi string
    712  * @param serv_type type of service to use, e.g., "smtp"
    713  * @param host fully-qualified canonical DNS name of host
    714  * @param serv_name service name if it is replicated via DNS records; may
    715  * be NULL.
    716  * @return digesturi string, NULL on failure.
    717  */
    718 static char *
    719 saslc__mech_digestmd5_digesturi(saslc_sess_t *sess, const char *serv_host)
    720 {
    721 	const char *serv_list;
    722 	char *serv_name;
    723 	const char *serv_type;
    724 	char *r;
    725 	int rv;
    726 
    727 	serv_type = saslc_sess_getprop(sess, SASLC_DIGESTMD5_SERVICE);
    728 	if (serv_type == NULL) {
    729 		saslc__error_set(ERR(sess), ERROR_MECH,
    730 		    "service is required for an authentication");
    731 		return NULL;
    732 	}
    733 	serv_list = saslc_sess_getprop(sess, SASLC_DIGESTMD5_SERVNAME);
    734 	if (serv_list == NULL)
    735 		serv_name = NULL;
    736 	else if (choose_from_hqlist(serv_list, serv_host, &serv_name) == -1)
    737 		goto nomem;
    738 
    739 	saslc__msg_dbg("%s: serv_name='%s'", __func__,
    740 	    serv_name ? serv_name : "<null>");
    741 
    742 	/****************************************************************/
    743 	/* digest-uri       = "digest-uri" "=" <"> digest-uri-value <">	*/
    744 	/* digest-uri-value  = serv-type "/" host [ "/" serv-name ]	*/
    745 	/*								*/
    746 	/* If the service is not replicated, or the serv-name is	*/
    747 	/* identical to the host, then the serv-name component MUST be	*/
    748 	/* omitted.  The service is considered to be replicated if the	*/
    749 	/* client's service-location process involves resolution using	*/
    750 	/* standard DNS lookup operations, and if these operations	*/
    751 	/* involve DNS records (such as SRV, or MX) which resolve one	*/
    752 	/* DNS name into a set of other DNS names.			*/
    753 	/****************************************************************/
    754 
    755 	rv = serv_name == NULL || strcmp(serv_host, serv_name) == 0
    756 	    ? asprintf(&r, "%s/%s", serv_type, serv_host)
    757 	    : asprintf(&r, "%s/%s/%s", serv_type, serv_host, serv_name);
    758 	if (serv_name != NULL)
    759 		free(serv_name);
    760 	if (rv == -1)
    761 		goto nomem;
    762 
    763 	saslc__msg_dbg("%s: digest-uri='%s'", __func__, r);
    764 	return r;
    765  nomem:
    766 	saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
    767 	return NULL;
    768 }
    769 
    770 /**
    771  * @brief creates client's nonce. (Basing on crypto.h)
    772  * @param s length of nonce
    773  * @return nonce string, NULL on failure.
    774  */
    775 static char *
    776 saslc__mech_digestmd5_nonce(size_t s)
    777 {
    778 	char *nonce;
    779 	char *r;
    780 
    781 	nonce = saslc__crypto_nonce(s);
    782 	if (nonce == NULL)
    783 		return NULL;
    784 
    785 	if (saslc__crypto_encode_base64(nonce, s, &r, NULL) == -1)
    786 		return NULL;
    787 	free(nonce);
    788 
    789 	return r;
    790 }
    791 
    792 /**
    793  * @brief strip quotes from a string (modifies the string)
    794  * @param str the string
    795  * @return string without quotes.
    796  */
    797 static char *
    798 strip_quotes(char *str)
    799 {
    800 	char *p;
    801 	size_t len;
    802 
    803 	if (*str != '"')
    804 		return str;
    805 
    806 	len = strlen(str);
    807 	p = str + len;
    808 	if (len < 2 || p[-1] != '"')
    809 		return str;
    810 
    811 	p[-1] = '\0';
    812 	return ++str;
    813 }
    814 
    815 /**
    816  * @brief convert a list of realms from utf-8 to iso8859-q if necessary.
    817  * @param is_utf8 the characterset of the realms (true if utf8)
    818  * @param realms the realm list
    819  */
    820 static int
    821 stringprep_realms(bool is_utf8, list_t *realms)
    822 {
    823 	list_t *l;
    824 	char *utf8, *iso8859;
    825 
    826 	/******************************************************************/
    827 	/* If at least one realm is present and the charset directive is  */
    828 	/* also specified (which means that realm(s) are encoded as       */
    829 	/* UTF-8), the client should prepare each instance of realm using */
    830 	/* the "SASLPrep" profile [SASLPrep] of the "stringprep"          */
    831 	/* algorithm [StringPrep]. If preparation of a realm instance     */
    832 	/* fails or results in an empty string, the client should abort   */
    833 	/* the authentication exchange.                                   */
    834 	/******************************************************************/
    835 	if (!is_utf8)
    836 		return 0;
    837 
    838 	for (l = realms; l != NULL; l = l->next) {
    839 		utf8 = l->value;
    840 		if (utf8_to_8859_1(utf8, &iso8859) == -1)
    841 			return -1;
    842 		free(utf8);
    843 		l->value = iso8859;
    844 	}
    845 	return 0;
    846 }
    847 
    848 /**
    849  * @brief choose a realm from a list of possible realms provided by the server
    850  * @param sess the session context
    851  * @param realms the list of realms
    852  * @return our choice of realm or NULL on failure.  It is the user's
    853  * responsibility to free the memory allocated for the return string.
    854  */
    855 static char *
    856 choose_realm(saslc_sess_t *sess, const char *hostname, list_t *realms)
    857 {
    858 	const char *user_realms;
    859 	list_t *l;
    860 	char *p = NULL;
    861 
    862 	/*****************************************************************/
    863 	/* The realm containing the user's account. This directive is	 */
    864 	/* required if the server provided any realms in the		 */
    865 	/* "digest-challenge", in which case it may appear exactly once  */
    866 	/* and its value SHOULD be one of those realms. If the directive */
    867 	/* is missing, "realm-value" will set to the empty string when	 */
    868 	/* computing A1 (see below for details).			 */
    869 	/*****************************************************************/
    870 
    871 	user_realms = saslc_sess_getprop(sess, SASLC_DIGESTMD5_REALM);
    872 
    873 	/*
    874 	 * If the challenge provided no realms, try to pick one from a
    875 	 * user specified list, which may be keyed by the hostname.
    876 	 * If one can't be found, return NULL;
    877 	 */
    878 	if (realms == NULL) {
    879 		/*
    880 		 * No realm was supplied in challenge.  Figure out a
    881 		 * plausable default.
    882 		 */
    883 		if (user_realms == NULL) {
    884 			saslc__error_set(ERR(sess), ERROR_MECH,
    885 			    "cannot determine the realm");
    886 			return NULL;
    887 		}
    888 		if (choose_from_hqlist(user_realms, hostname, &p) == -1)
    889 			goto nomem;
    890 
    891 		if (p == NULL)
    892 			saslc__error_set(ERR(sess), ERROR_MECH,
    893 			    "cannot choose a realm");
    894 		return p;
    895 	}
    896 
    897 	/************************************************************/
    898 	/* Multiple realm directives are allowed, in which case the */
    899 	/* user or client must choose one as the realm for which to */
    900 	/* supply to username and password.                         */
    901 	/************************************************************/
    902 	/*
    903 	 * If the user hasn't specified any realms, or we can't find
    904 	 * one from the user provided list, just take the first realm
    905 	 * from the challenge.
    906 	 */
    907 	if (user_realms == NULL)
    908 		goto use_1st_realm;
    909 
    910 	if (choose_from_hqlist(user_realms, hostname, &p) == -1)
    911 		goto nomem;
    912 
    913 	if (p == NULL)
    914 		goto use_1st_realm;
    915 
    916 	/*
    917 	 * If we found a matching user provide realm, make sure it is
    918 	 * on the list of realms.  If it isn't, just take the first
    919 	 * realm in the challenge.
    920 	 */
    921 	for (l = realms; l != NULL; l = l->next) {
    922 		if (strcasecmp(p, l->value) == 0)
    923 			return p;
    924 	}
    925  use_1st_realm:
    926 	free(p);
    927 	if ((p = strdup(realms->value)) == NULL)
    928 		goto nomem;
    929 	return p;
    930  nomem:
    931 	saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
    932 	return NULL;
    933 }
    934 
    935 /**
    936  * @brief destroy a cipher context
    937  * @param ctx cipher context
    938  * @return nothing
    939  */
    940 static void
    941 cipher_context_destroy(cipher_context_t *ctx)
    942 {
    943 
    944 	if (ctx != NULL) {
    945 		if (ctx->evp_ctx != NULL)
    946 			EVP_CIPHER_CTX_free(ctx->evp_ctx);
    947 		free(ctx);
    948 	}
    949 }
    950 
    951 /**
    952  * @brief slide the bits from 7 bytes into the high 7 bits of 8 bites
    953  * @param ikey input key
    954  * @param okey output key
    955  *
    956  * This matches cyrus-sasl 2.1.23
    957  */
    958 static inline void
    959 slidebits(uint8_t *ikey, uint8_t *okey)
    960 {
    961 
    962 	okey[0] = ikey[0] << 0;
    963 	okey[1] = ikey[0] << 7 | (unsigned)ikey[1] >> 1;
    964 	okey[2] = ikey[1] << 6 | (unsigned)ikey[2] >> 2;
    965 	okey[3] = ikey[2] << 5 | (unsigned)ikey[3] >> 3;
    966 	okey[4] = ikey[3] << 4 | (unsigned)ikey[4] >> 4;
    967 	okey[5] = ikey[4] << 3 | (unsigned)ikey[5] >> 5;
    968 	okey[6] = ikey[5] << 2 | (unsigned)ikey[6] >> 6;
    969 	okey[7] = ikey[6] << 1;
    970 }
    971 
    972 /**
    973  * @brief convert our key to a DES key
    974  * @param key our key
    975  * @param keylen our key length
    976  * @param deskey the key in DES format
    977  *
    978  * NOTE: The openssl implementations of "des" and "3des" expect their
    979  * keys to be in the high 7 bits of 8 bytes and 16 bytes,
    980  * respectively.  Thus, our key length will be 7 and 14 bytes,
    981  * respectively.
    982  */
    983 static void
    984 make_deskey(uint8_t *key, size_t keylen, uint8_t *deskey)
    985 {
    986 
    987 	assert(keylen == 7 || keylen == 14);
    988 
    989 	slidebits(deskey + 0, key + 0);
    990 	if (keylen == 14)
    991 		slidebits(deskey + 7, key + 7);
    992 }
    993 
    994 /**
    995  * @brief create a cipher context, including EVP cipher initialization.
    996  * @param sess session context
    997  * @param cipher cipher to use
    998  * @param do_enc encode context if set, decode context if 0
    999  * @param key crypt key to use
   1000  * @return cipher context, or NULL on error
   1001  */
   1002 static cipher_context_t *
   1003 cipher_context_create(saslc_sess_t *sess, cipher_t cipher, int do_enc, uint8_t *key)
   1004 {
   1005 #define AES_IV_MAGIC		"aes-128"
   1006 #define AES_IV_MAGIC_LEN	(sizeof(AES_IV_MAGIC) - 1)
   1007 	static const struct cipher_ctx_tbl_s {
   1008 		cipher_t eval;			/* for error checking */
   1009 		const EVP_CIPHER *(*evp_type)(void);/* type of cipher */
   1010 		size_t keylen;			/* key length */
   1011 		ssize_t blksize;		/* block size for cipher */
   1012 		size_t ivlen;			/* initial value length */
   1013 	} cipher_ctx_tbl[] = {
   1014 		/* NB: table indexed by cipher_t */
   1015 		/* eval		 evp_type	 keylen  blksize  ivlen */
   1016 		{ CIPHER_DES,    EVP_des_cbc,       7,       8,      8 },
   1017 		{ CIPHER_3DES,   EVP_des_ede_cbc,  14,       8,      8 },
   1018 		{ CIPHER_RC4,    EVP_rc4,          16,       1,      0 },
   1019 		{ CIPHER_RC4_40, EVP_rc4,           5,       1,      0 },
   1020 		{ CIPHER_RC4_56, EVP_rc4,           7,       1,      0 },
   1021 		{ CIPHER_AES,    EVP_aes_128_cbc,  16,      16,     16 }
   1022 	};
   1023 	const struct cipher_ctx_tbl_s *ctp;
   1024 	char buf[sizeof(md5hash_t) + AES_IV_MAGIC_LEN];
   1025 	uint8_t deskey[16];
   1026 	md5hash_t aes_iv;		/* initial value buffer for aes */
   1027 	cipher_context_t *ctx;		/* cipher context */
   1028 	uint8_t *ivp;
   1029 	const char *errmsg;
   1030 	int rv;
   1031 
   1032 	/*************************************************************************/
   1033 	/* See draft-ietf-sasl-rfc2831bis-02.txt section 2.4 (mentions "aes")    */
   1034 	/* The key for the "rc4" and "aes" ciphers is all 16 bytes of Kcc or Kcs.*/
   1035 	/* The key for the "rc4-40" cipher is the first 5 bytes of Kcc or Kcs.   */
   1036 	/* The key for the "rc4-56" is the first 7 bytes of Kcc or Kcs.          */
   1037 	/* The key for "des" is the first 7 bytes of Kcc or Kcs.                 */
   1038 	/* The key for "3des" is the first 14 bytes of Kcc or Kcs.               */
   1039 	/*                                                                       */
   1040 	/* The IV used to send/receive the initial buffer of security encoded    */
   1041 	/* data for "des" and "3des" is the last 8 bytes of Kcc or Kcs. For all  */
   1042 	/* subsequent buffers the last 8 bytes of the ciphertext of the buffer   */
   1043 	/* NNN is used as the IV for the buffer (NNN + 1).                       */
   1044 	/*                                                                       */
   1045 	/* The IV for the "aes" cipher in CBC mode for messages going from the   */
   1046 	/* client to the server (IVc) consists of 16 bytes calculated as         */
   1047 	/* follows: IVc = MD5({Kcc, "aes-128"})                                  */
   1048 	/*                                                                       */
   1049 	/* The IV for the "aes" cipher in CBC mode for messages going from the   */
   1050 	/* server to the client (IVs) consists of 16 bytes calculated as         */
   1051 	/* follows: IVs = MD5({Kcs, "aes-128"})                                  */
   1052 	/*************************************************************************/
   1053 
   1054 	assert(cipher < __arraycount(cipher_ctx_tbl));
   1055 	if (cipher >= __arraycount(cipher_ctx_tbl)) {
   1056 		saslc__error_set_errno(ERR(sess), ERROR_BADARG);
   1057 		return NULL;
   1058 	}
   1059 
   1060 	ctx = malloc(sizeof(*ctx));
   1061 	if (ctx == NULL) {
   1062 		saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   1063 		return NULL;
   1064 	}
   1065 
   1066 	ctp = &cipher_ctx_tbl[cipher];
   1067 	assert(ctp->eval == cipher);
   1068 
   1069 	ctx->blksize = ctp->blksize;
   1070 
   1071 	ctx->evp_ctx = EVP_CIPHER_CTX_new();
   1072 	if (ctx->evp_ctx == NULL) {
   1073 		errmsg = "EVP_CIPHER_CTX_new failed";
   1074 		goto err;
   1075 	}
   1076 	if (EVP_CipherInit_ex(ctx->evp_ctx, ctp->evp_type(), NULL, NULL, NULL,
   1077 								do_enc) == 0) {
   1078 		errmsg = "EVP_CipherInit_ex failed";
   1079 		goto err;
   1080 	}
   1081 	if (EVP_CIPHER_CTX_set_padding(ctx->evp_ctx, 0) == 0) {
   1082 		errmsg = "EVP_CIPHER_CTX_set_padding failed";
   1083 		goto err;
   1084 	}
   1085 	ivp = NULL;
   1086 	switch (cipher) {	/* prepare key and IV */
   1087 	case CIPHER_RC4:
   1088 	case CIPHER_RC4_40:
   1089 	case CIPHER_RC4_56:
   1090 		assert(ctp->ivlen == 0);	/* no IV */
   1091 		rv = EVP_CIPHER_CTX_set_key_length(ctx->evp_ctx,
   1092 		    (int)ctp->keylen);
   1093 		if (rv == 0) {
   1094 			errmsg = "EVP_CIPHER_CTX_set_key_length failed";
   1095 			goto err;
   1096 		}
   1097 		break;
   1098 	case CIPHER_DES:
   1099 	case CIPHER_3DES:
   1100 		assert(ctp->ivlen == 8);
   1101 		ivp = key + 8;
   1102 		make_deskey(key, ctp->keylen, deskey);
   1103 		key = deskey;
   1104 		break;
   1105 	case CIPHER_AES:
   1106 		assert(ctp->ivlen == 16);
   1107 		/* IVs = MD5({Kcs, "aes-128"}) */
   1108 		memcpy(buf, key, sizeof(md5hash_t));
   1109 		memcpy(buf + sizeof(md5hash_t), AES_IV_MAGIC, AES_IV_MAGIC_LEN);
   1110 		saslc__crypto_md5_hash(buf, sizeof(buf), aes_iv);
   1111 		ivp = aes_iv;
   1112 		break;
   1113 	}
   1114 	if (EVP_CipherInit_ex(ctx->evp_ctx, NULL, NULL, key, ivp, do_enc) == 0) {
   1115 		errmsg = "EVP_CipherInit_ex 2 failed";
   1116 		goto err;
   1117 	}
   1118 	return ctx;
   1119  err:
   1120 	cipher_context_destroy(ctx);
   1121 	saslc__error_set(ERR(sess), ERROR_MECH, errmsg);
   1122 	return NULL;
   1123 
   1124 #undef AES_IV_MAGIC_LEN
   1125 #undef AES_IV_MAGIC
   1126 }
   1127 
   1128 /**
   1129  * @brief compute the necessary padding length
   1130  * @param ctx the cipher context
   1131  * @param inlen the data length to put in the packet
   1132  * @return the length of padding needed (zero if none needed)
   1133  */
   1134 static size_t
   1135 get_padlen(cipher_context_t *ctx, size_t inlen)
   1136 {
   1137 	size_t blksize;
   1138 
   1139 	if (ctx == NULL)
   1140 		return 0;
   1141 
   1142 	blksize = ctx->blksize;
   1143 	if (blksize == 1)
   1144 		return 0;
   1145 
   1146 	return blksize - ((inlen + 10) % blksize);
   1147 }
   1148 
   1149 /**
   1150  * @brief compute the packet integrity including the version and
   1151  * sequence number
   1152  * @param key the hmac_md5 hash key
   1153  * @param seqnum the sequence number
   1154  * @param in the input buffer
   1155  * @param inlen the input buffer length
   1156  * @return 0 on success, -1 on failure
   1157  */
   1158 static int
   1159 packet_integrity(md5hash_t key, uint32_t seqnum, void *in, size_t inlen,
   1160     md5hash_t mac)
   1161 {
   1162 
   1163 	be32enc(in, seqnum);
   1164 	if (saslc__crypto_hmac_md5_hash(key, MD5_DIGEST_LENGTH, in, inlen, mac)
   1165 	    == -1)
   1166 		return -1;
   1167 
   1168 	/* we keep only the first 10 bytes of the hash */
   1169 	be16enc(mac + 10, 0x0001);	/* add 2 byte version number */
   1170 	be32enc(mac + 12, seqnum);	/* add 4 byte sequence number */
   1171 	return 0;
   1172 }
   1173 
   1174 /**
   1175  * @brief encode or decode a buffer (in place)
   1176  * @param ctx the cipher context
   1177  * @param in the input buffer
   1178  * @param inlen the buffer length
   1179  * @return the length of the result left in the input buffer after
   1180  * processing, or -1 on failure.
   1181  */
   1182 static ssize_t
   1183 cipher_update(cipher_context_t *ctx, void *in, size_t inlen)
   1184 {
   1185 	int outl, rv;
   1186 	void *out;
   1187 
   1188 	out = in; /* XXX: this assumes we can encoded and decode in place */
   1189 	rv = EVP_CipherUpdate(ctx->evp_ctx, out, &outl, in, (int)inlen);
   1190 	if (rv == 0)
   1191 		return -1;
   1192 
   1193 	return outl;
   1194 }
   1195 
   1196 /**
   1197  * @brief incapsulate a message with confidentiality (sign and encrypt)
   1198  * @param ctx coder context
   1199  * @param in pointer to message to encode
   1200  * @param inlen length of message
   1201  * @param out encoded output packet (including prefixed 4 byte length field)
   1202  * @param outlen decoded output packet length
   1203  * @returns 0 on success, -1 on failure
   1204  *
   1205  * NOTE: this allocates memory for its output and the caller is
   1206  * responsible for freeing it.
   1207  *
   1208  * integrity (auth-int):
   1209  * len, HMAC(ki, {SeqNum, msg})[0..9], x0001, SeqNum
   1210  *
   1211  * confidentiality (auth-conf):
   1212  * len, CIPHER(Kc, {msg, pag, HMAC(ki, {SeqNum, msg})[0..9]}), x0001, SeqNum
   1213  */
   1214 static ssize_t
   1215 encode_buffer(coder_context_t *ctx, const void *in, size_t inlen,
   1216     void **out, size_t *outlen)
   1217 {
   1218 	void *buf;
   1219 	uint8_t *mac, *p;
   1220 	ssize_t tmplen;
   1221 	size_t buflen;
   1222 	size_t padlen;
   1223 
   1224 	padlen = get_padlen(ctx->cph_ctx, inlen);
   1225 	buflen = 4 + inlen + padlen + sizeof(md5hash_t);
   1226 	buf = malloc(buflen);
   1227 	if (buf == NULL) {
   1228 		saslc__error_set_errno(ERR(ctx->sess), ERROR_NOMEM);
   1229 		return -1;
   1230 	}
   1231 	p = buf;
   1232 	memcpy(p + 4, in, inlen);
   1233 	mac = p + 4 + inlen + padlen;
   1234 	if (packet_integrity(ctx->key, ctx->seqnum, buf, 4 + inlen, mac)
   1235 	    == -1) {
   1236 		saslc__error_set(ERR(ctx->sess), ERROR_MECH, "HMAC failed");
   1237 		free(buf);
   1238 		return -1;
   1239 	}
   1240 
   1241 	if (padlen)
   1242 		memset(p + 4 + inlen, (int)padlen, padlen);
   1243 
   1244 	if (ctx->cph_ctx != NULL) {
   1245 		if ((tmplen = cipher_update(ctx->cph_ctx, p + 4,
   1246 			 inlen + padlen + 10)) == -1) {
   1247 			saslc__error_set(ERR(ctx->sess), ERROR_MECH,
   1248 			    "cipher error");
   1249 			free(buf);
   1250 			return -1;
   1251 		}
   1252 		assert((size_t)tmplen == inlen + padlen + 10);
   1253 		if ((size_t)tmplen != inlen + padlen + 10)
   1254 			return -1;
   1255 	}
   1256 
   1257 	be32enc(buf, (uint32_t)(buflen - 4));
   1258 
   1259 	*out = buf;
   1260 	*outlen = buflen;
   1261 	ctx->seqnum++;		/* wraps at 2^32 */
   1262 	return 0;
   1263 }
   1264 
   1265 /**
   1266  * @brief decode one complete confidentiality encoded packet
   1267  * @param ctx coder context
   1268  * @param in pointer to packet, including the beginning 4 byte length field.
   1269  * @param inlen length of packet
   1270  * @param out decoded output
   1271  * @param outlen decoded output length
   1272  * @returns 0 on success, -1 on failure
   1273  *
   1274  * NOTE: this modifies the intput buffer!
   1275  * NOTE: this allocates memory for its output and the caller is
   1276  * responsible for freeing it.
   1277  *
   1278  * integrity (auth-int):
   1279  * len, HMAC(ki, {SeqNum, msg})[0..9], x0001, SeqNum
   1280  *
   1281  * confidentiality (auth-conf):
   1282  * len, CIPHER(Kc, {msg, pag, HMAC(ki, {SeqNum, msg})[0..9]}), x0001, SeqNum
   1283  */
   1284 static ssize_t
   1285 decode_buffer(coder_context_t *ctx, void *in, size_t inlen,
   1286     void **out, size_t *outlen)
   1287 {
   1288 	md5hash_t mac;
   1289 	void *buf;
   1290 	uint8_t *p;
   1291 	size_t blksize, buflen, padlen;
   1292 	ssize_t tmplen;
   1293 	uint32_t len;
   1294 
   1295 	padlen = get_padlen(ctx->cph_ctx, 1);
   1296 	if (inlen < 4 + 1 + padlen + MD5_DIGEST_LENGTH) {
   1297 		saslc__error_set(ERR(ctx->sess), ERROR_MECH,
   1298 		    "zero payload packet");
   1299 		return -1;
   1300 	}
   1301 	len = be32dec(in);
   1302 	if (len + 4 != inlen) {
   1303 		saslc__error_set(ERR(ctx->sess), ERROR_MECH,
   1304 		    "bad packet length");
   1305 		return -1;
   1306 	}
   1307 
   1308 	if (ctx->cph_ctx != NULL) {
   1309 		p = in;
   1310 		if ((tmplen = cipher_update(ctx->cph_ctx, p + 4, len - 6)) == -1) {
   1311 			saslc__error_set(ERR(ctx->sess), ERROR_MECH,
   1312 			    "cipher error");
   1313 			return -1;
   1314 		}
   1315 		assert(tmplen == (ssize_t)len - 6);
   1316 		if (tmplen != (ssize_t)len - 6)
   1317 			return -1;
   1318 	}
   1319 
   1320 	blksize = ctx->cph_ctx ? ctx->cph_ctx->blksize : 0;
   1321 	if (blksize <= 1)
   1322 		padlen = 0;
   1323 	else{
   1324 		p = in;
   1325 		padlen = p[inlen - sizeof(md5hash_t) - 1];
   1326 		if (padlen > blksize || padlen == 0) {
   1327 			saslc__error_set(ERR(ctx->sess), ERROR_MECH,
   1328 			    "invalid padding length after decode");
   1329 			return -1;
   1330 		}
   1331 	}
   1332 	if (packet_integrity(ctx->key, ctx->seqnum, in,
   1333 				inlen - padlen - sizeof(mac), mac) == -1) {
   1334 		saslc__error_set(ERR(ctx->sess), ERROR_MECH, "HMAC failed");
   1335 		return -1;
   1336 	}
   1337 
   1338 	p = in;
   1339 	p += 4 + len - MD5_DIGEST_LENGTH;
   1340 	if (memcmp(p, mac, MD5_DIGEST_LENGTH) != 0) {
   1341 		uint32_t seqnum;
   1342 
   1343 		p = in;
   1344 		seqnum = be32dec(p + inlen - 4);
   1345 		saslc__error_set(ERR(ctx->sess), ERROR_MECH,
   1346 		    seqnum != ctx->seqnum ? "invalid MAC (bad seqnum)" :
   1347 		    "invalid MAC");
   1348 		return -1;
   1349 	}
   1350 
   1351 	buflen = len - padlen - MD5_DIGEST_LENGTH;
   1352 	buf = malloc(buflen);
   1353 	if (buf == NULL) {
   1354 		saslc__error_set_errno(ERR(ctx->sess), ERROR_NOMEM);
   1355 		return -1;
   1356 	}
   1357 	p = in;
   1358 	p += 4;
   1359 	memcpy(buf, p, buflen);
   1360 
   1361 	*out = buf;
   1362 	*outlen = buflen;
   1363 	ctx->seqnum++;
   1364 	return 0;
   1365 }
   1366 
   1367 /**
   1368  * @brief add integrity or confidentiality layer
   1369  * @param sess session handle
   1370  * @param in input buffer
   1371  * @param inlen input buffer length
   1372  * @param out pointer to output buffer
   1373  * @param out pointer to output buffer length
   1374  * @return number of bytes consumed on success, 0 if insufficient data
   1375  * to process, -1 on failure
   1376  */
   1377 static ssize_t
   1378 saslc__mech_digestmd5_encode(saslc_sess_t *sess, const void *in, size_t inlen,
   1379     void **out, size_t *outlen)
   1380 {
   1381 	saslc__mech_digestmd5_sess_t *ms;
   1382 	uint8_t *buf;
   1383 	size_t buflen;
   1384 	ssize_t rval;
   1385 
   1386 	ms = sess->mech_sess;
   1387 	assert(ms->mech_sess.qop != QOP_NONE);
   1388 	if (ms->mech_sess.qop == QOP_NONE)
   1389 		return -1;
   1390 
   1391 	rval = saslc__buffer_fetch(ms->enc_ctx.buf_ctx, in, inlen, &buf, &buflen);
   1392 	if (rval == -1)
   1393 		return -1;
   1394 	if (buflen == 0) {
   1395 		*out = NULL;
   1396 		*outlen = 0;
   1397 		return rval;
   1398 	}
   1399 	if (encode_buffer(&ms->enc_ctx, buf, buflen, out, outlen) == -1)
   1400 		return -1;
   1401 
   1402 	return rval;
   1403 }
   1404 
   1405 /**
   1406  * @brief remove integrity or confidentiality layer
   1407  * @param sess session handle
   1408  * @param in input buffer
   1409  * @param inlen input buffer length
   1410  * @param out pointer to output buffer
   1411  * @param out pointer to output buffer length
   1412  * @return number of bytes consumed on success, 0 if insufficient data
   1413  * to process, -1 on failure
   1414  *
   1415  * integrity (auth-int):
   1416  * len, HMAC(ki, {SeqNum, msg})[0..9], x0001, SeqNum
   1417  *
   1418  * confidentiality (auth-conf):
   1419  * len, CIPHER(Kc, {msg, pag, HMAC(ki, {SeqNum, msg})[0..9]}), x0001, SeqNum
   1420  */
   1421 static ssize_t
   1422 saslc__mech_digestmd5_decode(saslc_sess_t *sess, const void *in, size_t inlen,
   1423     void **out, size_t *outlen)
   1424 {
   1425 	saslc__mech_digestmd5_sess_t *ms;
   1426 	uint8_t *buf;
   1427 	size_t buflen;
   1428 	ssize_t rval;
   1429 
   1430 	ms = sess->mech_sess;
   1431 	assert(ms->mech_sess.qop != QOP_NONE);
   1432 	if (ms->mech_sess.qop == QOP_NONE)
   1433 		return -1;
   1434 
   1435 	rval = saslc__buffer32_fetch(ms->dec_ctx.buf_ctx, in, inlen, &buf, &buflen);
   1436 	if (rval == -1)
   1437 		return -1;
   1438 
   1439 	if (buflen == 0) {
   1440 		*out = NULL;
   1441 		*outlen = 0;
   1442 		return rval;
   1443 	}
   1444 	if (decode_buffer(&ms->dec_ctx, buf, buflen, out, outlen) == -1)
   1445 		return -1;
   1446 
   1447 	return rval;
   1448 }
   1449 
   1450 /************************************************************************
   1451  * XXX: Share with mech_gssapi.c?  They are almost identical.
   1452  */
   1453 /**
   1454  * @brief choose the best qop based on what was provided by the
   1455  * challenge and a possible user mask.
   1456  * @param sess the session context
   1457  * @param qop_flags the qop flags parsed from the challenge string
   1458  * @return the selected saslc__mech_sess_qop_t or -1 if no match
   1459  */
   1460 static int
   1461 choose_qop(saslc_sess_t *sess, uint32_t qop_flags)
   1462 {
   1463 	list_t *list;
   1464 	const char *user_qop;
   1465 
   1466 	if (qop_flags == 0)	/* no qop spec in challenge (it's optional) */
   1467 		return QOP_NONE;
   1468 
   1469 	qop_flags &= DEFAULT_QOP_MASK;
   1470 	user_qop = saslc_sess_getprop(sess, SASLC_DIGESTMD5_QOPMASK);
   1471 	if (user_qop != NULL) {
   1472 		if (saslc__list_parse(&list, user_qop) == -1) {
   1473 			saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   1474 			return -1;
   1475 		}
   1476 		qop_flags &= saslc__mech_qop_list_flags(list);
   1477 		saslc__list_free(list);
   1478 	}
   1479 
   1480 	/*
   1481 	 * Select the most secure supported qop.
   1482 	 */
   1483 	if ((qop_flags & F_QOP_CONF) != 0)
   1484 		return QOP_CONF;
   1485 	if ((qop_flags & F_QOP_INT) != 0)
   1486 		return QOP_INT;
   1487 	if ((qop_flags & F_QOP_NONE) != 0)
   1488 		return QOP_NONE;
   1489 
   1490 	saslc__error_set(ERR(sess), ERROR_MECH,
   1491 	    "cannot choose an acceptable qop");
   1492 	return -1;
   1493 }
   1494 /************************************************************************/
   1495 
   1496 /**
   1497  * @brief choose the best cipher based on what was provided by the
   1498  * challenge and a possible user mask.
   1499  * @param sess the session context
   1500  * @param cipher_flags the cipher flags parsed from the challenge
   1501  * string
   1502  * @return the selected cipher_t
   1503  */
   1504 static int
   1505 choose_cipher(saslc_sess_t *sess, unsigned int cipher_flags)
   1506 {
   1507 	list_t *list;
   1508 	unsigned int cipher_mask;
   1509 	const char *user_cipher;
   1510 
   1511 	if (cipher_flags == 0) {
   1512 		saslc__error_set(ERR(sess), ERROR_MECH,
   1513 		    "no cipher spec in challenge");
   1514 		return -1;
   1515 	}
   1516 	cipher_mask = DEFAULT_CIPHER_MASK;
   1517 	user_cipher = saslc_sess_getprop(sess, SASLC_DIGESTMD5_CIPHERMASK);
   1518 	if (user_cipher != NULL) {
   1519 		if (saslc__list_parse(&list, user_cipher) == -1) {
   1520 			saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   1521 			return -1;
   1522 		}
   1523 		cipher_mask = cipher_list_flags(list);
   1524 		saslc__list_free(list);
   1525 	}
   1526 	cipher_flags &= cipher_mask;
   1527 
   1528 	/*
   1529 	 * Select the most secure cipher supported.
   1530 	 * XXX: Is the order here right?
   1531 	 */
   1532 	if ((cipher_flags & F_CIPHER_AES) != 0)
   1533 		return CIPHER_AES;
   1534 	if ((cipher_flags & F_CIPHER_3DES) != 0)
   1535 		return CIPHER_3DES;
   1536 	if ((cipher_flags & F_CIPHER_DES) != 0)
   1537 		return CIPHER_DES;
   1538 	if ((cipher_flags & F_CIPHER_RC4) != 0)
   1539 		return CIPHER_RC4;
   1540 	if ((cipher_flags & F_CIPHER_RC4_56) != 0)
   1541 		return CIPHER_RC4_56;
   1542 	if ((cipher_flags & F_CIPHER_RC4_40) != 0)
   1543 		return CIPHER_RC4_40;
   1544 
   1545 	saslc__error_set(ERR(sess), ERROR_MECH,
   1546 	    "qop \"auth-conf\" requires a cipher");
   1547 	return -1;
   1548 }
   1549 
   1550 /**
   1551  * @brief get the challenge_t value corresponding to a challenge key
   1552  * string.
   1553  * @param key challenge key string
   1554  * @return the challenge_t value including CHALLENGE_IGNORE (-1) if
   1555  * the key is not recognized
   1556  */
   1557 static challenge_t
   1558 get_challenge_t(const char *key)
   1559 {
   1560 	static const struct {
   1561 		const char *key;
   1562 		challenge_t value;
   1563 	} challenge_keys[] = {
   1564 		{ "realm",	CHALLENGE_REALM     },
   1565 		{ "nonce",	CHALLENGE_NONCE     },
   1566 		{ "qop",	CHALLENGE_QOP       },
   1567 		{ "stale",	CHALLENGE_STALE     },
   1568 		{ "maxbuf",	CHALLENGE_MAXBUF    },
   1569 		{ "charset",	CHALLENGE_CHARSET   },
   1570 		{ "algorithm",	CHALLENGE_ALGORITHM },
   1571 		{ "cipher",	CHALLENGE_CIPHER    }
   1572 	};
   1573 	size_t i;
   1574 
   1575 	for (i = 0; i < __arraycount(challenge_keys); i++) {
   1576 		if (strcasecmp(key, challenge_keys[i].key) == 0)
   1577 			return challenge_keys[i].value;
   1578 	}
   1579 	return CHALLENGE_IGNORE;
   1580 }
   1581 
   1582 /**
   1583  * @brief parses challenge and store result in mech_sess.
   1584  * @param mech_sess session where parsed data will be stored
   1585  * @param challenge challenge
   1586  * @return 0 on success, -1 on failure.
   1587  */
   1588 static int
   1589 saslc__mech_digestmd5_parse_challenge(saslc_sess_t *sess, const char *challenge)
   1590 {
   1591 	saslc__mech_digestmd5_sess_t *ms;
   1592 	list_t *list, *n;
   1593 	list_t *tmp_list;
   1594 	cdata_t *cdata;
   1595 	size_t maxbuf;
   1596 	uint32_t tmp_flags;
   1597 	int rv;
   1598 
   1599 	/******************************************************************/
   1600 	/* digest-challenge  =                                            */
   1601 	/*     1#( realm | nonce | qop-options | stale | server_maxbuf |  */
   1602 	/*      charset | algorithm | cipher-opts | auth-param )          */
   1603 	/******************************************************************/
   1604 
   1605 	saslc__msg_dbg("challenge: '%s'\n", challenge);
   1606 
   1607 	ms = sess->mech_sess;
   1608 	cdata = &ms->cdata;
   1609 
   1610 	rv = -1;
   1611 	memset(cdata, 0, sizeof(*cdata));
   1612 	if (saslc__list_parse(&list, challenge) == -1) {
   1613 		saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   1614 		return -1;
   1615 	}
   1616 	saslc__list_log(list, "parse list:\n");
   1617 	for (n = list; n != NULL; n = n->next) {
   1618 		char *key;
   1619 		char *val;
   1620 
   1621 		/* Split string into key and val */
   1622 		key = n->value;
   1623 		val = strchr(key, '=');
   1624 		if (val == NULL)
   1625 			goto no_mem;
   1626 		*val = '\0';
   1627 		val = strip_quotes(val + 1);
   1628 
   1629 		saslc__msg_dbg("key='%s' val='%s'\n", key, val);
   1630 		switch (get_challenge_t(key)) {
   1631 		case CHALLENGE_REALM:
   1632 			/**************************************************/
   1633 			/* realm       = "realm" "=" <"> realm-value <">  */
   1634 			/* realm-value = qdstr-val                        */
   1635 			/*                                                */
   1636 			/* This directive is optional; if not present,    */
   1637 			/* the client SHOULD solicit it from the user or  */
   1638 			/* be able to compute a default; a plausible      */
   1639 			/* default might be the realm supplied by the     */
   1640 			/* user when they logged in to the client system. */
   1641 			/* Multiple realm directives are allowed, in      */
   1642 			/* which case the user or client must choose one  */
   1643 			/* as the realm for which to supply to username   */
   1644 			/* and password.                                  */
   1645 			/**************************************************/
   1646 			if (saslc__list_append(&cdata->realm, val) == -1)
   1647 				goto no_mem;
   1648 			break;
   1649 		case CHALLENGE_NONCE:
   1650 			/**************************************************/
   1651 			/* nonce       = "nonce" "=" <"> nonce-value <">  */
   1652 			/* nonce-value = *qdtext                          */
   1653 			/*                                                */
   1654 			/* This directive is required and MUST appear     */
   1655 			/* exactly once; if not present, or if multiple   */
   1656 			/* instances are present, the client should abort */
   1657 			/* the authentication exchange.                   */
   1658 			/**************************************************/
   1659 			if (cdata->nonce != NULL) {
   1660 				saslc__error_set(ERR(sess), ERROR_MECH,
   1661 				    "multiple nonce in challenge");
   1662 				goto out;
   1663 			}
   1664 			cdata->nonce = strdup(val);
   1665 			if (cdata->nonce == NULL)
   1666 				goto no_mem;
   1667 			break;
   1668 		case CHALLENGE_QOP:
   1669 			/**************************************************/
   1670 			/* qop-options = "qop" "=" <"> qop-list <">       */
   1671 			/* qop-list    = 1#qop-value                      */
   1672 			/* qop-value   = "auth" | "auth-int" |            */
   1673 			/*               "auth-conf" | token              */
   1674 			/*                                                */
   1675 			/* This directive is optional; if not present it  */
   1676 			/* defaults to "auth".  The client MUST ignore    */
   1677 			/* unrecognized options; if the client recognizes */
   1678 			/* no option, it should abort the authentication  */
   1679 			/* exchange.                                      */
   1680 			/**************************************************/
   1681 			if (saslc__list_parse(&tmp_list, val) == -1)
   1682 				goto no_mem;
   1683 			saslc__list_log(tmp_list, "qop list:\n");
   1684 			tmp_flags = saslc__mech_qop_list_flags(tmp_list);
   1685 			saslc__list_free(tmp_list);
   1686 			if (tmp_flags == 0) {
   1687 				saslc__error_set(ERR(sess), ERROR_MECH,
   1688 				    "qop required in challenge");
   1689 				goto out;
   1690 			}
   1691 			cdata->qop_flags |= tmp_flags;
   1692 			break;
   1693 		case CHALLENGE_STALE:
   1694 			/**************************************************/
   1695 			/* stale = "stale" "=" "true"                     */
   1696 			/*                                                */
   1697 			/* This directive may appear at most once; if     */
   1698 			/* multiple instances are present, the client     */
   1699 			/* should abort the authentication exchange.      */
   1700 			/**************************************************/
   1701 			if (cdata->stale) {
   1702 				saslc__error_set(ERR(sess), ERROR_MECH,
   1703 				    "multiple stale in challenge");
   1704 				goto out;
   1705 			}
   1706 			if (strcasecmp(val, "true") != 0) {
   1707 				saslc__error_set(ERR(sess), ERROR_MECH,
   1708 				    "stale must be true");
   1709 				goto out;
   1710 			}
   1711 			cdata->stale = true;
   1712 			break;
   1713 		case CHALLENGE_MAXBUF:
   1714 			/**************************************************/
   1715 			/* maxbuf-value = 1*DIGIT                         */
   1716 			/*                                                */
   1717 			/* The value MUST be bigger than 16 and smaller   */
   1718 			/* or equal to 16777215 (i.e.  2**24-1). If this  */
   1719 			/* directive is missing, the default value is     */
   1720 			/* 65536. This directive may appear at most once; */
   1721 			/* if multiple instances are present, the client  */
   1722 			/* MUST abort the authentication exchange.        */
   1723 			/**************************************************/
   1724 			if (cdata->maxbuf != 0) {
   1725 				saslc__error_set(ERR(sess), ERROR_MECH,
   1726 				    "multiple maxbuf in challenge");
   1727 				goto out;
   1728 			}
   1729 			maxbuf = (size_t)strtoul(val, NULL, 10);
   1730 			if (INVALID_MAXBUF(maxbuf)) {
   1731 				saslc__error_set(ERR(sess), ERROR_MECH,
   1732 				    "invalid maxbuf in challenge");
   1733 				goto out;
   1734 			}
   1735 			cdata->maxbuf = maxbuf;
   1736 			break;
   1737 		case CHALLENGE_CHARSET:
   1738 			/**************************************************/
   1739 			/* charset = "charset" "=" "utf-8"                */
   1740 			/*                                                */
   1741 			/* This directive may appear at most once; if     */
   1742 			/* multiple instances are present, the client     */
   1743 			/* should abort the authentication exchange.      */
   1744 			/**************************************************/
   1745 			if (cdata->utf8) {
   1746 				saslc__error_set(ERR(sess), ERROR_MECH,
   1747 				    "multiple charset in challenge");
   1748 				goto out;
   1749 			}
   1750 			if (strcasecmp(val, "utf-8") != 0) {
   1751 				saslc__error_set(ERR(sess), ERROR_MECH,
   1752 				    "charset != \"utf-8\" in challenge");
   1753 				goto out;
   1754 			}
   1755 			cdata->utf8 = true;
   1756 			break;
   1757 		case CHALLENGE_ALGORITHM:
   1758 			/**************************************************/
   1759 			/* algorithm = "algorithm" "=" "md5-sess"         */
   1760 			/*                                                */
   1761 			/* This directive is required and MUST appear     */
   1762 			/* exactly once; if not present, or if multiple   */
   1763 			/* instances are present, the client should abort */
   1764 			/* the authentication exchange.                   */
   1765 			/**************************************************/
   1766 			if (cdata->algorithm) {
   1767 				saslc__error_set(ERR(sess), ERROR_MECH,
   1768 				    "multiple algorithm in challenge");
   1769 				goto out;
   1770 			}
   1771 			if (strcasecmp(val, "md5-sess") != 0) {
   1772 				saslc__error_set(ERR(sess), ERROR_MECH,
   1773 				    "algorithm != \"md5-sess\" in challenge");
   1774 				goto out;
   1775 			}
   1776 			cdata->algorithm = true;
   1777 			break;
   1778 		case CHALLENGE_CIPHER:
   1779 			/**************************************************/
   1780 			/* cipher-opts = "cipher" "=" <"> 1#cipher-val <">*/
   1781 			/* cipher-val  = "3des" | "des" | "rc4-40" |      */
   1782 			/*               "rc4" |"rc4-56" | "aes" |        */
   1783 			/*               token                            */
   1784 			/*                                                */
   1785 			/* This directive must be present exactly once if */
   1786 			/* "auth-conf" is offered in the "qop-options"    */
   1787 			/* directive, in which case the "3des" cipher is  */
   1788 			/* mandatory-to-implement. The client MUST ignore */
   1789 			/* unrecognized options; if the client recognizes */
   1790 			/* no option, it should abort the authentication  */
   1791 			/* exchange.                                      */
   1792 			/**************************************************/
   1793 			if (saslc__list_parse(&tmp_list, val) == -1)
   1794 				goto no_mem;
   1795 			saslc__list_log(tmp_list, "cipher list:\n");
   1796 			tmp_flags = cipher_list_flags(tmp_list);
   1797 			saslc__list_free(tmp_list);
   1798 			if (tmp_flags == 0) {
   1799 				saslc__error_set(ERR(sess), ERROR_MECH,
   1800 				    "unknown cipher");
   1801 				goto out;
   1802 			}
   1803 			cdata->cipher_flags |= tmp_flags;
   1804 			break;
   1805 		case CHALLENGE_IGNORE:
   1806 			/**************************************************/
   1807 			/* auth-param = token "=" ( token |               */
   1808 			/*                          quoted-string )       */
   1809 			/*                                                */
   1810 			/* The client MUST ignore any unrecognized        */
   1811 			/* directives.                                    */
   1812 			/**************************************************/
   1813 			break;
   1814 		}
   1815 	}
   1816 
   1817 	/*
   1818 	 * make sure realms are in iso8859-1
   1819 	 */
   1820 	if (stringprep_realms(cdata->utf8, cdata->realm) == -1) {
   1821 		saslc__error_set(ERR(sess), ERROR_MECH,
   1822 		    "unable to convert realms in challenge from "
   1823 		    "\"utf-8\" to iso8859-1");
   1824 		goto out;
   1825 	}
   1826 
   1827 	/*
   1828 	 * test for required options
   1829 	 */
   1830 	if (cdata->nonce == NULL) {
   1831 		saslc__error_set(ERR(sess), ERROR_MECH,
   1832 		    "nonce required in challenge");
   1833 		goto out;
   1834 	}
   1835 
   1836 	if (!cdata->algorithm) {
   1837 		saslc__error_set(ERR(sess), ERROR_MECH,
   1838 		    "algorithm required in challenge");
   1839 		goto out;
   1840 	}
   1841 
   1842 	/*
   1843 	 * set the default maxbuf value if it was missing from the
   1844 	 * challenge.
   1845 	 */
   1846 	if (cdata->maxbuf == 0)
   1847 		cdata->maxbuf = DEFAULT_MAXBUF;
   1848 
   1849 	saslc__msg_dbg("qop_flags=0x%04x\n",    cdata->qop_flags);
   1850 	saslc__msg_dbg("cipher_flags=0x%04x\n", cdata->cipher_flags);
   1851 
   1852 	rv = 0;
   1853  out:
   1854 	saslc__list_free(list);
   1855 	return rv;
   1856  no_mem:
   1857 	saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   1858 	goto out;
   1859 }
   1860 
   1861 /**
   1862  * @brief creates digestmd5 mechanism session.
   1863  * Function initializes also default options for the session.
   1864  * @param sess sasl session
   1865  * @return 0 on success, -1 on failure.
   1866  */
   1867 static int
   1868 saslc__mech_digestmd5_create(saslc_sess_t *sess)
   1869 {
   1870 	saslc__mech_digestmd5_sess_t *c;
   1871 
   1872 	if ((c = calloc(1, sizeof(*c))) == NULL) {
   1873 		saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   1874 		return -1;
   1875 	}
   1876 	c->rdata.nonce_cnt = 1;
   1877 	sess->mech_sess = c;
   1878 
   1879 	return 0;
   1880 }
   1881 
   1882 static void
   1883 free_cdata(cdata_t *cdata)
   1884 {
   1885 
   1886 	free(cdata->nonce);
   1887 	saslc__list_free(cdata->realm);
   1888 }
   1889 
   1890 static void
   1891 free_rdata(rdata_t *rdata)
   1892 {
   1893 
   1894 	free(rdata->authcid);
   1895 	free(rdata->authzid);
   1896 	free(rdata->cnonce);
   1897 	free(rdata->digesturi);
   1898 	if (rdata->passwd != NULL) {
   1899 		memset(rdata->passwd, 0, strlen(rdata->passwd));
   1900 		free(rdata->passwd);
   1901 	}
   1902 	free(rdata->realm);
   1903 }
   1904 
   1905 /**
   1906  * @brief destroys digestmd5 mechanism session.
   1907  * Function also is freeing assigned resources to the session.
   1908  * @param sess sasl session
   1909  * @return Functions always returns 0.
   1910  */
   1911 static int
   1912 saslc__mech_digestmd5_destroy(saslc_sess_t *sess)
   1913 {
   1914 	saslc__mech_digestmd5_sess_t *ms;
   1915 
   1916 	ms = sess->mech_sess;
   1917 
   1918 	free_cdata(&ms->cdata);
   1919 	free_rdata(&ms->rdata);
   1920 
   1921 	saslc__buffer32_destroy(ms->dec_ctx.buf_ctx);
   1922 	saslc__buffer_destroy(ms->enc_ctx.buf_ctx);
   1923 
   1924 	cipher_context_destroy(ms->dec_ctx.cph_ctx);
   1925 	cipher_context_destroy(ms->enc_ctx.cph_ctx);
   1926 
   1927 	free(sess->mech_sess);
   1928 	sess->mech_sess = NULL;
   1929 
   1930 	return 0;
   1931 }
   1932 
   1933 /**
   1934  * @brief collect the response data necessary to build the reply.
   1935  * @param sess the session context
   1936  * @return 0 on success, -1 on failure
   1937  *
   1938  * NOTE:
   1939  * The input info is from the challenge (previously saved in cdata of
   1940  * saslc__mech_digestmd5_sess_t) or from the property dictionaries.
   1941  *
   1942  * The output info is saved in (mostly) in rdata of the
   1943  * saslc__mech_digestmd5_sess_t structure.  The qop is special in that
   1944  * it is exposed to the saslc__mech_sess_t layer.
   1945  */
   1946 static int
   1947 saslc__mech_digestmd5_response_data(saslc_sess_t *sess)
   1948 {
   1949 	saslc__mech_digestmd5_sess_t *ms;
   1950 	cdata_t *cdata;
   1951 	rdata_t *rdata;
   1952 	const char *authcid;
   1953 	const char *authzid;
   1954 	const char *hostname;
   1955 	const char *maxbuf;
   1956 	const char *passwd;
   1957 	int rv;
   1958 
   1959 	ms = sess->mech_sess;
   1960 	cdata = &ms->cdata;
   1961 	rdata = &ms->rdata;
   1962 
   1963 	if ((rv = choose_qop(sess, cdata->qop_flags)) == -1)
   1964 		return -1;	/* error message already set */
   1965 	ms->mech_sess.qop = rv;
   1966 
   1967 	if (ms->mech_sess.qop == QOP_CONF) {
   1968 		if ((rv = choose_cipher(sess, cdata->cipher_flags)) == -1)
   1969 			return -1;	/* error message already set */
   1970 		rdata->cipher = rv;
   1971 	}
   1972 
   1973 	hostname = saslc_sess_getprop(sess, SASLC_DIGESTMD5_HOSTNAME);
   1974 	if (hostname == NULL) {
   1975 		saslc__error_set(ERR(sess), ERROR_MECH,
   1976 		    "hostname is required for authentication");
   1977 		return -1;
   1978 	}
   1979 
   1980 	rdata->realm = choose_realm(sess, hostname, cdata->realm);
   1981 	if (rdata->realm == NULL)
   1982 		return -1;	/* error message already set */
   1983 
   1984 	rdata->digesturi = saslc__mech_digestmd5_digesturi(sess, hostname);
   1985 	if (rdata->digesturi == NULL)
   1986 		return -1;	/* error message already set */
   1987 
   1988 	authcid = saslc_sess_getprop(sess, SASLC_DIGESTMD5_AUTHCID);
   1989 	if (authcid == NULL) {
   1990 		saslc__error_set(ERR(sess), ERROR_MECH,
   1991 		    "authcid is required for an authentication");
   1992 		return -1;
   1993 	}
   1994 	rdata->authcid = strdup(authcid);
   1995 	if (rdata->authcid == NULL)
   1996 		goto no_mem;
   1997 
   1998 	authzid = saslc_sess_getprop(sess, SASLC_DIGESTMD5_AUTHZID);
   1999 	if (authzid != NULL) {
   2000 		rdata->authzid = strdup(authzid);
   2001 		if (rdata->authzid == NULL)
   2002 			goto no_mem;
   2003 	}
   2004 
   2005 	passwd = saslc_sess_getprop(sess, SASLC_DIGESTMD5_PASSWD);
   2006 	if (passwd == NULL) {
   2007 		saslc__error_set(ERR(sess), ERROR_MECH,
   2008 		    "password is required for an authentication");
   2009 		return -1;
   2010 	}
   2011 	rdata->passwd = strdup(passwd);
   2012 	if (rdata->passwd == NULL)
   2013 		goto no_mem;
   2014 
   2015 	rdata->cnonce = saslc__mech_digestmd5_nonce(NONCE_LEN);
   2016 	if (rdata->cnonce == NULL) {
   2017 		saslc__error_set(ERR(sess), ERROR_MECH,
   2018 		    "failed to create cnonce");
   2019 		return -1;
   2020 	}
   2021 #ifdef SASLC_DIGESTMD5_CNONCE	/* XXX: for debugging! */
   2022 	{
   2023 		const char *cnonce;
   2024 		cnonce = saslc_sess_getprop(sess, SASLC_DIGESTMD5_CNONCE);
   2025 		if (cnonce != NULL) {
   2026 			rdata->cnonce = strdup(cnonce);
   2027 			if (rdata->cnonce == NULL)
   2028 				goto no_mem;
   2029 		}
   2030 	}
   2031 #endif
   2032 	if (ms->mech_sess.qop != QOP_NONE) {
   2033 		maxbuf = saslc_sess_getprop(sess, SASLC_DIGESTMD5_MAXBUF);
   2034 		if (maxbuf != NULL)
   2035 			rdata->maxbuf = (size_t)strtoul(maxbuf, NULL, 10);
   2036 		if (rdata->maxbuf == 0)
   2037 			rdata->maxbuf = cdata->maxbuf;
   2038 		if (INVALID_MAXBUF(rdata->maxbuf)) {
   2039 			saslc__error_set(ERR(sess), ERROR_MECH,
   2040 			    "maxbuf out of range");
   2041 			return -1;
   2042 		}
   2043 	}
   2044 	return 0;
   2045 
   2046  no_mem:
   2047 	saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   2048 	return -1;
   2049 }
   2050 
   2051 /**
   2052  * @brief compute the maximum payload that can go into an integrity or
   2053  * confidentiality packet.
   2054  * @param maxbuf the server's maxbuf size.
   2055  * @param blksize the ciphers block size.  0 or 1 if there is no blocking.
   2056  * @return the payload size
   2057  *
   2058  * The packet (not including the leading uint32_t packet length field)
   2059  * has this structure:
   2060  *
   2061  * struct {
   2062  *    uint8_t payload[];	// packet payload
   2063  *    uint8_t padding[];	// padding to block size
   2064  *    uint8_t hmac_0_9[10];	// the first 10 bytes of the hmac
   2065  *    uint8_t version[2];	// version number (1) in BE format
   2066  *    uint8_t seqnum[4];	// sequence number in BE format
   2067  * } __packed
   2068  *
   2069  * NOTE: if the block size is > 1, then padding is required to make
   2070  * the {payload[], padding[], and hmac_0_9[]} a multiple of the block
   2071  * size.  Furthermore there must be at least one byte of padding!  The
   2072  * padding bytes are all set to the padding length and one byte of
   2073  * padding is necessary to recover the padding length.
   2074  */
   2075 static size_t
   2076 maxpayload(size_t maxbuf, size_t blksize)
   2077 {
   2078 	size_t l;
   2079 
   2080 	if (blksize <= 1) {	/* no padding used */
   2081 		if (maxbuf <= sizeof(md5hash_t))
   2082 			return 0;
   2083 
   2084 		return maxbuf - sizeof(md5hash_t);
   2085 	}
   2086 	if (maxbuf < 2 * blksize + 6)
   2087 		return 0;
   2088 
   2089 	l = rounddown(maxbuf - 6, blksize);
   2090 	if (l <= 10 + 1)	/* we need at least one byte of padding */
   2091 		return 0;
   2092 
   2093 	return l - 10 - 1;
   2094 }
   2095 
   2096 /**
   2097  * @brief initialize the encode and decode coder contexts for the session
   2098  * @param sess the current session
   2099  * @return 0 on success, -1 on failure.
   2100  */
   2101 static int
   2102 init_coder_context(saslc_sess_t *sess)
   2103 {
   2104 	saslc__mech_digestmd5_sess_t *ms;
   2105 	size_t blksize;
   2106 #ifdef SASLC_DIGESTMD5_SELFTEST
   2107 	int selftest;		/* XXX: allow for testing against ourselves */
   2108 #endif
   2109 
   2110 	ms = sess->mech_sess;
   2111 #ifdef SASLC_DIGESTMD5_SELFTEST
   2112 	selftest = saslc_sess_getprop(sess, SASLC_DIGESTMD5_SELFTEST) != NULL;
   2113 #endif
   2114 	blksize = 0;
   2115 	switch (ms->mech_sess.qop) {
   2116 	case QOP_NONE:
   2117 		return 0;
   2118 	case QOP_INT:
   2119 #ifdef	SASLC_DIGESTMD5_SELFTEST
   2120 		ms->dec_ctx.key = selftest ? ms->keys.kic : ms->keys.kis;
   2121 #else
   2122 		ms->dec_ctx.key = ms->keys.kis;
   2123 #endif
   2124 		ms->enc_ctx.key = ms->keys.kic;
   2125 		ms->dec_ctx.cph_ctx = NULL;
   2126 		ms->enc_ctx.cph_ctx = NULL;
   2127 		break;
   2128 	case QOP_CONF:
   2129 #ifdef	SASLC_DIGESTMD5_SELFTEST
   2130 		ms->dec_ctx.key = selftest ? ms->keys.kcc : ms->keys.kcs;
   2131 #else
   2132 		ms->dec_ctx.key = ms->keys.kcs;
   2133 #endif
   2134 		ms->enc_ctx.key = ms->keys.kcc;
   2135 		ms->dec_ctx.cph_ctx = cipher_context_create(sess,
   2136 		    ms->rdata.cipher, 0, ms->dec_ctx.key);
   2137 		if (ms->dec_ctx.cph_ctx == NULL)
   2138 			return -1;
   2139 
   2140 		ms->enc_ctx.cph_ctx = cipher_context_create(sess,
   2141 		    ms->rdata.cipher, 1, ms->enc_ctx.key);
   2142 		if (ms->enc_ctx.cph_ctx == NULL)
   2143 			return -1;
   2144 
   2145 		blksize = ms->enc_ctx.cph_ctx->blksize;
   2146 		break;
   2147 	}
   2148 	ms->dec_ctx.sess = sess;
   2149 	ms->enc_ctx.sess = sess;
   2150 	ms->dec_ctx.buf_ctx = saslc__buffer32_create(sess, ms->rdata.maxbuf);
   2151 	if (ms->cdata.maxbuf < 2 * blksize + 6) {
   2152 		saslc__error_set(ERR(sess), ERROR_MECH,
   2153 		    "server buffer too small for packet");
   2154 		return -1;
   2155 	}
   2156 	ms->enc_ctx.buf_ctx = saslc__buffer_create(sess,
   2157 	    maxpayload(ms->cdata.maxbuf, blksize));
   2158 
   2159 	if (ms->dec_ctx.buf_ctx == NULL || ms->enc_ctx.buf_ctx == NULL) {
   2160 		saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   2161 		return -1;
   2162 	}
   2163 	return 0;
   2164 }
   2165 
   2166 /**
   2167  * @brief construct the reply string.
   2168  * @param sess session context
   2169  * @param response string
   2170  * @return reply string or NULL on failure.
   2171  */
   2172 static char *
   2173 saslc__mech_digestmd5_reply(saslc_sess_t *sess, char *response)
   2174 {
   2175 	saslc__mech_digestmd5_sess_t *ms;
   2176 	char *out;
   2177 	char *cipher, *maxbuf, *realm;
   2178 
   2179 	ms = sess->mech_sess;
   2180 
   2181 	out = NULL;
   2182 	cipher = __UNCONST("");
   2183 	maxbuf = __UNCONST("");
   2184 	realm = __UNCONST("");
   2185 
   2186 	switch (ms->mech_sess.qop) {
   2187 	case QOP_CONF:
   2188 		if (asprintf(&cipher, "cipher=\"%s\",",
   2189 				cipher_name(ms->rdata.cipher)) == -1) {
   2190 			saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   2191 			goto done;
   2192 		}
   2193 		/*FALLTHROUGH*/
   2194 	case QOP_INT:
   2195 		if (asprintf(&maxbuf, "maxbuf=%zu,", ms->rdata.maxbuf) == -1) {
   2196 			saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   2197 			goto done;
   2198 		}
   2199 		break;
   2200 	case QOP_NONE:
   2201 		break;
   2202 	default:
   2203 		assert(/*CONSTCOND*/0);
   2204 		return NULL;
   2205 	}
   2206 	if (ms->rdata.realm != NULL &&
   2207 	    asprintf(&realm, "realm=\"%s\",", ms->rdata.realm) == -1) {
   2208 		saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   2209 		goto done;
   2210 	}
   2211 
   2212 	if (asprintf(&out,
   2213 		"username=\"%s\","
   2214 		"%s"			/* realm= */
   2215 		"nonce=\"%s\","
   2216 		"cnonce=\"%s\","
   2217 		"nc=%08d,"
   2218 		"qop=%s,"
   2219 		"%s"			/* cipher= */
   2220 		"%s"			/* maxbuf= */
   2221 		"digest-uri=\"%s\","
   2222 		"response=%s",
   2223 		ms->rdata.authcid,
   2224 		realm,
   2225 		ms->cdata.nonce,
   2226 		ms->rdata.cnonce,
   2227 		ms->rdata.nonce_cnt,
   2228 		saslc__mech_qop_name(ms->mech_sess.qop),
   2229 		cipher,
   2230 		maxbuf,
   2231 		ms->rdata.digesturi,
   2232 		response
   2233 		    ) == -1) {
   2234 		saslc__error_set_errno(ERR(sess), ERROR_NOMEM);
   2235 		out = NULL;
   2236 	}
   2237  done:
   2238 	if (realm[0] != '\0')
   2239 		free(realm);
   2240 	if (maxbuf[0] != '\0')
   2241 		free(maxbuf);
   2242 	if (cipher[0] != '\0')
   2243 		free(cipher);
   2244 
   2245 	return out;
   2246 }
   2247 
   2248 /**
   2249  * @brief do one step of the sasl authentication
   2250  * @param sess sasl session
   2251  * @param in input data
   2252  * @param inlen input data length
   2253  * @param out place to store output data
   2254  * @param outlen output data length
   2255  * @return MECH_OK - authentication successful,
   2256  * MECH_STEP - more steps are needed,
   2257  * MECH_ERROR - error
   2258  */
   2259 static int
   2260 saslc__mech_digestmd5_cont(saslc_sess_t *sess, const void *in, size_t inlen,
   2261     void **out, size_t *outlen)
   2262 {
   2263 	saslc__mech_digestmd5_sess_t *ms;
   2264 	char *response;
   2265 	const char *p;
   2266 
   2267 	ms = sess->mech_sess;
   2268 
   2269 	switch(ms->mech_sess.step) {
   2270 	case 0:
   2271 		/* in case we are called before getting data from server */
   2272 		if (inlen == 0) {
   2273 			*out = NULL;
   2274 			*outlen = 0;
   2275 			return MECH_STEP;
   2276 		}
   2277 		/* if input data was provided, then doing the first step */
   2278 		ms->mech_sess.step++;
   2279 		/*FALLTHROUGH*/
   2280 	case 1:
   2281 		if (saslc__mech_digestmd5_parse_challenge(sess, in) == -1)
   2282 			return MECH_ERROR;
   2283 
   2284 		if (saslc__mech_digestmd5_response_data(sess) == -1)
   2285 			return MECH_ERROR;
   2286 
   2287 		if ((response = saslc__mech_digestmd5_response(ms,
   2288 			 "AUTHENTICATE")) == NULL) {
   2289 			saslc__error_set(ERR(sess), ERROR_MECH,
   2290 			    "unable to construct response");
   2291 			return MECH_ERROR;
   2292 		}
   2293 		*out = saslc__mech_digestmd5_reply(sess, response);
   2294 		free(response);
   2295 		if (*out == NULL)
   2296 			return MECH_ERROR;
   2297 
   2298 		*outlen = strlen(*out);
   2299 		return MECH_STEP;
   2300 	case 2:
   2301 		if ((response = saslc__mech_digestmd5_response(ms, ""))
   2302 		    == NULL) {
   2303 			saslc__error_set(ERR(sess), ERROR_MECH,
   2304 			    "unable to construct rspauth");
   2305 			return MECH_ERROR;
   2306 		}
   2307 		p = in;
   2308 		if (strncmp(p, "rspauth=", 8) != 0 ||
   2309 		    strcmp(response, p + 8) != 0) {
   2310 			saslc__msg_dbg("rspauth='%s'\n", response);
   2311 			saslc__error_set(ERR(sess), ERROR_MECH,
   2312 			    "failed to validate rspauth response");
   2313 			free(response);
   2314 			return MECH_ERROR;
   2315 		}
   2316 		free(response);
   2317 		if (init_coder_context(sess) == -1)
   2318 			return MECH_ERROR;
   2319 		*out = NULL;
   2320 		*outlen = 0;
   2321 		return MECH_OK;
   2322 	default:
   2323 		assert(/*CONSTCOND*/0); /* impossible */
   2324 		return MECH_ERROR;
   2325 	}
   2326 }
   2327 
   2328 /* mechanism definition */
   2329 const saslc__mech_t saslc__mech_digestmd5 = {
   2330 	.name	 = "DIGEST-MD5",
   2331 	.flags	 = FLAG_MUTUAL | FLAG_DICTIONARY,
   2332 	.create	 = saslc__mech_digestmd5_create,
   2333 	.cont	 = saslc__mech_digestmd5_cont,
   2334 	.encode	 = saslc__mech_digestmd5_encode,
   2335 	.decode	 = saslc__mech_digestmd5_decode,
   2336 	.destroy = saslc__mech_digestmd5_destroy
   2337 };
   2338