Esempio n. 1
0
void
cipher_init(struct iked_cipher *encr, int enc)
{
	EVP_CipherInit_ex(encr->encr_ctx, encr->encr_priv, NULL,
	    ibuf_data(encr->encr_key), ibuf_data(encr->encr_iv), enc);
	EVP_CIPHER_CTX_set_padding(encr->encr_ctx, 0);
}
Esempio n. 2
0
struct ibuf *
ikev2_msg_auth(struct iked *env, struct iked_sa *sa, int response)
{
	struct ibuf		*authmsg = NULL, *nonce, *prfkey, *buf;
	uint8_t			*ptr;
	struct iked_id		*id;
	size_t			 tmplen;

	/*
	 * Create the payload to be signed/MAC'ed for AUTH
	 */

	if (!response) {
		if ((nonce = sa->sa_rnonce) == NULL ||
		    (sa->sa_iid.id_type == 0) ||
		    (prfkey = sa->sa_key_iprf) == NULL ||
		    (buf = sa->sa_1stmsg) == NULL)
			return (NULL);
		id = &sa->sa_iid;
	} else {
		if ((nonce = sa->sa_inonce) == NULL ||
		    (sa->sa_rid.id_type == 0) ||
		    (prfkey = sa->sa_key_rprf) == NULL ||
		    (buf = sa->sa_2ndmsg) == NULL)
			return (NULL);
		id = &sa->sa_rid;
	}

	if ((authmsg = ibuf_dup(buf)) == NULL)
		return (NULL);
	if (ibuf_cat(authmsg, nonce) != 0)
		goto fail;

	if ((hash_setkey(sa->sa_prf, ibuf_data(prfkey),
	    ibuf_size(prfkey))) == NULL)
		goto fail;

	if ((ptr = ibuf_advance(authmsg,
	    hash_length(sa->sa_prf))) == NULL)
		goto fail;

	hash_init(sa->sa_prf);
	hash_update(sa->sa_prf, ibuf_data(id->id_buf), ibuf_size(id->id_buf));
	hash_final(sa->sa_prf, ptr, &tmplen);

	if (tmplen != hash_length(sa->sa_prf))
		goto fail;

	log_debug("%s: %s auth data length %zu",
	    __func__, response ? "responder" : "initiator",
	    ibuf_size(authmsg));
	print_hex(ibuf_data(authmsg), 0, ibuf_size(authmsg));

	return (authmsg);

 fail:
	ibuf_release(authmsg);
	return (NULL);
}
Esempio n. 3
0
int
ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total,
    struct ikev2_transform *xfrm)
{
	u_int8_t	*msgbuf = ibuf_data(msg->msg_data);
	size_t		 xfrm_length;

	if (total < sizeof(*xfrm)) {
		log_debug("%s: payload malformed: too short for header "
		    "(%zu < %zu)", __func__, total, sizeof(*xfrm));
		return (-1);
	}
	memcpy(xfrm, msgbuf + offset, sizeof(*xfrm));

	xfrm_length = betoh16(xfrm->xfrm_length);
	if (xfrm_length < sizeof(*xfrm)) {
		log_debug("%s: payload malformed: shorter than minimal header "
		    "(%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm));
		return (-1);
	}
	if (total < xfrm_length) {
		log_debug("%s: malformed payload: too long for payload size "
		    "(%zu < %zu)", __func__, total, xfrm_length);
		return (-1);
	}

	return (0);
}
Esempio n. 4
0
int
ikev2_msg_send(struct iked *env, struct iked_message *msg)
{
	struct ibuf		*buf = msg->msg_data;
	u_int32_t		 natt = 0x00000000;
	struct ike_header	*hdr;

	if (buf == NULL || (hdr = ibuf_seek(msg->msg_data,
	    msg->msg_offset, sizeof(*hdr))) == NULL)
		return (-1);

	log_info("%s: %s from %s to %s, %ld bytes", __func__,
	    print_map(hdr->ike_exchange, ikev2_exchange_map),
	    print_host(&msg->msg_local, NULL, 0),
	    print_host(&msg->msg_peer, NULL, 0),
	    ibuf_length(buf));

	if (msg->msg_natt || (msg->msg_sa && msg->msg_sa->sa_natt)) {
		if (ibuf_prepend(buf, &natt, sizeof(natt)) == -1) {
			log_debug("%s: failed to set NAT-T", __func__);
			return (-1);
		}
	}

	if ((sendto(msg->msg_fd, ibuf_data(buf), ibuf_size(buf), 0,
	    (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen)) == -1) {
		log_warn("%s: sendto", __func__);
		return (-1);
	}

	return (0);
}
Esempio n. 5
0
int
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, off_t offset)
{
	struct ikev2_keyexchange	 kex;
	u_int8_t			*buf;
	size_t				 len;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	memcpy(&kex, msgbuf + offset, sizeof(kex));

	log_debug("%s: dh group %s reserved %d", __func__,
	    print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),
	    betoh16(kex.kex_reserved));

