Example #1
0
File: message.c Project: surki/hipl
int hip_read_user_control_msg(int socket, struct hip_common *hip_msg,
			      struct sockaddr_in6 *saddr)
{
	int err = 0, bytes, hdr_size = sizeof(struct hip_common), total;
	socklen_t len;

	memset(saddr, 0, sizeof(*saddr));

	len = sizeof(*saddr);

	HIP_IFEL(((total = hip_peek_recv_total_len(socket, 0, HIP_DEFAULT_MSG_TIMEOUT)) <= 0), -1,
		 "recv peek failed\n");

	_HIP_DEBUG("msg total length = %d\n", total);

	/** @todo Compiler warning;
	    warning: pointer targets in passing argument 6 of 'recvfrom'
	    differ in signedness. */
	HIP_IFEL(((bytes = recvfrom(socket, hip_msg, total, 0,
				    (struct sockaddr *) saddr,
				    &len)) != total), -1, "recv\n");

	HIP_DEBUG("received user message from local port %d\n",
		   ntohs(saddr->sin6_port));
	_HIP_DEBUG("read_user_control_msg recv len=%d\n", len);
	_HIP_HEXDUMP("recv saddr ", saddr, sizeof(struct sockaddr_un));
	_HIP_DEBUG("read %d bytes succesfully\n", bytes);
 out_err:
	if (bytes < 0 || err)
		HIP_PERROR("perror: ");

	return err;
}
Example #2
0
File: message.c Project: surki/hipl
int hip_daemon_bind_socket(int socket, struct sockaddr *sa) {
	int err = 0, port = 0, on = 1;
	struct sockaddr_in6 *addr = (struct sockaddr_in6 *) sa;

	HIP_ASSERT(addr->sin6_family == AF_INET6);

	errno = 0;

	if (setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
		HIP_DEBUG ("Failed to set socket option SO_REUSEADDR %s \n",  strerror(errno));
	}

	if (addr->sin6_port) {
		HIP_DEBUG("Bind to fixed port %d\n", addr->sin6_port);
		err = bind(socket,(struct sockaddr *)addr,
			   sizeof(struct sockaddr_in6));
		err = -errno;
		goto out_err;
	}

	/* try to bind first to a priviledged port and then to ephemeral */
	port = 1000;
	while (port++ < 61000) {
		_HIP_DEBUG("trying bind() to port %d\n", port);
		addr->sin6_port = htons(port);
		err = bind(socket,(struct sockaddr *)addr,
			   hip_sockaddr_len(addr));
		if (err == -1) {
			if (errno == EACCES) {
				/* Ephemeral ports:
				   /proc/sys/net/ipv4/ip_local_port_range */
				_HIP_DEBUG("Skipping to ephemeral range\n");
				port = 32768;
				errno = 0;
				err = 0;
			} else if (errno == EADDRINUSE) {
				_HIP_DEBUG("Port %d in use, skip\n", port);
				errno = 0;
				err = 0;
			} else {
				HIP_ERROR("Error %d bind() wasn't succesful\n",
					  errno);
				err = -1;
				goto out_err;
			}
		}
		else {
			_HIP_DEBUG("Bind() to port %d successful\n", port);
			goto out_err;
		}
	}

	if (port == 61000) {
		HIP_ERROR("All privileged ports were occupied\n");
		err = -1;
	}

 out_err:
	return err;
}
Example #3
0
int opendht_send(int sockfd, void *packet)
{
	int err = 0, len = strlen((char *)packet); 
  
	_HIP_DEBUG("Packet: %s\n",put_packet);
	_HIP_DEBUG("OpenDHT send: packet length: %d\n", len);
	
	if (len > 0)
		err = send(sockfd, (char *) packet, len, 0);

	if (err < 1)
		HIP_PERROR("Error opendht_send: ");

    return 0;
}
Example #4
0
File: dh.c Project: surki/hipl
/**
 * hip_calculate_shared_secret - Creates a shared secret based on the
 * public key of the peer (passed as an argument) and own DH private key
 * (created beforehand).
 * @param public_value Peer's Diffie-Hellman public key
 * @param group_id the Diffie-Hellman group ID
 * @param len the length of the public value
 * @param buffer Buffer that holds enough space for the shared secret.
 * @param bufsize size of the buffer
 *
 * @return the length of the shared secret in octets if successful,
 * or -1 if an error occured.
 */
int hip_calculate_shared_secret(uint8_t *public_value, uint8_t group_id,
                                signed int len, u8* buffer, int bufsize)
{
	int err;
	DH *tmp;

        /*
	 * First check that we have the key available.
	 * Then encode it into the buffer
	 */

	if (dh_table[group_id] == NULL) {
		tmp = hip_generate_dh_key(group_id);
		_HIP_DEBUG("Generating key\n");
		dh_table[group_id] = tmp;

		if (dh_table[group_id] == NULL) {
		        HIP_ERROR("Unsupported DH group: %d\n", group_id);
			return -1;
		}
	}

	err = hip_gen_dh_shared_key(dh_table[group_id], public_value,
				    len, buffer, bufsize);
	if (err < 0) {
                HIP_ERROR("Could not create shared secret\n");
		return -1;
        }

	_HIP_HEXDUMP("Peer DH pubkey", public_value, len);
	_HIP_HEXDUMP("Shared key", buffer, bufsize);

	return err;
}
Example #5
0
/**
 * handle_locator_value - This function copies the 2nd address (ipv4) from
 * the locator from packet returned from lookup
 * 
 * @param *packet response returned from the lookup service
 * @param *locator_ipv4 opaque pointer passed to point to the ipv4 address
 * @return status of the operation 0 on success, -1 on failure
 */
int handle_locator_value (unsigned char *packet, void *locator_ipv4)
{
	struct hip_locator *locator;
	struct hip_locator_info_addr_item *locator_address_item = NULL;
	int locator_item_count = 0;
	struct in6_addr addr6;
	struct in_addr addr4;
   
	locator = hip_get_param((struct hip_common *)packet, HIP_PARAM_LOCATOR);

	if (locator) {
		locator_item_count = hip_get_locator_addr_item_count(locator);
		locator_item_count--;
		locator_address_item = hip_get_locator_first_addr_item(locator);
		memcpy(&addr6, 
			(struct in6_addr*)&locator_address_item[locator_item_count].address, 
				sizeof(struct in6_addr));
		if (IN6_IS_ADDR_V4MAPPED(&addr6)) {
			IPV6_TO_IPV4_MAP(&addr6, &addr4);
			sprintf((char*)locator_ipv4, "%s", inet_ntoa(addr4));
		} else {
			hip_in6_ntop(&addr6, (char*)locator_ipv4);
			_HIP_DEBUG("Value: %s\n", (char*)locator_ipv4);
		}
		return 0 ;
	} else
		return -1;	
}
Example #6
0
File: opptcp.c Project: surki/hipl
/**
 * Send the ip of a peer to hipd, so that it can:
 * - unblock the packets that are sent to a particular peer.
 * - add it to the blacklist database.
 *
 * @param peer_ip	peer ip.
 * @return		nothing
 */
