Beispiel #1
0
/* Add User-Password attribute to a RADIUS message and encrypt it as specified
 * in RFC 2865, Chap. 5.2 */
struct radius_attr_hdr *
radius_msg_add_attr_user_password(struct radius_msg *msg,
				  u8 *data, size_t data_len,
				  u8 *secret, size_t secret_len)
{
	u8 buf[128];
	int padlen, i;
	size_t buf_len, pos;
	const u8 *addr[2];
	size_t len[2];
	u8 hash[16];

	if (data_len > 128)
		return NULL;

	os_memcpy(buf, data, data_len);
	buf_len = data_len;

	padlen = data_len % 16;
	if (padlen) {
		padlen = 16 - padlen;
		os_memset(buf + data_len, 0, padlen);
		buf_len += padlen;
	}

	addr[0] = secret;
	len[0] = secret_len;
	addr[1] = msg->hdr->authenticator;
	len[1] = 16;
	md5_vector(2, addr, len, hash);

	for (i = 0; i < 16; i++)
		buf[i] ^= hash[i];
	pos = 16;

	while (pos < buf_len) {
		addr[0] = secret;
		len[0] = secret_len;
		addr[1] = &buf[pos - 16];
		len[1] = 16;
		md5_vector(2, addr, len, hash);

		for (i = 0; i < 16; i++)
			buf[pos + i] ^= hash[i];

		pos += 16;
	}

	return radius_msg_add_attr(msg, RADIUS_ATTR_USER_PASSWORD,
				   buf, buf_len);
}
int radius_user_password_hide(struct radius_msg *msg,
			      const u8 *data, size_t data_len,
			      const u8 *secret, size_t secret_len,
			      u8 *buf, size_t buf_len)
{
	size_t padlen, i, pos;
	const u8 *addr[2];
	size_t len[2];
	u8 hash[16];

	if (data_len + 16 > buf_len)
		return -1;

	os_memcpy(buf, data, data_len);

	padlen = data_len % 16;
	if (padlen && data_len < buf_len) {
		padlen = 16 - padlen;
		os_memset(buf + data_len, 0, padlen);
		buf_len = data_len + padlen;
	} else {
		buf_len = data_len;
	}

	addr[0] = secret;
	len[0] = secret_len;
	addr[1] = msg->hdr->authenticator;
	len[1] = 16;
	md5_vector(2, addr, len, hash);

	for (i = 0; i < 16; i++)
		buf[i] ^= hash[i];
	pos = 16;

	while (pos < buf_len) {
		addr[0] = secret;
		len[0] = secret_len;
		addr[1] = &buf[pos - 16];
		len[1] = 16;
		md5_vector(2, addr, len, hash);

		for (i = 0; i < 16; i++)
			buf[pos + i] ^= hash[i];

		pos += 16;
	}

	return buf_len;
}
Beispiel #3
0
int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
		      size_t secret_len, struct radius_msg *sent_msg, int auth)
{
	const u8 *addr[4];
	size_t len[4];
	u8 hash[MD5_MAC_LEN];

	if (sent_msg == NULL) {
		printf("No matching Access-Request message found\n");
		return 1;
	}

	if (auth &&
	    radius_msg_verify_msg_auth(msg, secret, secret_len,
				       sent_msg->hdr->authenticator)) {
		return 1;
	}

	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
	addr[0] = (u8 *) msg->hdr;
	len[0] = 1 + 1 + 2;
	addr[1] = sent_msg->hdr->authenticator;
	len[1] = MD5_MAC_LEN;
	addr[2] = (u8 *) (msg->hdr + 1);
	len[2] = msg->buf_used - sizeof(*msg->hdr);
	addr[3] = secret;
	len[3] = secret_len;
	md5_vector(4, addr, len, hash);
	if (os_memcmp(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
		printf("Response Authenticator invalid!\n");
		return 1;
	}

	return 0;
}
int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
		      size_t secret_len, struct radius_msg *sent_msg, int auth)
{
	const u8 *addr[4];
	size_t len[4];
	u8 hash[MD5_MAC_LEN];

	if (sent_msg == NULL) {
		wpa_printf(MSG_INFO, "No matching Access-Request message found");
		return 1;
	}

	if (auth &&
	    radius_msg_verify_msg_auth(msg, secret, secret_len,
				       sent_msg->hdr->authenticator)) {
		return 1;
	}

	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
	addr[0] = (u8 *) msg->hdr;
	len[0] = 1 + 1 + 2;
	addr[1] = sent_msg->hdr->authenticator;
	len[1] = MD5_MAC_LEN;
	addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr);
	len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
	addr[3] = secret;
	len[3] = secret_len;
	if (md5_vector(4, addr, len, hash) < 0 ||
	    os_memcmp_const(hash, msg->hdr->authenticator, MD5_MAC_LEN) != 0) {
		wpa_printf(MSG_INFO, "Response Authenticator invalid!");
		return 1;
	}

	return 0;
}
int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
			      size_t secret_len)
{
	const u8 *addr[4];
	size_t len[4];
	u8 zero[MD5_MAC_LEN];
	u8 hash[MD5_MAC_LEN];
	u8 auth[MD5_MAC_LEN], orig[MD5_MAC_LEN];
	u8 orig_authenticator[16];

	struct radius_attr_hdr *attr = NULL, *tmp;
	size_t i;

	os_memset(zero, 0, sizeof(zero));
	addr[0] = (u8 *) msg->hdr;
	len[0] = sizeof(struct radius_hdr) - MD5_MAC_LEN;
	addr[1] = zero;
	len[1] = MD5_MAC_LEN;
	addr[2] = (u8 *) (msg->hdr + 1);
	len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
	addr[3] = secret;
	len[3] = secret_len;
	md5_vector(4, addr, len, hash);
	if (os_memcmp(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0)
		return 1;

	for (i = 0; i < msg->attr_used; i++) {
		tmp = radius_get_attr_hdr(msg, i);
		if (tmp->type == RADIUS_ATTR_MESSAGE_AUTHENTICATOR) {
			if (attr != NULL) {
				wpa_printf(MSG_WARNING, "Multiple "
					   "Message-Authenticator attributes "
					   "in RADIUS message");
				return 1;
			}
			attr = tmp;
		}
	}

	if (attr == NULL) {
		/* Message-Authenticator is MAY; not required */
		return 0;
	}

	os_memcpy(orig, attr + 1, MD5_MAC_LEN);
	os_memset(attr + 1, 0, MD5_MAC_LEN);
	os_memcpy(orig_authenticator, msg->hdr->authenticator,
		  sizeof(orig_authenticator));
	os_memset(msg->hdr->authenticator, 0,
		  sizeof(msg->hdr->authenticator));
	hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
		 wpabuf_len(msg->buf), auth);
	os_memcpy(attr + 1, orig, MD5_MAC_LEN);
	os_memcpy(msg->hdr->authenticator, orig_authenticator,
		  sizeof(orig_authenticator));

	return os_memcmp(orig, auth, MD5_MAC_LEN) != 0;
}
Beispiel #6
0
static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
	struct eap_leap_data *data = priv;
	u8 *key, pw_hash_hash[16], pw_hash[16];
	const u8 *addr[5], *password;
	size_t elen[5], password_len;
	int pwhash;

	if (data->state != LEAP_DONE)
		return NULL;

	password = eap_get_config_password2(sm, &password_len, &pwhash);
	if (password == NULL)
		return NULL;

	key = os_malloc(LEAP_KEY_LEN);
	if (key == NULL)
		return NULL;

	if (pwhash) {
		if (hash_nt_password_hash(password, pw_hash_hash)) {
			os_free(key);
			return NULL;
		}
	} else {
		if (nt_password_hash(password, password_len, pw_hash) ||
		    hash_nt_password_hash(pw_hash, pw_hash_hash)) {
			os_free(key);
			return NULL;
		}
	}
	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash",
			pw_hash_hash, 16);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge",
		    data->peer_challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response",
		    data->peer_response, LEAP_RESPONSE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge",
		    data->ap_challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response",
		    data->ap_response, LEAP_RESPONSE_LEN);

	addr[0] = pw_hash_hash;
	elen[0] = 16;
	addr[1] = data->ap_challenge;
	elen[1] = LEAP_CHALLENGE_LEN;
	addr[2] = data->ap_response;
	elen[2] = LEAP_RESPONSE_LEN;
	addr[3] = data->peer_challenge;
	elen[3] = LEAP_CHALLENGE_LEN;
	addr[4] = data->peer_response;
	elen[4] = LEAP_RESPONSE_LEN;
	md5_vector(5, addr, elen, key);
	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
	*len = LEAP_KEY_LEN;

	return key;
}
Beispiel #7
0
int chap_md5(u8 id, const u8 *secret, size_t secret_len, const u8 *challenge,
	     size_t challenge_len, u8 *response)
{
	const u8 *addr[3];
	size_t len[3];

	addr[0] = &id;
	len[0] = 1;
	addr[1] = secret;
	len[1] = secret_len;
	addr[2] = challenge;
	len[2] = challenge_len;
	return md5_vector(3, addr, len, response);
}
Beispiel #8
0
static void encrypt_ms_key(const u8 *key, size_t key_len, u16 salt,
			   const u8 *req_authenticator,
			   const u8 *secret, size_t secret_len,
			   u8 *ebuf, size_t *elen)
{
	int i, len, first = 1;
	u8 hash[MD5_MAC_LEN], saltbuf[2], *pos;
	const u8 *addr[3];
	size_t _len[3];

	saltbuf[0] = salt >> 8;
	saltbuf[1] = salt;

	len = 1 + key_len;
	if (len & 0x0f) {
		len = (len & 0xf0) + 16;
	}
	os_memset(ebuf, 0, len);
	ebuf[0] = key_len;
	os_memcpy(ebuf + 1, key, key_len);

	*elen = len;

	pos = ebuf;
	while (len > 0) {
		/* b(1) = MD5(Secret + Request-Authenticator + Salt)
		 * b(i) = MD5(Secret + c(i - 1)) for i > 1 */
		addr[0] = secret;
		_len[0] = secret_len;
		if (first) {
			addr[1] = req_authenticator;
			_len[1] = MD5_MAC_LEN;
			addr[2] = saltbuf;
			_len[2] = sizeof(saltbuf);
		} else {
			addr[1] = pos - MD5_MAC_LEN;
			_len[1] = MD5_MAC_LEN;
		}
		md5_vector(first ? 3 : 2, addr, _len, hash);
		first = 0;

		for (i = 0; i < MD5_MAC_LEN; i++)
			*pos++ ^= hash[i];

		len -= MD5_MAC_LEN;
	}
}
Beispiel #9
0
/* Create Request Authenticator. The value should be unique over the lifetime
 * of the shared secret between authenticator and authentication server.
 * Use one-way MD5 hash calculated from current timestamp and some data given
 * by the caller. */