	buf = msgbuf + offset + sizeof(kex);
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(kex);

	print_hex(buf, 0, len);

	if (ikev2_msg_frompeer(msg)) {
		ibuf_release(msg->msg_parent->msg_ke);
		if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) {
			log_debug("%s: failed to get exchange", __func__);
			return (-1);
		}
	}

	return (0);
}
Esempio n. 6
0
int
ca_key_serialize(EVP_PKEY *key, struct iked_id *id)
{
	int		 len;
	u_int8_t	*d;
	RSA		*rsa;

	switch (key->type) {
	case EVP_PKEY_RSA:
		id->id_type = 0;
		id->id_offset = 0;
		ibuf_release(id->id_buf);

		if ((rsa = EVP_PKEY_get1_RSA(key)) == NULL)
			return (-1);
		if ((len = i2d_RSAPrivateKey(rsa, NULL)) <= 0)
			return (-1);
		if ((id->id_buf = ibuf_new(NULL, len)) == NULL)
			return (-1);

		d = ibuf_data(id->id_buf);
		if (i2d_RSAPrivateKey(rsa, &d) != len) {
			ibuf_release(id->id_buf);
			return (-1);
		}

		id->id_type = IKEV2_CERT_RSA_KEY;
		break;
	default:
		log_debug("%s: unsupported key type %d", __func__, key->type);
		return (-1);
	}

	return (0);
}
Esempio n. 7
0
int
ca_setauth(struct iked *env, struct iked_sa *sa,
    struct ibuf *authmsg, enum privsep_procid id)
{
	struct iovec		 iov[3];
	int			 iovcnt = 3;
	struct iked_policy	*policy = sa->sa_policy;
	u_int8_t		 type = policy->pol_auth.auth_method;

	if (type == IKEV2_AUTH_SHARED_KEY_MIC) {
		sa->sa_stateflags |= IKED_REQ_AUTH;
		return (ikev2_msg_authsign(env, sa,
		    &policy->pol_auth, authmsg));
	}

	iov[0].iov_base = &sa->sa_hdr;
	iov[0].iov_len = sizeof(sa->sa_hdr);
	iov[1].iov_base = &type;
	iov[1].iov_len = sizeof(type);
	if (type == IKEV2_AUTH_NONE)
		iovcnt--;
	else {
		iov[2].iov_base = ibuf_data(authmsg);
		iov[2].iov_len = ibuf_size(authmsg);
		log_debug("%s: auth length %d", __func__, ibuf_size(authmsg));
	}