int hip_fw_unblock_and_blacklist(const struct in6_addr *peer_ip){
	struct hip_common *msg = NULL;
	int err = 0;

	HIP_DEBUG("\n");

	HIP_IFE(!(msg = hip_msg_alloc()), -1);

	HIP_IFEL(hip_build_param_contents(msg, (void *)(peer_ip),
					HIP_PARAM_IPV6_ADDR,
					sizeof(struct in6_addr)),
			-1, "build param HIP_PARAM_IPV6_ADDR failed\n");

	/* build the message header */
	HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_OPPTCP_UNBLOCK_AND_BLACKLIST, 0),
		 -1, "build hdr failed\n");
	HIP_DUMP_MSG(msg);

	/* send and receive msg to/from hipd */
	HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send_recv msg failed\n");
	_HIP_DEBUG("send_recv msg succeed\n");
	/* check error value */
	HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n");

out_err:
	return err;
}
Example #7
0
/** 
 * opendht_rm - Builds XML RPC packet and sends it through given socket and reads the response
 * @param sockfd Socket to be used with the send
 * @param key Key for the openDHT
 * @param value Value to be removed to the openDHT
 * @param secret Value to be used as a secret in remove
 * @param host Host address
 * @param response Buffer where the possible error message is saved 
 *
 * @return Returns integer -1 on error, on success 0
 */
int opendht_rm(int sockfd, 
                   unsigned char * key,
                   unsigned char * value, 
                   unsigned char * secret,
                   unsigned char * host,
                   int opendht_port,
                   int opendht_ttl)
{
    int key_len = 0;
    char put_packet[HIP_MAX_PACKET];
    char tmp_key[21];
    
    key_len = opendht_handle_key(key, tmp_key);
    
    /* Rm operation */
    memset(put_packet, '\0', sizeof(put_packet));
    if (build_packet_rm((unsigned char *)tmp_key,
                         key_len,
                         (unsigned char *)value,
	                 strlen((char *)value),
                         (unsigned char *)secret,
                         strlen((char *)secret),
                         opendht_port,
                         (unsigned char *)host,
                         put_packet, opendht_ttl) != 0)
        {
            HIP_DEBUG("Rm packet creation failed.\n");
            return(-1);
        }
    _HIP_DEBUG("Host address in OpenDHT rm : %s\n", host); 
    HIP_DEBUG("Actual OpenDHT send starts here\n");
    send(sockfd, put_packet, strlen(put_packet), 0);
    return(0);
}
Example #8
0
/*
 * Handle child exits to avoid zombies
 */
static void sig_chld (int signo)
{
	pid_t child_pid;
	int child_status; // child exit code
	child_pid = waitpid (0, &child_status, WNOHANG);
	/* Commented the following line to see if it helps with bug id 884
	   -miika */
	_HIP_DEBUG("child pid: %d, status: %d\n", child_pid, child_status);
}
Example #9
0
File: lsi.c Project: surki/hipl
/*
 * similar to the hip_request_peer_hit_from_hipd(...) function
 * 
 */