void radius_msg_make_authenticator(struct radius_msg *msg,
				   u8 *data, size_t len)
{
	struct timeval tv;
	long int l;
	const u8 *addr[3];
	size_t elen[3];

	gettimeofday(&tv, NULL);
	l = random();
	addr[0] = (u8 *) &tv;
	elen[0] = sizeof(tv);
	addr[1] = data;
	elen[1] = len;
	addr[2] = (u8 *) &l;
	elen[2] = sizeof(l);
	md5_vector(3, addr, elen, msg->hdr->authenticator);
}
Beispiel #10
0
/* Create Request Authenticator. The value should be unique over the lifetime
 * of the shared secret between authenticator and authentication server.
 * Use one-way MD5 hash calculated from current timestamp and some data given
 * by the caller. */
void radius_msg_make_authenticator(struct radius_msg *msg,
				   const u8 *data, size_t len)
{
	struct os_time tv;
	long int l;
	const u8 *addr[3];
	size_t elen[3];

	os_get_time(&tv);
	l = os_random();
	addr[0] = (u8 *) &tv;
	elen[0] = sizeof(tv);
	addr[1] = data;
	elen[1] = len;
	addr[2] = (u8 *) &l;
	elen[2] = sizeof(l);
	md5_vector(3, addr, elen, msg->hdr->authenticator);
}
Beispiel #11
0
static u8 * eap_leap_getKey(struct eap_sm *sm, void *priv, size_t *len)
{
	struct eap_leap_data *data = priv;
	struct wpa_ssid *config = eap_get_config(sm);
	u8 *key, pw_hash_hash[16], pw_hash[16];
	const u8 *addr[5];
	size_t elen[5];

	if (data->state != LEAP_DONE)
		return NULL;

	key = malloc(LEAP_KEY_LEN);
	if (key == NULL)
		return NULL;

	nt_password_hash(config->password, config->password_len, pw_hash);
	hash_nt_password_hash(pw_hash, pw_hash_hash);
	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: pw_hash_hash",
			pw_hash_hash, 16);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_challenge",
		    data->peer_challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: peer_response",
		    data->peer_response, LEAP_RESPONSE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_challenge",
		    data->ap_challenge, LEAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-LEAP: ap_response",
		    data->ap_response, LEAP_RESPONSE_LEN);

	addr[0] = pw_hash_hash;
	elen[0] = 16;
	addr[1] = data->ap_challenge;
	elen[1] = LEAP_CHALLENGE_LEN;
	addr[2] = data->ap_response;
	elen[2] = LEAP_RESPONSE_LEN;
	addr[3] = data->peer_challenge;
	elen[3] = LEAP_CHALLENGE_LEN;
	addr[4] = data->peer_response;
	elen[4] = LEAP_RESPONSE_LEN;
	md5_vector(5, addr, elen, key);
	wpa_hexdump_key(MSG_DEBUG, "EAP-LEAP: master key", key, LEAP_KEY_LEN);
	*len = LEAP_KEY_LEN;

	return key;
}
Beispiel #12
0
static void eap_md5_process(struct eap_sm *sm, void *priv,
			    u8 *respData, size_t respDataLen)
{
	struct eap_md5_data *data = priv;
	struct eap_hdr *resp;
	const u8 *pos;
	const u8 *addr[3];
	size_t len[3], plen;
	u8 hash[MD5_MAC_LEN];

	if (sm->user == NULL || sm->user->password == NULL ||
	    sm->user->password_hash) {
		wpa_printf(MSG_INFO, "EAP-MD5: Plaintext password not "
			   "configured");
		data->state = FAILURE;
		return;
	}

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5,
			       respData, respDataLen, &plen);
	if (pos == NULL || *pos != MD5_MAC_LEN || plen < 1 + MD5_MAC_LEN)
		return; /* Should not happen - frame already validated */

	pos++; /* Skip response len */
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", pos, MD5_MAC_LEN);

	resp = (struct eap_hdr *) respData;
	addr[0] = &resp->identifier;
	len[0] = 1;
	addr[1] = sm->user->password;
	len[1] = sm->user->password_len;
	addr[2] = data->challenge;
	len[2] = CHALLENGE_LEN;
	md5_vector(3, addr, len, hash);

	if (memcmp(hash, pos, MD5_MAC_LEN) == 0) {
		wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Success");
		data->state = SUCCESS;
	} else {
		wpa_printf(MSG_DEBUG, "EAP-MD5: Done - Failure");
		data->state = FAILURE;
	}
}
Beispiel #13
0
int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
			  size_t secret_len, const u8 *req_authenticator)
{
	u8 auth[MD5_MAC_LEN];
	struct radius_attr_hdr *attr;
	const u8 *addr[4];
	size_t len[4];

	if (msg->hdr->code != RADIUS_CODE_ACCOUNTING_RESPONSE) {
	    os_memset(auth, 0, MD5_MAC_LEN);
	    attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
				       auth, MD5_MAC_LEN);
	    if (attr == NULL) {
		    fd_log_debug("WARNING: Could not add Message-Authenticator");
		    return -1;
	    }
	    msg->hdr->length = htons(msg->buf_used);
	    os_memcpy(msg->hdr->authenticator, req_authenticator,
		      sizeof(msg->hdr->authenticator));
	    hmac_md5(secret, secret_len, msg->buf, msg->buf_used,
		     (u8 *) (attr + 1));
	} else {
	    msg->hdr->length = htons(msg->buf_used);
	}

	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
	addr[0] = (u8 *) msg->hdr;
	len[0] = 1 + 1 + 2;
	addr[1] = req_authenticator;
	len[1] = MD5_MAC_LEN;
	addr[2] = (u8 *) (msg->hdr + 1);
	len[2] = msg->buf_used - sizeof(*msg->hdr);
	addr[3] = secret;
	len[3] = secret_len;
	md5_vector(4, addr, len, msg->hdr->authenticator);

	if (msg->buf_used > 0xffff) {
		fd_log_debug("WARNING: too long RADIUS message (%lu)",
		       (unsigned long) msg->buf_used);
		return -1;
	}
	return 0;
}
Beispiel #14
0
void radius_msg_finish_acct(struct radius_msg *msg, u8 *secret,
			    size_t secret_len)
{
	const u8 *addr[2];
	size_t len[2];

	msg->hdr->length = htons(msg->buf_used);
	os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
	addr[0] = msg->buf;
	len[0] = msg->buf_used;
	addr[1] = secret;
	len[1] = secret_len;
	md5_vector(2, addr, len, msg->hdr->authenticator);

	if (msg->buf_used > 0xffff) {
		printf("WARNING: too long RADIUS messages (%lu)\n",
		       (unsigned long) msg->buf_used);
	}
}
Beispiel #15
0
void radius_msg_finish_acct(struct radius_msg *msg, const u8 *secret,
			    size_t secret_len)
{
	const u8 *addr[2];
	size_t len[2];

	msg->hdr->length = htons(wpabuf_len(msg->buf));
	os_memset(msg->hdr->authenticator, 0, MD5_MAC_LEN);
	addr[0] = wpabuf_head(msg->buf);
	len[0] = wpabuf_len(msg->buf);
	addr[1] = secret;
	len[1] = secret_len;
	md5_vector(2, addr, len, msg->hdr->authenticator);

	if (wpabuf_len(msg->buf) > 0xffff) {
		wpa_printf(MSG_WARNING, "RADIUS: Too long messages (%lu)",
			   (unsigned long) wpabuf_len(msg->buf));
	}
}
int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret,
			       size_t secret_len)
{
	const u8 *addr[4];
	size_t len[4];
	u8 zero[MD5_MAC_LEN];
	u8 hash[MD5_MAC_LEN];

	os_memset(zero, 0, sizeof(zero));
	addr[0] = (u8 *) msg->hdr;
	len[0] = sizeof(struct radius_hdr) - MD5_MAC_LEN;
	addr[1] = zero;
	len[1] = MD5_MAC_LEN;
	addr[2] = (u8 *) (msg->hdr + 1);
	len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
	addr[3] = secret;
	len[3] = secret_len;
	md5_vector(4, addr, len, hash);
	return os_memcmp(msg->hdr->authenticator, hash, MD5_MAC_LEN) != 0;
}
Beispiel #17
0
int radius_msg_finish_srv(struct radius_msg *msg, const u8 *secret,
			  size_t secret_len, const u8 *req_authenticator)
{
	u8 auth[MD5_MAC_LEN];
	struct radius_attr_hdr *attr;
	const u8 *addr[4];
	size_t len[4];

	os_memset(auth, 0, MD5_MAC_LEN);
	attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
				   auth, MD5_MAC_LEN);
	if (attr == NULL) {
		printf("WARNING: Could not add Message-Authenticator\n");
		return -1;
	}
	msg->hdr->length = htons(wpabuf_len(msg->buf));
	os_memcpy(msg->hdr->authenticator, req_authenticator,
		  sizeof(msg->hdr->authenticator));
	hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
		 wpabuf_len(msg->buf), (u8 *) (attr + 1));

	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
	addr[0] = (u8 *) msg->hdr;
	len[0] = 1 + 1 + 2;
	addr[1] = req_authenticator;
	len[1] = MD5_MAC_LEN;
	addr[2] = wpabuf_head_u8(msg->buf) + sizeof(struct radius_hdr);
	len[2] = wpabuf_len(msg->buf) - sizeof(struct radius_hdr);
	addr[3] = secret;
	len[3] = secret_len;
	md5_vector(4, addr, len, msg->hdr->authenticator);

	if (wpabuf_len(msg->buf) > 0xffff) {
		wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)",
			   (unsigned long) wpabuf_len(msg->buf));
		return -1;
	}
	return 0;
}
int radius_msg_finish_das_resp(struct radius_msg *msg, const u8 *secret,
			       size_t secret_len,
			       const struct radius_hdr *req_hdr)
{
	const u8 *addr[2];
	size_t len[2];
	u8 auth[MD5_MAC_LEN];
	struct radius_attr_hdr *attr;

	os_memset(auth, 0, MD5_MAC_LEN);
	attr = radius_msg_add_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR,
				   auth, MD5_MAC_LEN);
	if (attr == NULL) {
		wpa_printf(MSG_WARNING, "Could not add Message-Authenticator");
		return -1;
	}

	msg->hdr->length = host_to_be16(wpabuf_len(msg->buf));
	os_memcpy(msg->hdr->authenticator, req_hdr->authenticator, 16);
	hmac_md5(secret, secret_len, wpabuf_head(msg->buf),
		 wpabuf_len(msg->buf), (u8 *) (attr + 1));

	/* ResponseAuth = MD5(Code+ID+Length+RequestAuth+Attributes+Secret) */
	addr[0] = wpabuf_head_u8(msg->buf);
	len[0] = wpabuf_len(msg->buf);
	addr[1] = secret;
	len[1] = secret_len;
	if (md5_vector(2, addr, len, msg->hdr->authenticator) < 0)
		return -1;

	if (wpabuf_len(msg->buf) > 0xffff) {
		wpa_printf(MSG_WARNING, "RADIUS: Too long message (%lu)",
			   (unsigned long) wpabuf_len(msg->buf));
		return -1;
	}
	return 0;
}
Beispiel #19
0
static u8 * decrypt_ms_key(const u8 *key, size_t len,
			   const u8 *req_authenticator,
			   const u8 *secret, size_t secret_len, size_t *reslen)
{
	u8 *plain, *ppos, *res;
	const u8 *pos;
	size_t left, plen;
	u8 hash[MD5_MAC_LEN];
	int i, first = 1;
	const u8 *addr[3];
	size_t elen[3];

	/* key: 16-bit salt followed by encrypted key info */

	if (len < 2 + 16)
		return NULL;

	pos = key + 2;
	left = len - 2;
	if (left % 16) {
		printf("Invalid ms key len %lu\n", (unsigned long) left);
		return NULL;
	}

	plen = left;
	ppos = plain = os_malloc(plen);
	if (plain == NULL)
		return NULL;

	while (left > 0) {
		/* b(1) = MD5(Secret + Request-Authenticator + Salt)
		 * b(i) = MD5(Secret + c(i - 1)) for i > 1 */

		addr[0] = secret;
		elen[0] = secret_len;
		if (first) {
			addr[1] = req_authenticator;
			elen[1] = MD5_MAC_LEN;
			addr[2] = key;
			elen[2] = 2; /* Salt */
		} else {
			addr[1] = pos - MD5_MAC_LEN;
			elen[1] = MD5_MAC_LEN;
		}
		md5_vector(first ? 3 : 2, addr, elen, hash);
		first = 0;

		for (i = 0; i < MD5_MAC_LEN; i++)
			*ppos++ = *pos++ ^ hash[i];
		left -= MD5_MAC_LEN;
	}

	if (plain[0] > plen - 1) {
		printf("Failed to decrypt MPPE key\n");
		os_free(plain);
		return NULL;
	}

	res = os_malloc(plain[0]);
	if (res == NULL) {
		os_free(plain);
		return NULL;
	}
	os_memcpy(res, plain + 1, plain[0]);
	if (reslen)
		*reslen = plain[0];
	os_free(plain);
	return res;
}
Beispiel #20
0
int main(int argc, char *argv[])
{
	struct {
		char *data;
		char *hash;
	} tests[] = {
		{
			"",
			"\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04"
			"\xe9\x80\x09\x98\xec\xf8\x42\x7e"
		},
		{
			"a",
			"\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8"
			"\x31\xc3\x99\xe2\x69\x77\x26\x61"
		},
		{
			"abc",
			"\x90\x01\x50\x98\x3c\xd2\x4f\xb0"
			"\xd6\x96\x3f\x7d\x28\xe1\x7f\x72"
		},
		{
			"message digest",
			"\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d"
			"\x52\x5a\x2f\x31\xaa\xf1\x61\xd0"
		},
		{
			"abcdefghijklmnopqrstuvwxyz",
			"\xc3\xfc\xd3\xd7\x61\x92\xe4\x00"
			"\x7d\xfb\x49\x6c\xca\x67\xe1\x3b"
		},
		{
			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
			"0123456789",
			"\xd1\x74\xab\x98\xd2\x77\xd9\xf5"
			"\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f"
		},
		{
			"12345678901234567890123456789012345678901234567890"
			"123456789012345678901234567890",
			"\x57\xed\xf4\xa2\x2b\xe3\xc9\x55"
			"\xac\x49\xda\x2e\x21\x07\xb6\x7a"
		}
	};
	unsigned int i;
	u8 hash[16];
	const u8 *addr[2];
	size_t len[2];
	int errors = 0;

	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
		printf("MD5 test case %d:", i);

		addr[0] = (u8 *) tests[i].data;
		len[0] = strlen(tests[i].data);
		md5_vector(1, addr, len, hash);
		if (memcmp(hash, tests[i].hash, 16) != 0) {
			printf(" FAIL");
			errors++;
		} else
			printf(" OK");

		if (len[0]) {
			addr[0] = (u8 *) tests[i].data;
			len[0] = strlen(tests[i].data);
			addr[1] = (u8 *) tests[i].data + 1;
			len[1] = strlen(tests[i].data) - 1;
			md5_vector(1, addr, len, hash);
			if (memcmp(hash, tests[i].hash, 16) != 0) {
				printf(" FAIL");
				errors++;
			} else
				printf(" OK");
		}

		printf("\n");
	}

	return errors;
}
/**
 * radius_msg_get_tunnel_password - Parse RADIUS attribute Tunnel-Password
 * @msg: Received RADIUS message
 * @keylen: Length of returned password
 * @secret: RADIUS shared secret
 * @secret_len: Length of secret
 * @sent_msg: Sent RADIUS message
 * @n: Number of password attribute to return (starting with 0)
 * Returns: Pointer to n-th password (free with os_free) or %NULL
 */