	if (proc_composev_imsg(env, id, IMSG_AUTH, -1, iov, iovcnt) == -1)
		return (-1);
	return (0);
}
Esempio n. 8
0
void
ikev2_msg_retransmit_timeout(struct iked *env, void *arg)
{
	struct iked_message	*msg = arg;
	struct iked_sa		*sa = msg->msg_sa;

	if (msg->msg_tries < IKED_RETRANSMIT_TRIES) {
		if (sendtofrom(msg->msg_fd, ibuf_data(msg->msg_data),
		    ibuf_size(msg->msg_data), 0,
		    (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen,
		    (struct sockaddr *)&msg->msg_local,
		    msg->msg_locallen) == -1) {
			log_warn("%s: sendtofrom", __func__);
			sa_free(env, sa);
			return;
		}
		/* Exponential timeout */
		timer_add(env, &msg->msg_timer,
		    IKED_RETRANSMIT_TIMEOUT * (2 << (msg->msg_tries++)));
	} else {
		log_debug("%s: retransmit limit reached for msgid %u",
		    __func__, msg->msg_msgid);
		sa_free(env, sa);
	}
}
Esempio n. 9
0
void
ikev1_recv(struct iked *env, struct iked_message *msg)
{
	struct ike_header	*hdr;

	if (ibuf_size(msg->msg_data) <= sizeof(*hdr)) {
		log_debug("%s: short message", __func__);
		return;
	}

	hdr = (struct ike_header *)ibuf_data(msg->msg_data);

	log_debug("%s: header ispi %s rspi %s"
	    " nextpayload %u version 0x%02x exchange %u flags 0x%02x"
	    " msgid %u length %u", __func__,
	    print_spi(betoh64(hdr->ike_ispi), 8),
	    print_spi(betoh64(hdr->ike_rspi), 8),
	    hdr->ike_nextpayload,
	    hdr->ike_version,
	    hdr->ike_exchange,
	    hdr->ike_flags,
	    betoh32(hdr->ike_msgid),
	    betoh32(hdr->ike_length));

	log_debug("%s: IKEv1 not supported", __func__);
}
Esempio n. 10
0
int
ca_x509_subjectaltname_cmp(X509 *cert, struct iked_static_id *id)
{
	struct iked_id	 sanid;
	char		 idstr[IKED_ID_SIZE];
	int		 ret = -1;

	bzero(&sanid, sizeof(sanid));

	if (ca_x509_subjectaltname(cert, &sanid) != 0)
		return (-1);

	ikev2_print_id(&sanid, idstr, sizeof(idstr));

	/* Compare id types, length and data */
	if ((id->id_type != sanid.id_type) ||
	    ((ssize_t)ibuf_size(sanid.id_buf) !=
	    (id->id_length - id->id_offset)) ||
	    (memcmp(id->id_data + id->id_offset,
	    ibuf_data(sanid.id_buf),
	    ibuf_size(sanid.id_buf)) != 0)) {
		log_debug("%s: %s mismatched", __func__, idstr);
		goto done;
	}

	ret = 0;
 done:
	ibuf_release(sanid.id_buf);
	return (ret);
}
Esempio n. 11
0
int
ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left,
    struct ikev2_payload *pld, struct ikev2_auth *auth)
{
	u_int8_t	*msgbuf = ibuf_data(msg->msg_data);
	size_t		 pld_length;

	pld_length = betoh16(pld->pld_length);
	if (pld_length < sizeof(*pld) + sizeof(*auth)) {
		log_debug("%s: malformed payload: specified length smaller "
		    "than minimum size (%zu < %zu)", __func__, pld_length,
		    sizeof(*pld) + sizeof(*auth));
		return (-1);
	}

	/* This will actually be caught by earlier checks. */
	if (left < sizeof(*auth)) {
		log_debug("%s: malformed payload: too short for header "
		    "(%zu < %zu)", __func__, left, sizeof(*auth));
		return (-1);
	}
	memcpy(auth, msgbuf + offset, sizeof(*auth));