int hip_request_peer_hit_from_hipd_at_firewall(
			const struct in6_addr *peer_ip,
	         	struct in6_addr       *peer_hit,
			const struct in6_addr *local_hit,
			in_port_t             *src_tcp_port,
			in_port_t             *dst_tcp_port,
			int                   *fallback,
			int                   *reject){
	struct hip_common *msg = NULL;
	struct in6_addr *hit_recv = NULL;
	hip_hit_t *ptr = NULL;
	int err = 0;
	int ret = 0;

	*fallback = 1;
	*reject = 0;

	HIP_IFE(!(msg = hip_msg_alloc()), -1);

	HIP_IFEL(hip_build_param_contents(msg, (void *)(local_hit),
					  HIP_PARAM_HIT_LOCAL,
					  sizeof(struct in6_addr)),
			-1, "build param HIP_PARAM_HIT  failed\n");

	if (hip_opptcp) {
		HIP_IFEL(hip_build_param_contents(msg, (void *)(src_tcp_port),
						  HIP_PARAM_SRC_TCP_PORT,
						  sizeof(in_port_t)),
			 -1, "build param HIP_PARAM_SRC_TCP_PORT failed\n");
		
		HIP_IFEL(hip_build_param_contents(msg, (void *)(dst_tcp_port),
						  HIP_PARAM_DST_TCP_PORT,
						  sizeof(in_port_t)),
			 -1, "build param HIP_PARAM_DST_TCP_PORT failed\n");
	}

	HIP_IFEL(hip_build_param_contents(msg, (void *)(peer_ip),
					  HIP_PARAM_IPV6_ADDR_PEER,
					  sizeof(struct in6_addr)),
			-1, "build param HIP_PARAM_IPV6_ADDR failed\n");

	/* build the message header */
	HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_GET_PEER_HIT, 0),
		 -1, "build hdr failed\n");

	/* this message has to be delivered with the async socket because
	   opportunistic mode responds asynchronously */
	HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock),
		 -1, "send msg failed\n");

	_HIP_DEBUG("send_recv msg succeed\n");

 out_err:
	if(msg)
		free(msg);
	return err;
}
Example #10
0
int create_udp_ipv4_socket(in_port_t local_port) {
	int ipv4_sock = -1, err = 0, on = 1, sendnum;
	struct sockaddr_in inaddr_any;

	/* IPv6 "server" sockets support incoming IPv4 packets with
	   IPv4-in-IPv6 format. However, outgoing packets with IPv4-in-IPv6
	   formatted address stop working in some kernel version. Here
	   we create a socket for sending IPv4 packets. */
	ipv4_sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (ipv4_sock < 0) {
		printf("ipv4 socket\n");
		err = -1;
		goto out_err;
	}

	err = setsockopt(ipv4_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	if (err != 0) {
		perror("setsockopt SO_REUSEADDR");
		goto out_err;
	}

        err = setsockopt(ipv4_sock, IPPROTO_IP,
			 IP_PKTINFO, &on, sizeof(on));
	if (err != 0) {
		perror("setsockopt IP_PKTINFO");
		goto out_err;
	}

	/* Weird, but we have to set this option to receive
	   IPv4 addresses for UDP. We don't get them in mapped format. */ 
        err = setsockopt(ipv4_sock, IPPROTO_IP,
			 IP_PKTINFO, &on, sizeof(on));
	if (err != 0) {
		perror("setsockopt IP_PKTINFO");
		goto out_err;
	}

	_HIP_DEBUG("my local port %d\n", local_port);

	inaddr_any.sin_family = AF_INET;
	inaddr_any.sin_port = htons(local_port);
	inaddr_any.sin_addr.s_addr = htonl(INADDR_ANY);
	err = bind(ipv4_sock, (struct sockaddr *) &inaddr_any,
		   sizeof(inaddr_any));
	if (err) {
		perror("bind\n");
		goto out_err;
	}

out_err:
	if (err == 0)
		return ipv4_sock;
	else
		return -1;

}
Example #11
0
File: opptcp.c Project: surki/hipl
/**
 * Send the necessary data to hipd, so that a tcp packet is sent from there. This was done because it was not possible to send a packet directly from here.
 * 
 * @param *hdr		pointer to the packet that is to be sent.
 * @param packet_size	the size of the packet.
 * @param ip_version	ipv4 or ipv6.
 * @param addHit	whether the local HIT is to be added at the tcp options
 * @param addOption	whether the i1 option is to be added at the tcp options
 * @return		nothing
 */
int hip_request_send_tcp_packet(void *hdr,
				int   packet_size,
				int   ip_version,
				int   addHit,
				int   addOption){
	const struct hip_common *msg = NULL;
	int err = 0;
	
	HIP_DEBUG("\n");

	HIP_IFE(!(msg = hip_msg_alloc()), -1);

	HIP_IFEL(hip_build_param_contents(msg, (void *)hdr,
					  HIP_PARAM_IP_HEADER,
					  packet_size),
		-1, "build param HIP_PARAM_IP_HEADER failed\n");
	
	HIP_IFEL(hip_build_param_contents(msg, (int *)(&packet_size),
					  HIP_PARAM_PACKET_SIZE,
					  sizeof(int)),
		-1, "build param HIP_PARAM_PACKET_SIZE failed\n");

	HIP_IFEL(hip_build_param_contents(msg, (int *)(&ip_version),
					  HIP_PARAM_TRAFFIC_TYPE,
					  sizeof(int)),
		-1, "build param HIP_PARAM_TRAFFIC_TYPE failed\n");

	HIP_IFEL(hip_build_param_contents(msg, (int *)(&addHit),
					  HIP_PARAM_ADD_HIT,
					  sizeof(int)),
		-1, "build param HIP_PARAM_ADD_HIT failed\n");

	HIP_IFEL(hip_build_param_contents(msg, (int *)(&addOption),
					  HIP_PARAM_ADD_OPTION,
					  sizeof(int)),
		-1, "build param HIP_PARAM_ADD_OPTION failed\n");

	/* build the message header */
	HIP_IFEL(hip_build_user_hdr(msg, SO_HIP_OPPTCP_SEND_TCP_PACKET, 0),
		-1, "build hdr failed\n");
	HIP_DUMP_MSG(msg);
	/* send and receive msg to/from hipd */
	HIP_IFEL(hip_send_recv_daemon_info(msg, 1, hip_fw_async_sock), -1, "send_recv msg failed\n");
	_HIP_DEBUG("send_recv msg succeed\n");
	/* check error value */
	//HIP_IFEL(hip_get_msg_err(msg), -1, "Got erroneous message!\n");

 out_err:
	return err;
}
Example #12
0
File: keymat.c Project: surki/hipl
/** hip_update_entry_keymat - update HADB's KEYMAT related information
 * @param entry HADB entry to be update
 * @param new_keymat_index new Keymat Index value
 * @param new_calc_index new one byte value
 * @param new_current_keymat Kn related to @c new_calc_index
 */
void hip_update_entry_keymat(struct hip_hadb_state *entry, 
			     uint16_t new_keymat_index,
			     uint8_t new_calc_index,
			     uint16_t esp_keymat_index,
			     unsigned char *new_current_keymat)
{
	/* must have the hadb lock when calling this function */
	entry->current_keymat_index = new_keymat_index;
	entry->keymat_calc_index = new_calc_index;
	entry->esp_keymat_index = esp_keymat_index;
	_HIP_DEBUG("New Entry keymat data: current_keymat_index=%u keymat_calc_index=%u\n",
		   entry->current_keymat_index, entry->keymat_calc_index);
	if (new_current_keymat) {
		memcpy(entry->current_keymat_K, new_current_keymat, HIP_AH_SHA_LEN);
		_HIP_HEXDUMP("new_current_keymat", new_current_keymat, HIP_AH_SHA_LEN);
	}
}
Example #13
0
/**
 * hip_run_unit_test_space - select and run tests in the unit test space
 * @param unit_space pointer to an unit space structure
 * @param spaceid test space id (zero = all spaces)
 * @param suiteid test suite number (zero = all suites)
 * @param caseid test case nuber (zero = all cases)
 * @param err_log a string where the error log is stored
 * @param err_max the capacity of the string
 *
 * This is only needed in the userspace for selecting and launching the
 * test cases in the correct testspace (kernelspace or userspace).
 *
 * @return the number of errors occurred when the test cases were run.
 */
uint16_t hip_run_unit_test_space(struct hip_unit_test_space *unit_space,
				 uint16_t spaceid, uint16_t suiteid,
				 uint16_t caseid, void *err_log,
				 size_t err_max)
{
	/* Spaceid is indexed in the range [1..n] because zero is reserved for
	   executing in all spaces. However, xx_space variables below are
	   indexed in the range [0..n-1] for direct access into the
	   corresponding array. */
	uint16_t first_space, current_space, last_space;
	size_t err_len = 0, space_left = 0;
	void *err_index = err_log;
	uint16_t err = 0;

	first_space = (spaceid == 0) ? 0 : spaceid - 1;
	last_space = (spaceid == 0) ?
		unit_space->nbr - 1 : spaceid - 1;

	if (last_space > unit_space->nbr - 1) {
		HIP_ERROR("Trying to access illegal unit test spaceid (%d/%d).", last_space, unit_space->nbr - 1);
		err = 1;
		goto out;
	}

	/* make sure that the string will null padded even if nothing
	   will actually be written to err_log in the call to test suite */
	if (err_max > 0)
		((char *)err_log)[0] = '\0';

	_HIP_DEBUG("for index: %d-%d\n", first_space, last_space);

	for (current_space = first_space; current_space <= last_space;
	     current_space++) {
		space_left = ((void *)err_log) - err_index + err_max;
		/* if no space - ignore error messages, just count errors */
		if (space_left <= 0)
			err_len = 0;
		err += hip_run_unit_test_case(unit_space->test_suite_list[current_space], suiteid, caseid, err_index, space_left);
		err_len = strlen(err_index);
		err_index += err_len;
	}

 out:
	return err;
}
Example #14
0
/** 
 * opendht_put - Builds XML RPC packet and sends it through given socket and reads the response
 * @param sockfd Socket to be used with the send
 * @param key Key for the openDHT
 * @param value Value to be stored to the openDHT
 * @param host Host address
 * @param response Buffer where the possible error message is saved 
 *
 * @return Returns integer -1 on error, on success 0
 */
int opendht_put(unsigned char * key,
                unsigned char * value, 
                unsigned char * host,
                int opendht_port,
                int opendht_ttl, void *put_packet)
{
    int key_len = 0;
    int value_len = 0;
    char tmp_key[21];   
    char tmp_value[21];
        
    key_len = opendht_handle_key(key, tmp_key);   
    value_len = opendht_handle_value(value, tmp_value);
           
    /* Put operation FQDN->HIT */
    if (key_len > 0) {
            if (build_packet_put((unsigned char *)tmp_key,
                                 key_len,
                                 (unsigned char *)tmp_value,
                                 value_len,
                                 opendht_port,
                                 (unsigned char *)host,
                                 (char*)put_packet, opendht_ttl) != 0)
                    {
                            HIP_DEBUG("Put packet creation failed.\n");
                            return(-1);
                    }
    }  else {
            if (build_packet_put((unsigned char *)tmp_key,
                                 key_len,
                                 (unsigned char *)value,
                                 strlen((char *)value),
                                 opendht_port,
                                 (unsigned char *)host,
                                 (char*)put_packet, opendht_ttl) != 0)
                    {
                            HIP_DEBUG("Put packet creation failed.\n");
                            return(-1);
                    }
    }
    _HIP_DEBUG("HTTP packet for put is ready to be sent to queue\n"); 
    return(0);
}
Example #15
0
/**
 * hip_opendht_get_key - creates socket, connects to OpenDHT and gets the value under given key
 *
 * @param *value_handler(), a pointer function which treats different values from openDHT based
 * on the function assigned to it by the caller
 * @param gateway A addrinfo struct containing the gateway address
 * @param key Pointer to key to be fetched
 * @param opaque_answer Pointer to memory area where the corresponding value will be saved
 *  	  opaque_answer is set by poiner function sent as param
 * @param dont_verify_hdrr if passed 0 HDRR sig and hostid verification is done, otherwise skipped 
 * @return integer -1 on error, on success 0
 */
int hip_opendht_get_key(int (*value_handler)(unsigned char * packet,
             void * answer),struct addrinfo * gateway, 
                       const unsigned char * key, void * opaque_answer, int dont_verify_hdrr)
{
	int err = 0, sfd = -1;
	char hostname[256];
	char *host_addr = NULL;
	struct hostent *hoste = NULL;
	struct in6_addr hit_key; /* To convert DHT key (HIT) to in6_addr structure */
        
	memset(hostname,'\0',sizeof(hostname));
	HIP_IFEL((gethostname(hostname, sizeof(hostname))),-1,"Error getting hostname\n");
	HIP_IFEL(!(hoste = gethostbyname(hostname)),-1,
		"Encountered an error when getting host address\n");
	if (hoste->h_addrtype == AF_INET)
		host_addr = inet_ntoa(*(struct in_addr *)*hoste->h_addr_list);
	else if (hoste->h_addrtype == AF_INET6) {
		HIP_IFEL(inet_ntop(AF_INET6, &hoste->h_addr_list, 
			host_addr, sizeof(INET6_ADDRSTRLEN)),
			-1,"Error converting host IPv6 address\n");
	}
	else {
		HIP_DEBUG("Unknown host address family\n");
		goto out_err;
	}

	host_addr = OPENDHT_GATEWAY;
	_HIP_DEBUG("Host addresss %s\n", host_addr);
	sfd = init_dht_gateway_socket_gw(sfd, gateway);
 	HIP_IFEL((err = connect_dht_gateway(sfd, gateway, 1))
			,-1,"OpenDHT connect error\n");
	HIP_IFEL((err = opendht_get(sfd, (unsigned char *)key, 
				    (unsigned char *)host_addr, OPENDHT_PORT)),
		-1, "Opendht_get error");
	HIP_IFEL(opendht_read_response(sfd, opaque_answer), 
		 -1, "Opendht_read_response error\n"); 
	_HIP_DUMP_MSG((struct hip_common *)opaque_answer);

	/* Check if we found the key from lookup service or not */
	HIP_IFEL((((struct hip_common *)opaque_answer)->payload_len == NULL),
		 -1, "NULL response\n");

	/* Call the hdrr verification function, in case of hdrr
	   if key for lookup is hit, it has to be hdrr */
	
	if ((inet_pton(AF_INET6, key, &hit_key.s6_addr) == 0) || dont_verify_hdrr) { 
		_HIP_DEBUG("lookup is not for HDRR or " 
			   "HDRR verification flag not set so skipping verification \n");
	} else {
		err = verify_hddr_lib ((struct hip_common *)opaque_answer,&hit_key);
		if (err != 0) {
			/*HDRR verification failed*/
			opaque_answer = NULL ;
			HIP_DEBUG("HDRR verification failed \n");
			err = -1 ;
		} else HIP_DEBUG("HDRR verification was successful\n");
					
	}

out_err:
 	if (sfd)
		close(sfd); 

	return(err);
}
Example #16
0
/**
 * opendht_handle_key Modifies the key to suitable format for OpenDHT
 *
 * @param key Key to be handled
 * @param out_key Where the key will be saved
 *
 * @return -1 if false otherwise it will be len of out_key
 */
int opendht_handle_key(char * key, char * out_key) 
{
    int err = 0, key_len = 0, i = 0 ;
    unsigned char tmp_key[21];
    struct in6_addr addrkey;
    unsigned char *sha_retval;
	int key_len_specified_in_bytes = 20;
	unsigned char *paddedkey = NULL;
	/* Below three variables are used for key padding logic*/
	int k = 0;
	unsigned char tempChar1 =' ';
	unsigned char tempChar2 =' ';
		
	/* check for too long keys and convert HITs to numeric form */
    memset(tmp_key, '\0', sizeof(tmp_key));

	if (inet_pton(AF_INET6, (char *)key, &addrkey.s6_addr) == 0)
	{
 		/* inet_pton failed because of invalid IPv6 address */
		memset(tmp_key,'\0',sizeof(tmp_key));
		/* strlen works now but maybe not later */
		for (i = 0; i < strlen(key); i++ )
            key[i] = tolower(key[i]);
        if (key[strlen(key)] == '.')
            key[strlen(key)] == '\0';
        sha_retval = SHA1(key, strlen(key), tmp_key); 
        key_len = 20;
		err = key_len;
        _HIP_HEXDUMP("KEY FOR OPENDHT", tmp_key, key_len);
        if (!sha_retval)
        {
        	HIP_DEBUG("SHA1 error when creating key for OpenDHT.\n");
            return(-1);
        }                
    }
    else 
    {
		/* We require only last 100 bits of the HIT. That is to say
		to ignore first 28 bits we need to shift 28 bits left the HIT.
		Follwoing logic does it and zero padding is already done in memset
		above for tmp_key to make it 160 bit long key */
		paddedkey = malloc(key_len_specified_in_bytes +4);
		memset(paddedkey, '\0', key_len_specified_in_bytes +4);
    	memcpy(paddedkey, addrkey.s6_addr, sizeof(addrkey.s6_addr));		
		paddedkey = paddedkey + 3;
		while (k <13)
		{ 	/*We get the MSB hex byte from tempchar1 and LSB temchar2 */
			tempChar1 = *(paddedkey+k);
		 	tempChar2 = *(paddedkey+k+1);
		 	tempChar1 = tempChar1 << 4 ;
		 	tempChar2 = tempChar2 >> 4 ;
		 	*(paddedkey+k) = tempChar1 | tempChar2 ;
		 	k++;
		 }
		_HIP_DEBUG("New key value:  %d.\n", k);
		memcpy(tmp_key, paddedkey, k+1);
		key_len = key_len_specified_in_bytes ;
		err = key_len;
	}
	memcpy(out_key, tmp_key, sizeof(tmp_key));
out_err:
	if(paddedkey)
	{
		paddedkey = paddedkey -3 ;
		free(paddedkey);
	}
	return(err);
}
Example #17
0
File: keymat.c Project: surki/hipl
/**
 * hip_make_keymat - generate HIP keying material
 * @param kij Diffie-Hellman Kij (as in the HIP drafts)
 * @param kij_len the length of the Kij material
 * @param keymat pointer to a keymat structure which will be updated according
 *           to the generated keymaterial
 * @param dstbuf the generated keymaterial will be written here
 * @param hit1 source HIT
 * @param hit2 destination HIT
 * @param calc_index where the one byte index is stored (n of Kn)
 *
 */
void hip_make_keymat(char *kij, size_t kij_len,
		     struct hip_keymat_keymat *keymat, 
		     void *dstbuf, size_t dstbuflen, struct in6_addr *hit1,
		     struct in6_addr *hit2, u8 *calc_index,
		     uint64_t I, uint64_t J)
{
	int bufsize, err = 0;
	uint8_t index_nbr = 1;
	int dstoffset = 0;
	void *seedkey;
	struct in6_addr *smaller_hit, *bigger_hit;
	int hit1_is_bigger;
	u8 *shabuffer = NULL;

	HIP_DEBUG("\n");
	if (dstbuflen < HIP_AH_SHA_LEN) {
		HIP_ERROR("dstbuf is too short (%d)\n", dstbuflen);
		return;
	}

	_HIP_ASSERT(dstbuflen % 32 == 0);
	HIP_ASSERT(sizeof(index_nbr) == HIP_KEYMAT_INDEX_NBR_SIZE);

	hit1_is_bigger = hip_hit_is_bigger(hit1, hit2);

	bigger_hit =  hit1_is_bigger ? hit1 : hit2;
	smaller_hit = hit1_is_bigger ? hit2 : hit1;

	_HIP_HEXDUMP("kij", kij, kij_len);
	_HIP_DEBUG("I=0x%llx J=0x%llx\n", I, J);
	_HIP_HEXDUMP("bigger hit", bigger_hit, 16);
	_HIP_HEXDUMP("smaller hit", smaller_hit, 16);
	_HIP_HEXDUMP("index_nbr", (char *) &index_nbr,
		     HIP_KEYMAT_INDEX_NBR_SIZE);

	shabuffer = hip_create_keymat_buffer(kij, kij_len, HIP_AH_SHA_LEN,
					     smaller_hit, bigger_hit, I, J);
	if (!shabuffer) {
		HIP_ERROR("No memory for keymat\n");
		return;
	}

	bufsize = kij_len + 2 * sizeof(struct in6_addr) +
		2 * sizeof(uint64_t) + 1;
	//bufsize = kij_len+2*sizeof(struct in6_addr)+ 1;

	// XX FIXME: is this correct
	hip_build_digest(HIP_DIGEST_SHA1, shabuffer, bufsize, dstbuf);

	_HIP_HEXDUMP("keymat digest", dstbuf, HIP_AH_SHA_LEN);

	dstoffset = HIP_AH_SHA_LEN;
	index_nbr++;

	/*
	 * K2 = SHA1(Kij | K1 | 2)
	 * K3 = SHA1(Kij | K2 | 3)
	 * ...
	 */
	seedkey = dstbuf;
	hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
				 kij_len, index_nbr);

	while (dstoffset < dstbuflen) {
		hip_build_digest(HIP_DIGEST_SHA1, shabuffer,
				 kij_len + HIP_AH_SHA_LEN + 1,
				 dstbuf + dstoffset);
		seedkey = dstbuf + dstoffset;
		dstoffset += HIP_AH_SHA_LEN;
		index_nbr++;
		hip_update_keymat_buffer(shabuffer, seedkey, HIP_AH_SHA_LEN,
					 kij_len, index_nbr);
	}

	keymat->offset = 0;
	keymat->keymatlen = dstoffset;
	keymat->keymatdst = dstbuf;

	if (calc_index)
		*calc_index = index_nbr;
	else
		HIP_ERROR("NULL calc_index\n");

	_HIP_DEBUG("keymat index_nbr=%u\n", index_nbr);
	_HIP_HEXDUMP("GENERATED KEYMAT: ", dstbuf, dstbuflen);
	if (shabuffer)
		HIP_FREE(shabuffer);

	return;
}
Example #18
0
File: message.c Project: surki/hipl
/**
 * Finds out how much data is coming from a socket
 *
 * @param  socket         a file descriptor.
 * @param  encap_hdr_size udp etc header size
 * @param  timeout        -1 for blocking sockets, 0 or positive nonblocking
 * @return Number of bytes received on success or a negative error value on
 *         error.
 */