char * radius_msg_get_tunnel_password(struct radius_msg *msg, int *keylen,
				      const u8 *secret, size_t secret_len,
				      struct radius_msg *sent_msg, size_t n)
{
	u8 *buf = NULL;
	size_t buflen;
	const u8 *salt;
	u8 *str;
	const u8 *addr[3];
	size_t len[3];
	u8 hash[16];
	u8 *pos;
	size_t i, j = 0;
	struct radius_attr_hdr *attr;
	const u8 *data;
	size_t dlen;
	const u8 *fdata = NULL; /* points to found item */
	size_t fdlen = -1;
	char *ret = NULL;

	/* find n-th valid Tunnel-Password attribute */
	for (i = 0; i < msg->attr_used; i++) {
		attr = radius_get_attr_hdr(msg, i);
		if (attr == NULL ||
		    attr->type != RADIUS_ATTR_TUNNEL_PASSWORD) {
			continue;
		}
		if (attr->length <= 5)
			continue;
		data = (const u8 *) (attr + 1);
		dlen = attr->length - sizeof(*attr);
		if (dlen <= 3 || dlen % 16 != 3)
			continue;
		j++;
		if (j <= n)
			continue;

		fdata = data;
		fdlen = dlen;
		break;
	}
	if (fdata == NULL)
		goto out;