	return (0);
}
Esempio n. 12
0
int
ikev2_msg_send(struct iked *env, struct iked_message *msg)
{
	struct iked_sa		*sa = msg->msg_sa;
	struct ibuf		*buf = msg->msg_data;
	u_int32_t		 natt = 0x00000000;
	int			 isnatt = 0;
	struct ike_header	*hdr;
	struct iked_message	*m;

	if (buf == NULL || (hdr = ibuf_seek(msg->msg_data,
	    msg->msg_offset, sizeof(*hdr))) == NULL)
		return (-1);

	isnatt = (msg->msg_natt || (msg->msg_sa && msg->msg_sa->sa_natt));

	log_info("%s: %s from %s to %s, %ld bytes%s", __func__,
	    print_map(hdr->ike_exchange, ikev2_exchange_map),
	    print_host(&msg->msg_local, NULL, 0),
	    print_host(&msg->msg_peer, NULL, 0),
	    ibuf_length(buf), isnatt ? ", NAT-T" : "");

	if (isnatt) {
		if (ibuf_prepend(buf, &natt, sizeof(natt)) == -1) {
			log_debug("%s: failed to set NAT-T", __func__);
			return (-1);
		}
		msg->msg_offset += sizeof(natt);
	}

	if ((sendto(msg->msg_fd, ibuf_data(buf), ibuf_size(buf), 0,
	    (struct sockaddr *)&msg->msg_peer, msg->msg_peerlen)) == -1) {
		log_warn("%s: sendto", __func__);
		return (-1);
	}

	if (!sa)
		return (0);

	if ((m = ikev2_msg_copy(env, msg)) == NULL) {
		log_debug("%s: failed to copy a message", __func__);
		return (-1);
	}
	m->msg_exchange = hdr->ike_exchange;

	if (hdr->ike_flags & IKEV2_FLAG_RESPONSE) {
		TAILQ_INSERT_TAIL(&sa->sa_responses, m, msg_entry);
		timer_initialize(env, &m->msg_timer,
		    ikev2_msg_response_timeout, m);
		timer_register(env, &m->msg_timer, IKED_RESPONSE_TIMEOUT);
	} else {
		TAILQ_INSERT_TAIL(&sa->sa_requests, m, msg_entry);
		timer_initialize(env, &m->msg_timer,
		    ikev2_msg_retransmit_timeout, m);
		timer_register(env, &m->msg_timer, IKED_RETRANSMIT_TIMEOUT);
	}

	return (0);
}
Esempio n. 13
0
int
ikev2_pld_id(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left, u_int payload)
{
	u_int8_t			*ptr;
	struct ikev2_id			 id;
	size_t				 len;
	struct iked_id			*idp, idb;
	struct iked_sa			*sa = msg->msg_sa;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);
	char				 idstr[IKED_ID_SIZE];

	if (ikev2_validate_id(msg, offset, left, pld, &id))
		return (-1);

	bzero(&idb, sizeof(idb));

	/* Don't strip the Id payload header */
	ptr = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld);

	idb.id_type = id.id_type;
	idb.id_offset = sizeof(id);
	if ((idb.id_buf = ibuf_new(ptr, len)) == NULL)
		return (-1);

	if (ikev2_print_id(&idb, idstr, sizeof(idstr)) == -1) {
		log_debug("%s: malformed id", __func__);
		return (-1);
	}

	log_debug("%s: id %s length %zu", __func__, idstr, len);

	if (!ikev2_msg_frompeer(msg)) {
		ibuf_release(idb.id_buf);
		return (0);
	}

	if (!((sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDr) ||
	    (!sa->sa_hdr.sh_initiator && payload == IKEV2_PAYLOAD_IDi))) {
		log_debug("%s: unexpected id payload", __func__);
		return (0);
	}

	idp = &msg->msg_parent->msg_id;
	if (idp->id_type) {
		log_debug("%s: duplicate id payload", __func__);
		return (-1);
	}

	idp->id_buf = idb.id_buf;
	idp->id_offset = idb.id_offset;
	idp->id_type = idb.id_type;

	return (0);
}
Esempio n. 14
0
int
ikev2_msg_integr(struct iked *env, struct iked_sa *sa, struct ibuf *src)
{
	int			 ret = -1;
	size_t			 integrlen, tmplen;
	struct ibuf		*integr, *prf, *tmp = NULL;
	u_int8_t		*ptr;

	log_debug("%s: message length %d", __func__, ibuf_size(src));
	print_hex(ibuf_data(src), 0, ibuf_size(src));

	if (sa == NULL ||
	    sa->sa_integr == NULL) {
		log_debug("%s: invalid SA", __func__);
		return (-1);
	}

	if (sa->sa_hdr.sh_initiator) {
		integr = sa->sa_key_iauth;
		prf = sa->sa_key_iprf;
	} else {
		integr = sa->sa_key_rauth;
		prf = sa->sa_key_rprf;
	}

	integrlen = hash_length(sa->sa_integr);

	log_debug("%s: integrity checksum length %d", __func__,
	    integrlen);

	/*
	 * Validate packet checksum
	 */
	if ((tmp = ibuf_new(NULL, hash_keylength(sa->sa_integr))) == NULL)
		goto done;

	hash_setkey(sa->sa_integr, ibuf_data(integr), ibuf_size(integr));
	hash_init(sa->sa_integr);
	hash_update(sa->sa_integr, ibuf_data(src),
	    ibuf_size(src) - integrlen);
	hash_final(sa->sa_integr, ibuf_data(tmp), &tmplen);

	if (tmplen != integrlen) {
		log_debug("%s: hash failure", __func__);
		goto done;
	}

	if ((ptr = ibuf_seek(src,
	    ibuf_size(src) - integrlen, integrlen)) == NULL)
		goto done;
	memcpy(ptr, ibuf_data(tmp), tmplen);

	print_hex(ibuf_data(tmp), 0, ibuf_size(tmp));

	ret = 0;
 done:
	ibuf_release(tmp);

	return (ret);
}
Esempio n. 15
0
int
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left)
{
	struct iked_sa			*sa = msg->msg_sa;
	struct ikev2_cert		 cert;
	u_int8_t			*buf;
	ssize_t				 len;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	if (ikev2_validate_certreq(msg, offset, left, pld, &cert))
		return (-1);
	offset += sizeof(cert);

	buf = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);

	log_debug("%s: type %s length %zd",
	    __func__, print_map(cert.cert_type, ikev2_cert_map), len);

	/* This will actually be caught by earlier checks. */
	if (len < 0) {
		log_debug("%s: invalid certificate request length", __func__);
		return (-1);
	}

	print_hex(buf, 0, len);

	if (!ikev2_msg_frompeer(msg))
		return (0);

	if (cert.cert_type == IKEV2_CERT_X509_CERT) {
		if (!len || (len % SHA_DIGEST_LENGTH) != 0) {
			log_debug("%s: invalid certificate request", __func__);
			return (-1);
		}
	}

	if (msg->msg_sa == NULL)
		return (-1);

	/* Optional certreq for PSK */
	if (sa->sa_hdr.sh_initiator)
		sa->sa_stateinit |= IKED_REQ_CERT;
	else
		sa->sa_statevalid |= IKED_REQ_CERT;

	ca_setreq(env, &sa->sa_hdr, &sa->sa_policy->pol_localid,
	    cert.cert_type, buf, len, PROC_CERT);

	return (0);
}
Esempio n. 16
0
int
ikev2_msg_retransmit_response(struct iked *env, struct iked_sa *sa,
                              struct iked_message *msg)
{
    if ((sendto(msg->msg_fd, ibuf_data(msg->msg_data),
                ibuf_size(msg->msg_data), 0, (struct sockaddr *)&msg->msg_peer,
                msg->msg_peerlen)) == -1) {
        log_warn("%s: sendto", __func__);
        return (-1);
    }