int hip_peek_recv_total_len(int socket, int encap_hdr_size,
			    unsigned long timeout)
{
	int bytes = 0, err = 0, flags = MSG_PEEK;
	unsigned long timeout_left = timeout;
	int hdr_size = encap_hdr_size + sizeof(struct hip_common);
	char *msg = NULL;
	hip_common_t *hip_hdr = NULL;
	struct timespec ts;

	ts.tv_sec = 0;
	ts.tv_nsec =  100000000;

        /* We're using system call here add thus reseting errno. */
	errno = 0;

	msg = (char *)malloc(hdr_size);
	HIP_IFEL(!msg, -ENOMEM, "Error allocating memory.\n");

	/* Make sure the socket does not block (bug id 806) */
	if (timeout >= 0)
		flags |= MSG_DONTWAIT;

	do {
		errno = 0;
		nanosleep(&ts, NULL);
		bytes = recv(socket, msg, hdr_size, flags);
		timeout_left -= ts.tv_nsec;
		_HIP_DEBUG("tol=%ld, ts=%ld, bytes=%d errno=%d\n",
			   timeout_left, ts.tv_nsec, bytes, errno);
	} while (timeout_left > 0 && errno == EAGAIN && bytes < 0);

	if(bytes < 0) {
		HIP_ERROR("recv() peek error (is hipd running?)\n");
		err = -EAGAIN;
		goto out_err;
	} else if (bytes < hdr_size) {
		HIP_ERROR("Packet payload is smaller than HIP header. Dropping.\n");
		/* Read and discard the datagram */
		recv(socket, msg, 0, 0);
		err = -bytes;
		goto out_err;
	}

	hip_hdr = (struct hip_common *) (msg + encap_hdr_size);
	bytes = hip_get_msg_total_len(hip_hdr);

	if(bytes == 0) {
		HIP_ERROR("HIP message is of zero length. Dropping.\n");
		recv(socket, msg, 0, 0);
		err = -EBADMSG;
		errno = EBADMSG;
		goto out_err;
	}

	/* The maximum possible length value is equal to HIP_MAX_PACKET.
	if(bytes > HIP_MAX_PACKET) {
		HIP_ERROR("HIP message max length exceeded. Dropping.\n");
		recv(socket, msg, 0, 0);
		err = -EMSGSIZE;
		errno = EMSGSIZE;
		goto out_err;
	} */

	bytes += encap_hdr_size;

 out_err:
	if (msg != NULL)
		free(msg);

	if (err)
		return err;

	return bytes;
}
Example #19
0
File: message.c Project: surki/hipl
/*
 * Don't call this function directly. Use hip_send_recv_daemon_info instead
 */