	/* alloc writable memory for decryption */
	buf = os_malloc(fdlen);
	if (buf == NULL)
		goto out;
	os_memcpy(buf, fdata, fdlen);
	buflen = fdlen;

	/* init pointers */
	salt = buf + 1;
	str = buf + 3;

	/* decrypt blocks */
	pos = buf + buflen - 16; /* last block */
	while (pos >= str + 16) { /* all but the first block */
		addr[0] = secret;
		len[0] = secret_len;
		addr[1] = pos - 16;
		len[1] = 16;
		md5_vector(2, addr, len, hash);

		for (i = 0; i < 16; i++)
			pos[i] ^= hash[i];

		pos -= 16;
	}

	/* decrypt first block */
	if (str != pos)
		goto out;
	addr[0] = secret;
	len[0] = secret_len;
	addr[1] = sent_msg->hdr->authenticator;
	len[1] = 16;
	addr[2] = salt;
	len[2] = 2;
	md5_vector(3, addr, len, hash);

	for (i = 0; i < 16; i++)
		pos[i] ^= hash[i];

	/* derive plaintext length from first subfield */
	*keylen = (unsigned char) str[0];
	if ((u8 *) (str + *keylen) >= (u8 *) (buf + buflen)) {
		/* decryption error - invalid key length */
		goto out;
	}
	if (*keylen == 0) {
		/* empty password */
		goto out;
	}