    timer_add(env, &msg->msg_timer, IKED_RESPONSE_TIMEOUT);
    return (0);
}
Esempio n. 17
0
int
ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total,
    struct ikev2_attribute *attr)
{
	u_int8_t	*msgbuf = ibuf_data(msg->msg_data);

	if (total < sizeof(*attr)) {
		log_debug("%s: payload malformed: too short for header "
		    "(%zu < %zu)", __func__, total, sizeof(*attr));
		return (-1);
	}
	memcpy(attr, msgbuf + offset, sizeof(*attr));

	return (0);
}
Esempio n. 18
0
int
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,
    struct iked_message *msg, size_t offset, size_t total)
{
	struct ikev2_attribute		 attr;
	u_int				 type;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);
	int				 ret = 0;
	size_t				 attr_length;

	if (ikev2_validate_attr(msg, offset, total, &attr))
		return (-1);

	type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;

	log_debug("%s: attribute type %s length %d total %zu",
	    __func__, print_map(type, ikev2_attrtype_map),
	    betoh16(attr.attr_length), total);

	if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) {
		/* Type-Value attribute */
		offset += sizeof(attr);
		total -= sizeof(attr);

		if (type == IKEV2_ATTRTYPE_KEY_LENGTH)
			msg->msg_attrlength = betoh16(attr.attr_length);
	} else {
		/* Type-Length-Value attribute */
		attr_length = betoh16(attr.attr_length);
		if (total < attr_length) {
			log_debug("%s: payload malformed: attribute larger "
			    "than actual payload (%zu < %zu)", __func__,
			    total, attr_length);
			return (-1);
		}
		print_hex(msgbuf, offset + sizeof(attr),
		    attr_length - sizeof(attr));
		offset += attr_length;
		total -= attr_length;
	}

	if (total > 0) {
		/* Next attribute */
		ret = ikev2_pld_attr(env, xfrm, msg, offset, total);
	}

	return (ret);
}
Esempio n. 19
0
int
ikev2_pld_e(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, off_t offset)
{
	struct iked_sa		*sa = msg->msg_sa;
	struct ibuf		*e = NULL;
	u_int8_t		*msgbuf = ibuf_data(msg->msg_data);
	struct iked_message	 emsg;
	u_int8_t		*buf;
	size_t			 len;
	int			 ret = -1;

	buf = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld);

	if ((e = ibuf_new(buf, len)) == NULL)
		goto done;

	if (ikev2_msg_frompeer(msg)) {
		e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
	} else {
		sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
		e = ikev2_msg_decrypt(env, msg->msg_sa, msg->msg_data, e);
		sa->sa_hdr.sh_initiator = sa->sa_hdr.sh_initiator ? 0 : 1;
	}

	if (e == NULL)
		goto done;

	/*
	 * Parse decrypted payload
	 */
	bzero(&emsg, sizeof(emsg));
	memcpy(&emsg, msg, sizeof(*msg));
	emsg.msg_data = e;
	emsg.msg_e = 1;
	emsg.msg_parent = msg;
	TAILQ_INIT(&emsg.msg_proposals);

	ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e),
	    pld->pld_nextpayload, 0);

 done:
	ibuf_release(e);

	return (ret);
}
Esempio n. 20
0
int
ca_setreq(struct iked *env, struct iked_sa *sa,
    struct iked_static_id *localid, uint8_t type, uint8_t *data,
    size_t len, enum privsep_procid procid)
{
	struct iovec		iov[4];
	int			iovcnt = 0;
	struct iked_static_id	idb;
	struct iked_id		id;
	int			ret = -1;

	/* Convert to a static Id */
	bzero(&id, sizeof(id));
	if (ikev2_policy2id(localid, &id, 1) != 0)
		return (-1);

	bzero(&idb, sizeof(idb));
	idb.id_type = id.id_type;
	idb.id_offset = id.id_offset;
	idb.id_length = ibuf_length(id.id_buf);
	memcpy(&idb.id_data, ibuf_data(id.id_buf),
	    ibuf_length(id.id_buf));
	iov[iovcnt].iov_base = &idb;
	iov[iovcnt].iov_len = sizeof(idb);
	iovcnt++;

	iov[iovcnt].iov_base = &sa->sa_hdr;
	iov[iovcnt].iov_len = sizeof(sa->sa_hdr);
	iovcnt++;
	iov[iovcnt].iov_base = &type;
	iov[iovcnt].iov_len = sizeof(type);
	iovcnt++;
	iov[iovcnt].iov_base = data;
	iov[iovcnt].iov_len = len;
	iovcnt++;

	if (proc_composev(&env->sc_ps, procid, IMSG_CERTREQ, iov, iovcnt) == -1)
		goto done;

	sa_stateflags(sa, IKED_REQ_CERTREQ);

	ret = 0;
 done:
	ibuf_release(id.id_buf);
	return (ret);
}
Esempio n. 21
0
int
ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left)
{
	struct ikev2_auth		 auth;
	struct iked_id			*idp;
	u_int8_t			*buf;
	size_t				 len;
	struct iked_sa			*sa = msg->msg_sa;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	if (ikev2_validate_auth(msg, offset, left, pld, &auth))
		return (-1);
	offset += sizeof(auth);

	buf = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(auth);

	log_debug("%s: method %s length %zu",
	    __func__, print_map(auth.auth_method, ikev2_auth_map), len);

	print_hex(buf, 0, len);

	if (!ikev2_msg_frompeer(msg))
		return (0);

	/* The AUTH payload indicates if the responder wants EAP or not */
	if (!sa_stateok(sa, IKEV2_STATE_EAP))
		sa_state(env, sa, IKEV2_STATE_AUTH_REQUEST);

	idp = &msg->msg_parent->msg_auth;
	if (idp->id_type) {
		log_debug("%s: duplicate auth payload", __func__);
		return (-1);
	}

	ibuf_release(idp->id_buf);
	idp->id_type = auth.auth_method;
	idp->id_offset = 0;
	if ((idp->id_buf = ibuf_new(buf, len)) == NULL)
		return (-1);

	return (0);
}
Esempio n. 22
0
int
ca_privkey_serialize(EVP_PKEY *key, struct iked_id *id)
{
	RSA		*rsa = NULL;
	uint8_t		*d;
	int		 len = 0;
	int		 ret = -1;

	switch (key->type) {
	case EVP_PKEY_RSA:
		id->id_type = 0;
		id->id_offset = 0;
		ibuf_release(id->id_buf);

		if ((rsa = EVP_PKEY_get1_RSA(key)) == NULL)
			goto done;
		if ((len = i2d_RSAPrivateKey(rsa, NULL)) <= 0)
			goto done;
		if ((id->id_buf = ibuf_new(NULL, len)) == NULL)
			goto done;

		d = ibuf_data(id->id_buf);
		if (i2d_RSAPrivateKey(rsa, &d) != len) {
			ibuf_release(id->id_buf);
			goto done;
		}

		id->id_type = IKEV2_CERT_RSA_KEY;
		break;
	default:
		log_debug("%s: unsupported key type %d", __func__, key->type);
		return (-1);
	}

	log_debug("%s: type %s length %d", __func__,
	    print_map(id->id_type, ikev2_cert_map), len);

	ret = 0;
 done:
	if (rsa != NULL)
		RSA_free(rsa);
	return (ret);
}
Esempio n. 23
0
int
ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, off_t offset)
{
	struct iked_sa			*sa = msg->msg_sa;
	struct ikev2_cert		 cert;
	u_int8_t			*buf;
	size_t				 len;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	memcpy(&cert, msgbuf + offset, sizeof(cert));
	offset += sizeof(cert);

	buf = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);

	log_debug("%s: type %s signatures length %d",
	    __func__, print_map(cert.cert_type, ikev2_cert_map), len);
	print_hex(buf, 0, len);

	if (!ikev2_msg_frompeer(msg))
		return (0);

	if (!len || (len % SHA_DIGEST_LENGTH) != 0) {
		log_debug("%s: invalid certificate request", __func__);
		return (-1);
	}

	if (msg->msg_sa == NULL)
		return (-1);

	/* Optional certreq for PSK */
	if (sa->sa_hdr.sh_initiator)
		sa->sa_stateinit |= IKED_REQ_CERT;
	else
		sa->sa_statevalid |= IKED_REQ_CERT;

	ca_setreq(env, &sa->sa_hdr, &sa->sa_policy->pol_localid,
	    cert.cert_type, buf, len, PROC_CERT);

	return (0);
}
Esempio n. 24
0
int
ca_setcert(struct iked *env, struct iked_sahdr *sh, struct iked_id *id,
    u_int8_t type, u_int8_t *data, size_t len, enum privsep_procid procid)
{
	struct iovec		iov[4];
	int			iovcnt = 0;
	struct iked_static_id	idb;

	/* Must send the cert and a valid Id to the ca process */
	if (procid == PROC_CERT) {
		if (id == NULL || id->id_type == IKEV2_ID_NONE ||
		    ibuf_length(id->id_buf) > IKED_ID_SIZE)
			return (-1);
		bzero(&idb, sizeof(idb));

		/* Convert to a static Id */
		idb.id_type = id->id_type;
		idb.id_offset = id->id_offset;
		idb.id_length = ibuf_length(id->id_buf);
		memcpy(&idb.id_data, ibuf_data(id->id_buf),
		    ibuf_length(id->id_buf));

		iov[iovcnt].iov_base = &idb;
		iov[iovcnt].iov_len = sizeof(idb);
		iovcnt++;
	}

	iov[iovcnt].iov_base = sh;
	iov[iovcnt].iov_len = sizeof(*sh);
	iovcnt++;
	iov[iovcnt].iov_base = &type;
	iov[iovcnt].iov_len = sizeof(type);
	iovcnt++;
	iov[iovcnt].iov_base = data;
	iov[iovcnt].iov_len = len;
	iovcnt++;

	if (proc_composev_imsg(&env->sc_ps, procid, -1,
	    IMSG_CERT, -1, iov, iovcnt) == -1)
		return (-1);
	return (0);
}
Esempio n. 25
0
int
ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left)
{
	struct ikev2_keyexchange	 kex;
	u_int8_t			*buf;
	size_t				 len;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	if (ikev2_validate_ke(msg, offset, left, pld, &kex))
		return (-1);

	log_debug("%s: dh group %s reserved %d", __func__,
	    print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map),
	    betoh16(kex.kex_reserved));

	buf = msgbuf + offset + sizeof(kex);
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(kex);

	if (len == 0) {
		log_debug("%s: malformed payload: no KE data given", __func__);
		return (-1);
	}
	/* This will actually be caught by earlier checks. */
	if (left < len) {
		log_debug("%s: malformed payload: smaller than specified "
		     "(%zu < %zu)", __func__, left, len);
		return (-1);
	}

	print_hex(buf, 0, len);

	if (ikev2_msg_frompeer(msg)) {
		ibuf_release(msg->msg_parent->msg_ke);
		if ((msg->msg_parent->msg_ke = ibuf_new(buf, len)) == NULL) {
			log_debug("%s: failed to get exchange", __func__);
			return (-1);
		}
	}

	return (0);
}
Esempio n. 26
0
int
ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left)
{
	struct ikev2_cp		 cp;
	struct ikev2_cfg	*cfg;
	u_int8_t		*buf;
	size_t			 len, i;
	u_int8_t		*msgbuf = ibuf_data(msg->msg_data);
	struct iked_sa		*sa = msg->msg_sa;

	if (ikev2_validate_cp(msg, offset, left, pld, &cp))
		return (-1);
	offset += sizeof(cp);

	buf = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cp);

	log_debug("%s: type %s length %zu",
	    __func__, print_map(cp.cp_type, ikev2_cp_map), len);
	print_hex(buf, 0, len);

	for (i = 0; i < len;) {
		cfg = (struct ikev2_cfg *)(buf + i);

		log_debug("%s: %s 0x%04x length %d", __func__,
		    print_map(betoh16(cfg->cfg_type), ikev2_cfg_map),
		    betoh16(cfg->cfg_type),
		    betoh16(cfg->cfg_length));

		i += betoh16(cfg->cfg_length) + sizeof(*cfg);
	}

	if (!ikev2_msg_frompeer(msg))
		return (0);

	if (sa)
		sa->sa_cp = cp.cp_type;

	return (0);
}
Esempio n. 27
0
int
ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld,
    struct iked_message *msg, size_t offset, size_t left)
{
	struct ikev2_cert		 cert;
	u_int8_t			*buf;
	size_t				 len;
	struct iked_id			*certid;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	if (ikev2_validate_cert(msg, offset, left, pld, &cert))
		return (-1);
	offset += sizeof(cert);