int hip_send_recv_daemon_info_internal(struct hip_common *msg, int opt_socket) {

	int hip_user_sock = 0, err = 0, n = 0, len = 0;
	struct sockaddr_in6 addr;
	uint8_t msg_type_old, msg_type_new;
	
	msg_type_old = hip_get_msg_type(msg);

	// We're using system call here and thus reseting errno.
	errno = 0;

	if (opt_socket) {
		hip_user_sock = opt_socket;
	} else {
		HIP_IFE(((hip_user_sock = socket(AF_INET6, SOCK_DGRAM, 0)) < 0), EHIP);

		memset(&addr, 0, sizeof(addr));
		addr.sin6_family = AF_INET6;
		addr.sin6_addr = in6addr_loopback;

		HIP_IFEL(hip_daemon_bind_socket(hip_user_sock,
						(struct sockaddr *) &addr), -1,
			 "bind failed\n");
		/* Connect to hipd. Otherwise e.g. "hipconf get ha all"
		   blocks when hipd is not running. */
		HIP_IFEL(hip_daemon_connect(hip_user_sock), -1,
			 "connect failed\n");
	}

	if ((len = hip_get_msg_total_len(msg)) < 0) {
		err = -EBADMSG;
		goto out_err;
	}

	/* Require a response from hipd */
	hip_set_msg_response(msg, 1);

	n = hip_sendto_hipd(hip_user_sock, msg, len);
	if (n < len) {
		HIP_ERROR("Could not send message to daemon.\n");
		err = -ECOMM;
		goto out_err;
	}

	HIP_DEBUG("Waiting to receive daemon info.\n");

	if((len = hip_peek_recv_total_len(hip_user_sock, 0, HIP_DEFAULT_MSG_TIMEOUT)) < 0) {
		err = len;
		goto out_err;
	}

	n = recv(hip_user_sock, msg, len, 0);

	/* You have a message synchronization problem if you see this error. */
	msg_type_new = hip_get_msg_type(msg);
	HIP_IFEL((msg_type_new != msg_type_old), -1,
		 "Message sync problem. Expected %d, got %d\n",
		 msg_type_old, msg_type_new);

	HIP_DEBUG("%d bytes received from HIP daemon\n", n);

	if (n == 0) {
		HIP_INFO("The HIP daemon has performed an "\
			 "orderly shutdown.\n");
		// Note. This is not an error condition, thus we return zero.
		goto out_err;
	} else if(n < sizeof(struct hip_common)) {
		HIP_ERROR("Could not receive message from daemon.\n");
		goto out_err;
	}

	if (hip_get_msg_err(msg)) {
		HIP_ERROR("HIP message contained an error.\n");
		err = -EHIP;
	}

	_HIP_DEBUG("Message received successfully\n");

 out_err:

	if (!opt_socket && hip_user_sock)
		close(hip_user_sock);

	return err;
}
Example #20
0
/**
 * Creates a socket and connects it a remote socket address. The connection is
 * tried using addresses in the @c peer_ai in the order specified by the linked
 * list of the structure. If a connection is successful, the rest of the
 * addresses are omitted. The socket is bound to the peer HIT, not to the peer
 * IP addresses.
 *
 * @param peer_ai a pointer to peer address info.
 * @param sock    a target buffer where the socket file descriptor is to be
 *                stored.
 * @return        zero on success, negative on failure. Possible error values
 *                are the @c errno values of socket(), connect() and close()
 *                with a minus sign.
 */