	/* copy passphrase into new buffer */
	ret = os_malloc(*keylen);
	if (ret)
		os_memcpy(ret, str + 1, *keylen);

out:
	/* return new buffer */
	os_free(buf);
	return ret;
}
Beispiel #22
0
void kr_hash_md5_v(size_t num_msgs, const uint8_t *msgs[],
                   const size_t *msg_lens, uint8_t *digest) {
  (void) md5_vector(num_msgs, msgs, msg_lens, digest);
}
Beispiel #23
0
static u8 * eap_md5_process(struct eap_sm *sm, void *priv,
			    struct eap_method_ret *ret,
			    const u8 *reqData, size_t reqDataLen,
			    size_t *respDataLen)
{
	const struct eap_hdr *req;
	struct eap_hdr *resp;
	const u8 *pos, *challenge, *password;
	u8 *rpos;
	size_t len, challenge_len, password_len;
	const u8 *addr[3];
	size_t elen[3];

	password = eap_get_config_password(sm, &password_len);
	if (password == NULL) {
		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
		eap_sm_request_password(sm);
		ret->ignore = TRUE;
		return NULL;
	}

	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5,
			       reqData, reqDataLen, &len);
	if (pos == NULL || len == 0) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)",
			   pos, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}

	/*
	 * CHAP Challenge:
	 * Value-Size (1 octet) | Value(Challenge) | Name(optional)
	 */
	req = (const struct eap_hdr *) reqData;
	challenge_len = *pos++;
	if (challenge_len == 0 || challenge_len > len - 1) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
			   "(challenge_len=%lu len=%lu)",
			   (unsigned long) challenge_len, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}
	ret->ignore = FALSE;
	challenge = pos;
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
		    challenge, challenge_len);

	wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response");
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_UNCOND_SUCC;
	ret->allowNotifications = TRUE;

	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, respDataLen,
			     1 + MD5_MAC_LEN, EAP_CODE_RESPONSE,
			     req->identifier, &rpos);
	if (resp == NULL)
		return NULL;

	/*
	 * CHAP Response:
	 * Value-Size (1 octet) | Value(Response) | Name(optional)
	 */
	*rpos++ = MD5_MAC_LEN;

	addr[0] = &resp->identifier;
	elen[0] = 1;
	addr[1] = password;
	elen[1] = password_len;
	addr[2] = challenge;
	elen[2] = challenge_len;
	md5_vector(3, addr, elen, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, MD5_MAC_LEN);

	return (u8 *) resp;
}
/**
 * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104)
 * @key: Key for HMAC operations
 * @key_len: Length of the key in bytes
 * @num_elem: Number of elements in the data vector
 * @addr: Pointers to the data areas
 * @len: Lengths of the data blocks
 * @mac: Buffer for the hash (16 bytes)
 * Returns: 0 on success, -1 on failure
 */