	buf = msgbuf + offset;
	len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(cert);

	log_debug("%s: type %s length %zu",
	    __func__, print_map(cert.cert_type, ikev2_cert_map), len);

	print_hex(buf, 0, len);

	if (!ikev2_msg_frompeer(msg))
		return (0);

	certid = &msg->msg_parent->msg_cert;
	if (certid->id_type) {
		log_debug("%s: duplicate cert payload", __func__);
		return (-1);
	}

	if ((certid->id_buf = ibuf_new(buf, len)) == NULL) {
		log_debug("%s: failed to save cert", __func__);
		return (-1);
	}
	certid->id_type = cert.cert_type;
	certid->id_offset = 0;

	return (0);
}
Esempio n. 28
0
int
dsa_init(struct iked_dsa *dsa, const void *buf, size_t len)
{
	int	 ret;

	if (dsa->dsa_hmac) {
		if (!HMAC_Init_ex(dsa->dsa_ctx, ibuf_data(dsa->dsa_keydata),
		    ibuf_length(dsa->dsa_keydata), dsa->dsa_priv, NULL))
			return (-1);
		return (0);
	}

	if (dsa->dsa_sign)
		ret = EVP_SignInit_ex(dsa->dsa_ctx, dsa->dsa_priv, NULL);
	else {
		if ((ret = _dsa_verify_init(dsa, buf, len)) != 0)
			return (ret);
		ret = EVP_VerifyInit_ex(dsa->dsa_ctx, dsa->dsa_priv, NULL);
	}

	return (ret ? 0 : -1);
}
Esempio n. 29
0
int
ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left,
    struct ikev2_payload *pld)
{
	u_int8_t	*msgbuf = ibuf_data(msg->msg_data);
	size_t		 pld_length;