int hip_connect_func(struct addrinfo *peer_ai, int *sock)
{
	int err = 0, connect_err = 0;
	unsigned long microseconds = 0;
	struct timeval stats_before, stats_after;
	char ip_str[INET6_ADDRSTRLEN];
	struct addrinfo *ai = NULL;
	struct in_addr *ipv4 = NULL;
	struct in6_addr *ipv6 = NULL;

	/* Set the memory allocated from the stack to zeros. */
	memset(&stats_before, 0, sizeof(stats_before));
	memset(&stats_after, 0, sizeof(stats_after));
	memset(ip_str, 0, sizeof(ip_str));
	
	/* Loop through every address in the address info. */
	for(ai = peer_ai; ai != NULL; ai = ai->ai_next) {
	        if (ai->ai_family == AF_INET)
		  _HIP_DEBUG("AF_INET\n");
		else
		  _HIP_DEBUG("af_inet6\n");
	}
	for(ai = peer_ai; ai != NULL; ai = ai->ai_next) {
	        ipv4 = &((struct sockaddr_in *)ai->ai_addr)->sin_addr;
		ipv6 = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;

		/* Check the type of address we are connecting to and print
		   information about the address to the user. If address is
		   not supported the move to next address in peer_ai. */
		if (ai->ai_family == AF_INET) {
			inet_ntop(AF_INET, ipv4, ip_str, sizeof(ip_str));
			
			if(IS_LSI32(ipv4->s_addr)) {
				HIP_INFO("Connecting to LSI %s.\n", ip_str);
			} else {
				HIP_INFO("Connecting to IPv4 address %s.\n",
					 ip_str);
			}
		} else if(ai->ai_family == AF_INET6 ||
			  ai->ai_family == AF_HIP) {
			inet_ntop(AF_INET6, ipv6, ip_str, sizeof(ip_str));
			
			if(ipv6_addr_is_hit(ipv6)){
				HIP_INFO("Connecting to HIT %s.\n", ip_str);
			} else if (IN6_IS_ADDR_V4MAPPED(ipv6)) {
				HIP_INFO("Connecting to IPv6-mapped IPv4 "\
					 "address %s.\n", ip_str);
			} else {
				HIP_INFO("Connecting to IPv6 address %s.\n",
					 ip_str);
			}
		} else {
			_HIP_DEBUG("Trying to connect to a non-inet address "\
				  "family address. Skipping.\n");
			/* If there are no more address in peer_ai, these err
			   and errno values are returned. */
			errno = EAFNOSUPPORT;
			err = -1;
			continue;
		}

		err = 0;
		errno = 0;
		
		/* Get a socket for sending. */
		*sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);

		if(*sock < 3) {
			HIP_ERROR("Unable to get a socket for sending.\n");
			err = -1;
			goto out_err;
		}
		
		gettimeofday(&stats_before, NULL);
		connect_err = connect(*sock, ai->ai_addr, ai->ai_addrlen);
		
		/* If we're unable to connect to the remote address we try next
		   address in peer_ai. We back off if the closing of the socket
		   fails. */
		if(connect_err != 0){
			_HIP_ERROR("Unable to connect to the remote address.\n");
			if(close(*sock) != 0) {
				HIP_ERROR("Unable to close a socket.\n");
				err = -1;
				break;
			}
			*sock = 0;
			err = -1;
			continue;
		}
	
		gettimeofday(&stats_after, NULL);
		
		microseconds  =
			((stats_after.tv_sec - stats_before.tv_sec) * 1000000)
			+ (stats_after.tv_usec - stats_before.tv_usec);
		
		printf("Connecting socket to remote socket address took "\
		       "%.5f seconds.\n", microseconds / 1000000.0 );
		
		if (connect_err != 0) {
			if(close(*sock) != 0) {
				HIP_ERROR("Unable to close a socket.\n");
				err = -1;
				break;
			}
			*sock = 0;
			/* Try the next address in peer_ai. */
			continue;
		} else {
			/* Connect succeeded and data can be sent/received. */
			break;
		}
	}
		
 out_err:
	return err;
}
Example #21
0
/**
 * hip_run_unit_test_case - run a single or multiple HIP unit test cases.
 *
 * @param list pointer to a test suite list
 * @param suiteid test suite number (zero = all suites in the list)
 * @param caseid test case nuber (zero = all cases in the suite)
 * @param err_log a string where the error log is stored
 * @param err_max the capacity of the string
 *
 * @return the number of errors found from the runned testcases. Error
 * log of the test cases will be recorded into err_log.
 *
 */