int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
		    const u8 *addr[], const size_t *len, u8 *mac)
{
	u8 k_pad[64]; /* padding - key XORd with ipad/opad */
	u8 tk[16];
	const u8 *_addr[6];
	size_t i, _len[6];

	if (num_elem > 5) {
		/*
		 * Fixed limit on the number of fragments to avoid having to
		 * allocate memory (which could fail).
		 */
		return -1;
	}

        /* if key is longer than 64 bytes reset it to key = MD5(key) */
        if (key_len > 64) {
		if (md5_vector(1, &key, &key_len, tk))
			return -1;
		key = tk;
		key_len = 16;
        }

	/* the HMAC_MD5 transform looks like:
	 *
	 * MD5(K XOR opad, MD5(K XOR ipad, text))
	 *
	 * where K is an n byte key
	 * ipad is the byte 0x36 repeated 64 times
	 * opad is the byte 0x5c repeated 64 times
	 * and text is the data being protected */

	/* start out by storing key in ipad */
	os_memset(k_pad, 0, sizeof(k_pad));
	os_memcpy(k_pad, key, key_len);

	/* XOR key with ipad values */
	for (i = 0; i < 64; i++)
		k_pad[i] ^= 0x36;

	/* perform inner MD5 */
	_addr[0] = k_pad;
	_len[0] = 64;
	for (i = 0; i < num_elem; i++) {
		_addr[i + 1] = addr[i];
		_len[i + 1] = len[i];
	}
	if (md5_vector(1 + num_elem, _addr, _len, mac))
		return -1;

	os_memset(k_pad, 0, sizeof(k_pad));
	os_memcpy(k_pad, key, key_len);
	/* XOR key with opad values */
	for (i = 0; i < 64; i++)
		k_pad[i] ^= 0x5c;

	/* perform outer MD5 */
	_addr[0] = k_pad;
	_len[0] = 64;
	_addr[1] = mac;
	_len[1] = MD5_MAC_LEN;
	return md5_vector(2, _addr, _len, mac);
}
Beispiel #25
0
static u8 * eap_md5_process(struct eap_sm *sm, void *priv,
			    struct eap_method_ret *ret,
			    const u8 *reqData, size_t reqDataLen,
			    size_t *respDataLen)
{
	struct wpa_ssid *config = eap_get_config(sm);
	const struct eap_hdr *req;
	struct eap_hdr *resp;
	const u8 *pos, *challenge;
	u8 *rpos;
	size_t len, challenge_len;
	const u8 *addr[3];
	size_t elen[3];

	if (config == NULL || config->password == NULL) {
		wpa_printf(MSG_INFO, "EAP-MD5: Password not configured");
		eap_sm_request_password(sm, config);
		ret->ignore = TRUE;
		return NULL;
	}

	pos = eap_hdr_validate(EAP_TYPE_MD5, reqData, reqDataLen, &len);
	if (pos == NULL) {
		ret->ignore = TRUE;
		return NULL;
	}
	req = (const struct eap_hdr *) reqData;
	challenge_len = *pos++;
	if (challenge_len == 0 ||
	    challenge_len > len - 1) {
		wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge "
			   "(challenge_len=%lu len=%lu",
			   (unsigned long) challenge_len, (unsigned long) len);
		ret->ignore = TRUE;
		return NULL;
	}
	ret->ignore = FALSE;
	challenge = pos;
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge",
		    challenge, challenge_len);

	wpa_printf(MSG_DEBUG, "EAP-MD5: generating Challenge Response");
	ret->methodState = METHOD_DONE;
	ret->decision = DECISION_UNCOND_SUCC;
	ret->allowNotifications = TRUE;

	*respDataLen = sizeof(struct eap_hdr) + 1 + 1 + MD5_MAC_LEN;
	resp = malloc(*respDataLen);
	if (resp == NULL)
		return NULL;
	resp->code = EAP_CODE_RESPONSE;
	resp->identifier = req->identifier;
	resp->length = host_to_be16(*respDataLen);
	rpos = (u8 *) (resp + 1);
	*rpos++ = EAP_TYPE_MD5;
	*rpos++ = MD5_MAC_LEN; /* Value-Size */

	addr[0] = &resp->identifier;
	elen[0] = 1;
	addr[1] = config->password;
	elen[1] = config->password_len;
	addr[2] = challenge;
	elen[2] = challenge_len;
	md5_vector(3, addr, elen, rpos);
	wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Response", rpos, MD5_MAC_LEN);

	return (u8 *) resp;
}
static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
					struct eap_ttls_data *data,
					struct eap_method_ret *ret,
					u8 **resp, size_t *resp_len)
{
	struct wpa_ssid *config = eap_get_config(sm);
	u8 *buf, *pos, *challenge;
	const u8 *addr[3];
	size_t len[3];

	wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");

	pos = buf = os_malloc(config->identity_len + 1000);
	if (buf == NULL) {
		wpa_printf(MSG_ERROR,
			   "EAP-TTLS/CHAP: Failed to allocate memory");
		return -1;
	}

	/* User-Name */
	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
			       config->identity, config->identity_len);

	/* CHAP-Challenge */
	challenge = eap_ttls_implicit_challenge(
		sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
	if (challenge == NULL) {
		os_free(buf);
		wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
			   "implicit challenge");
		return -1;
	}

	pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,
			       challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);

	/* CHAP-Password */
	pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,
			       1 + EAP_TTLS_CHAP_PASSWORD_LEN);
	data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];
	*pos++ = data->ident;

	/* MD5(Ident + Password + Challenge) */
	addr[0] = &data->ident;
	len[0] = 1;
	addr[1] = config->password;
	len[1] = config->password_len;
	addr[2] = challenge;
	len[2] = EAP_TTLS_CHAP_CHALLENGE_LEN;
	md5_vector(3, addr, len, pos);

	wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
			  config->identity, config->identity_len);
	wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
			      config->password, config->password_len);
	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
		    challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
	wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
		    pos, EAP_TTLS_CHAP_PASSWORD_LEN);
	pos += EAP_TTLS_CHAP_PASSWORD_LEN;
	os_free(challenge);
	AVP_PAD(buf, pos);

	*resp = buf;
	*resp_len = pos - buf;

	if (data->ttls_version > 0) {
		/* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
		 * so do not allow connection to be terminated yet. */
		ret->methodState = METHOD_CONT;
		ret->decision = DECISION_COND_SUCC;
	} else {
		/* EAP-TTLS/CHAP does not provide tunneled success
		 * notification, so assume that Phase2 succeeds. */
		ret->methodState = METHOD_DONE;
		ret->decision = DECISION_COND_SUCC;
	}

	return 0;
}