	/* We need at least the generic header. */
	if (left < sizeof(*pld)) {
		log_debug("%s: malformed payload: too short for generic "
		    "header (%zu < %zu)", __func__, left, sizeof(*pld));
		return (-1);
	}
	memcpy(pld, msgbuf + offset, sizeof(*pld));

	/*
	 * We need at least the specified number of bytes.
	 * pld_length is the full size of the payload including
	 * the generic payload header.
	 */
	pld_length = betoh16(pld->pld_length);
	if (left < pld_length) {
		log_debug("%s: malformed payload: shorter than specified "
		    "(%zu < %zu)", __func__, left, pld_length);
		return (-1);
	}
	/*
	 * Sanity check the specified payload size, it must
	 * be at last the size of the generic payload header.
	 */
	if (pld_length < sizeof(*pld)) {
		log_debug("%s: malformed payload: shorter than minimum "
		    "header size (%zu < %zu)", __func__, pld_length,
		    sizeof(*pld));
		return (-1);
	}

	return (0);
}
Esempio n. 30
0
int
ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm,
    struct iked_message *msg, off_t offset, int total)
{
	struct ikev2_attribute		 attr;
	u_int				 type;
	u_int8_t			*msgbuf = ibuf_data(msg->msg_data);

	memcpy(&attr, msgbuf + offset, sizeof(attr));

	type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV;

	log_debug("%s: attribute type %s length %d total %d",
	    __func__, print_map(type, ikev2_attrtype_map),
	    betoh16(attr.attr_length), total);

	if (betoh16(attr.attr_type) & IKEV2_ATTRAF_TV) {
		/* Type-Value attribute */
		offset += sizeof(attr);
		total -= sizeof(attr);

		if (type == IKEV2_ATTRTYPE_KEY_LENGTH)
			msg->msg_attrlength = betoh16(attr.attr_length);
	} else {
		/* Type-Length-Value attribute */
		print_hex(msgbuf, offset + sizeof(attr),
		    betoh16(attr.attr_length) - sizeof(attr));
		offset += betoh16(attr.attr_length);
		total -= betoh16(attr.attr_length);
	}

	if (total > 0) {
		/* Next attribute */
		ikev2_pld_attr(env, xfrm, msg, offset, total);
	}

	return (0);
}