uint16_t hip_run_unit_test_case(struct hip_unit_test_suite_list *list,
				uint16_t suiteid, uint16_t caseid,
				void *err_log, size_t err_max)
{
	size_t err_len = 0, space_left = 0;
	void *err_index = err_log;
	uint16_t err = 0;
	/* Suiteid and caseid are indexed in the range [1..n] because zero is
	   reserved for executing all tests. However, xx_suite and xx_case
	   variables below are indexed in the range [0..n-1] for direct
	   access into the corresponding arrays */
	uint16_t first_suite, current_suite, last_suite;
	uint16_t first_case, current_case, last_case;

	first_suite = (suiteid == 0) ? 0 : suiteid - 1;
	last_suite = (suiteid == 0) ?
		list->nbr - 1 : suiteid - 1;
	first_case = (caseid == 0) ? 0 : caseid - 1;

	_HIP_DEBUG("for1 index: %d-%d\n", suiteid, first_suite, last_suite);

	if (last_suite > list->nbr - 1) {
		HIP_ERROR("Trying to access illegal unit test suite (%d/%d)\n",
			  last_suite, list->nbr - 1);
		err = 1;
		goto out;
	}

        /* make sure that the string will null padded even if nothing
	   will actually be written to err_log in the call to test suite */
	if (err_max > 0)
		((char *)err_log)[0] = '\0';

	for (current_suite = first_suite; current_suite <= last_suite;
	     current_suite++) {
		last_case = (caseid == 0) ?
			list->test_suite[current_suite]->nbr - 1 :
		  caseid - 1;
		if (last_case >
		    list->test_suite[current_suite]->nbr - 1) {
			HIP_ERROR("Trying to access illegal test case (%d/%d)\n", last_case, list->test_suite[current_suite]->nbr - 1);
			err += 1;
			goto out;
		}

		for (current_case = first_case; current_case <= last_case;
		     current_case++) {
		  _HIP_DEBUG("for2 index: %d-%d\n", first_case, last_case);
			space_left = ((void *)err_log) - err_index + err_max;
			/* if no space left - ignore error messages,
			   just count errors */
			if (space_left <= 0)
				err_len = 0;
			list->test_suite[current_suite]->test_case[current_case]
				(&err, err_index, &err_len, space_left);

			/* glibc versions prior to 2.0.6 may return -1
			   if truncated */
			if (err_len < 0)
				space_left = 0;
			err_index += err_len;
		}
	}
 out:
	return err;

}
Example #22
0
File: lsi.c Project: surki/hipl
/**
 * Executes the packet reinjection
 *

 * @param src_hit              ipv6 source address 
 * @param dst_hit              ipv6 destination address
 * @param m                    pointer to the packet
 * @param ipOrigTraffic        type of Traffic (IPv4 or IPv6)
 * @param incoming             packet direction
 * @return	               err during the reinjection
 */
int reinject_packet(struct in6_addr *src_hit, struct in6_addr *dst_hit,
		    ipq_packet_msg_t *m, int ipOrigTraffic, int incoming)
{
        int err = 0, ip_hdr_size, packet_length = 0, protocol, ttl;
	u8 *msg;  
	struct icmphdr *icmp = NULL;

	if (ipOrigTraffic == 4) {
		struct ip *iphdr = (struct ip*) m->payload;
		ip_hdr_size = (iphdr->ip_hl * 4);  
		protocol = iphdr->ip_p;
		ttl = iphdr->ip_ttl;
        	HIP_DEBUG_LSI("Ipv4 address src ", &(iphdr->ip_src));
	        HIP_DEBUG_LSI("Ipv4 address dst ", &(iphdr->ip_dst));
	} else {
	        struct ip6_hdr* ip6_hdr = (struct ip6_hdr*) m->payload;
		ip_hdr_size = sizeof(struct ip6_hdr); //Fixed size
		protocol = ip6_hdr->ip6_nxt;
		ttl = ip6_hdr->ip6_hlim;
		HIP_DEBUG_IN6ADDR("Orig packet src address: ", &(ip6_hdr->ip6_src));
		HIP_DEBUG_IN6ADDR("Orig packet dst address: ", &(ip6_hdr->ip6_dst));
		HIP_DEBUG_IN6ADDR("New packet src address:", src_hit);
		HIP_DEBUG_IN6ADDR("New packet dst address: ", dst_hit);
	}
	
	if (m->data_len <= (BUFSIZE - ip_hdr_size)) {
		packet_length = m->data_len - ip_hdr_size; 	
	  	HIP_DEBUG("packet size smaller than buffer size\n");
	} else { 
	  	packet_length = BUFSIZE - ip_hdr_size;
		HIP_DEBUG("HIP packet size greater than buffer size\n");
	}

	_HIP_DEBUG("Reinject packet packet length (%d)\n", packet_length);
	_HIP_DEBUG("      Protocol %d\n", protocol);
	_HIP_DEBUG("      ipOrigTraffic %d \n", ipOrigTraffic);

	/* Note: using calloc to zero memory region here because I think
	   firewall_send_incoming_pkt() calculates checksum
	   from too long region sometimes. See bug id 874 */
	msg = (u8 *)calloc((packet_length + sizeof(struct ip)), 1);
	memcpy(msg, (m->payload)+ip_hdr_size, packet_length);

	if (protocol == IPPROTO_ICMP && incoming) {
		  icmp = (struct icmphdr *)msg;
		  HIP_DEBUG("incoming ICMP type=%d code=%d\n",
			    icmp->type,icmp->code);
		  /* Manually built due to kernel messed up with the
		     ECHO_REPLY message. Kernel was building an answer
		     message with equals @src and @dst*/
		  if (icmp->type == ICMP_ECHO) {
		  	icmp->type = ICMP_ECHOREPLY;
		    	err = firewall_send_outgoing_pkt(dst_hit, src_hit,
							 msg, packet_length,
							 protocol);
		  } else {
		    	err = firewall_send_incoming_pkt(src_hit, dst_hit,
							 msg, packet_length,
							 protocol, ttl);
		  }
	} else {
		  if (incoming) {
			    HIP_DEBUG("Firewall send to the kernel an incoming packet\n");
			    err = firewall_send_incoming_pkt(src_hit,
							     dst_hit, msg,
							     packet_length,
							     protocol, ttl);
		  } else {
			    HIP_DEBUG("Firewall send to the kernel an outgoing packet\n");
			    err = firewall_send_outgoing_pkt(src_hit,
							     dst_hit, msg,
							     packet_length,
							     protocol);
		  }
	}

	if(msg)
	        HIP_FREE(msg);
	return err;	
}
Example #23
0
File: keymat.c Project: surki/hipl
/** 
 * Calculates new keying material.
 *
 * This function gets next @c key_len bytes of KEYMAT to @c key starting from
 * requested offset @c keymat_index. On entry of this function @c calc_index
 * tells the one byte index value which is related to @c calc_index_keymat (for
 * example, if @c calc_index_keymat is K3, then @c calc_index is 3).
 *
 * On successful return, @c keymat_index and @c calc_index contain the values
 * used in the last round of calculating Kn of KEYMAT, @c calc_index_keymat
 * contains the last Kn, and @c Kn_is_at contains the byte offset value of
 * @c calc_index_keymat.
 *
 * @param key               buffer where the created KEYMAT is stored.
 * @param key_len           length of @c key in bytes.
 * @param kij               shared key.
 * @param kij_len           length of @c kij in bytes.
 * @param keymat_index      keymat index.
 * @param calc_index        the one byte index value.
 * @param calc_index_keymat Kn.
 * @param Kn_is_at          the byte offset where @c calc_index_keymat starts.
 * @return                  0 on success, < 0 otherwise.
 */
int hip_keymat_get_new(void *key, size_t key_len, char *kij, size_t kij_len,
		       uint16_t *keymat_index, uint8_t *calc_index,
		       unsigned char *calc_index_keymat, uint16_t *Kn_is_at)
{
	/* must have the hadb lock when calling this function */
	int err = 0;
	int copied = 0;
	u8 *tmp_data = NULL;
	size_t tmp_data_len;

	_HIP_DEBUG("key_len=%d, requested keymat_index=%u calc_index=%u Kn_is_at=%u\n",
		   key_len, *keymat_index, *calc_index, *Kn_is_at);
	_HIP_HEXDUMP("calc_index_keymat", calc_index_keymat, HIP_AH_SHA_LEN);

 	if (key_len == 0 || kij_len == 0) {
		HIP_ERROR("key_len = 0 or kij_len = 0\n");
		err = -EINVAL;
		goto out_err;
	}

	_HIP_DEBUG("one byte index at req'd index in the end should be %u\n",
		  (*keymat_index / HIP_AH_SHA_LEN + 1) % 256);

	if (*keymat_index < *Kn_is_at) {
		HIP_ERROR("requested keymat index %u is lower than lowest keymat index of Kn (%u)\n",
			  *keymat_index, *Kn_is_at);
		err = -EINVAL;
		goto out_err;
	}
	/** @todo Check here if we have to test *keymat_index <
	    entry->current_keymat_index ? */
	
	/* before calculating any hashes test if we already have
	 * needed amount of ready keymat
	 *
	 * must first check that the requested keymat_index is within the ready keymat
	 */
	if (*keymat_index - *Kn_is_at < HIP_AH_SHA_LEN) {
		int tmp = HIP_AH_SHA_LEN - (*keymat_index - *Kn_is_at);
		_HIP_DEBUG("test: can copy %d bytes from the end of sha K\n", tmp);
		if (tmp > HIP_AH_SHA_LEN) {
			HIP_ERROR("bug: tmp > 20\n");
			err = -EINVAL;
			goto out_err;
		}

		if (tmp > 0) {
			memcpy(key, calc_index_keymat + HIP_AH_SHA_LEN - tmp, tmp);
			copied += tmp;
		}
	}

	_HIP_DEBUG("copied=%d\n", copied);
	_HIP_HEXDUMP("KEY (0)", key, copied);

	if (copied == key_len) {
		_HIP_DEBUG("copied all, return\n");
		goto out;
	}

	_HIP_DEBUG("need %d bytes more data\n", key_len-copied);

	tmp_data_len = kij_len + HIP_AH_SHA_LEN + 1;
	tmp_data = (u8 *)HIP_MALLOC(tmp_data_len, GFP_KERNEL);
	if (!tmp_data) {
		HIP_ERROR("HIP_MALLOC failed\n");
		err = -ENOMEM;
		goto out_err;
	}

	memcpy(tmp_data, kij, kij_len); /* fixed part of every Kn round */

	while (copied < key_len) {
		(*calc_index)++;
		_HIP_DEBUG("calc_index=%u\n", *calc_index);
		/* create Kn = SHA-1( Kij | Kn-1 | calc_index) */

		/* Kij | Kn-1 */
		memcpy(tmp_data+kij_len, calc_index_keymat, HIP_AH_SHA_LEN);
		/* Kij | Kn-1 | calc_index */
		memcpy(tmp_data+kij_len+HIP_AH_SHA_LEN, calc_index, HIP_KEYMAT_INDEX_NBR_SIZE);
		/* SHA-1( Kij | Kn-1 | calc_index) */
		err = hip_build_digest(HIP_DIGEST_SHA1, tmp_data, tmp_data_len, calc_index_keymat);
		if (err) {
			HIP_ERROR("build_digest failed (K%u)\n", *calc_index);
			goto out_err;
		}
		*Kn_is_at += HIP_AH_SHA_LEN;
		if (*Kn_is_at + HIP_AH_SHA_LEN < *keymat_index) {
			HIP_DEBUG("skip until we are at right offset\n");
			continue;
		}

		_HIP_DEBUG("copied=%u, key_len=%u calc_index=%u dst to 0x%p\n", copied, key_len, *calc_index, key+copied);
		if (copied + HIP_AH_SHA_LEN <= key_len) {
			_HIP_DEBUG("copy whole sha block\n");
			memcpy(key+copied, calc_index_keymat, HIP_AH_SHA_LEN);
			copied += HIP_AH_SHA_LEN;
		} else {
			int t = HIP_AH_SHA_LEN - key_len % HIP_AH_SHA_LEN;
			t = key_len - copied;
			_HIP_DEBUG("copy partial %d bytes\n", t);
			memcpy(key+copied, calc_index_keymat, t);
			copied += t;
		}
	}

	_HIP_DEBUG("end: copied=%u\n", copied);

 out:
	_HIP_HEXDUMP("CALCULATED KEY", key, key_len);
	_HIP_DEBUG("at end: *keymat_index=%u *calc_index=%u\n",
		   *keymat_index, *calc_index);
 out_err:
	if(tmp_data)
		HIP_FREE(tmp_data);
	return err;
}