Example #1
0
/* Add remote address */
static int netlink_addroute(uint32_t ifa_index, uint8_t remote)
{
	struct rtmsg *rtm;
	struct rtattr *rta;
	uint32_t reqlen = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(*rtm)) +
				RTA_SPACE(1) +
				RTA_SPACE(sizeof(ifa_index)));
	struct req {
		struct nlmsghdr nlh;
		char buf[512];
	} req = {
		.nlh = {
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK
					| NLM_F_CREATE | NLM_F_APPEND,
			.nlmsg_type = RTM_NEWROUTE,
			.nlmsg_pid = getpid(),
			.nlmsg_len = reqlen,
		},
	};
	size_t buflen = sizeof(req.buf) - sizeof(*rtm);
	int fd;
	int error;
	struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };

	rtm = NLMSG_DATA(&req.nlh);
	rtm->rtm_family = AF_PHONET;
	rtm->rtm_dst_len = 6;
	rtm->rtm_src_len = 0;
	rtm->rtm_tos = 0;

	rtm->rtm_table = RT_TABLE_MAIN;
	rtm->rtm_protocol = RTPROT_STATIC;
	rtm->rtm_scope = RT_SCOPE_UNIVERSE;
	rtm->rtm_type = RTN_UNICAST;
	rtm->rtm_flags = 0;

	rta = IFA_RTA(rtm);
	rta->rta_type = RTA_DST;
	rta->rta_len = RTA_LENGTH(1);
	*(uint8_t *)RTA_DATA(rta) = remote;

	rta = RTA_NEXT(rta, buflen);
	rta->rta_type = RTA_OIF;
	rta->rta_len = RTA_LENGTH(sizeof(ifa_index));
	*(uint32_t *)RTA_DATA(rta) = ifa_index;

	fd = netlink_socket();
	if (fd == -1)
		return -errno;

	if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1)
		error = -errno;
	else
		error = netlink_getack(fd);

	close(fd);

	return error;
}
int cryptodev_get_cipher_keylen(unsigned int *keylen, struct session_op *sop,
		int aead)
{
	/*
	 * For blockciphers (AES-CBC) or non-composite aead ciphers (like AES-GCM),
	 * the key length is simply the cipher keylen obtained from userspace. If
	 * the cipher is composite aead, the keylen is the sum of cipher keylen,
	 * hmac keylen and a key header length. This key format is the one used in
	 * Linux kernel for composite aead ciphers (crypto/authenc.c)
	 */
	unsigned int klen = sop->keylen;

	if (unlikely(sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN))
		return -EINVAL;

	if (aead && sop->mackeylen) {
		if (unlikely(sop->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN))
			return -EINVAL;
		klen += sop->mackeylen;
		klen += RTA_SPACE(sizeof(struct crypto_authenc_key_param));
	}

	*keylen = klen;
	return 0;
}
int cryptodev_get_cipher_key(uint8_t *key, struct session_op *sop, int aead)
{
	/*
	 * Get cipher key from user-space. For blockciphers just copy it from
	 * user-space. For composite aead ciphers combine it with the hmac key in
	 * the format used by Linux kernel in crypto/authenc.c:
	 *
	 * [[AUTHENC_KEY_HEADER + CIPHER_KEYLEN] [AUTHENTICATION KEY] [CIPHER KEY]]
	 */
	struct crypto_authenc_key_param *param;
	struct rtattr *rta;
	int ret = 0;

	if (aead && sop->mackeylen) {
		/*
		 * Composite aead ciphers. The first four bytes are the header type and
		 * header length for aead keys
		 */
		rta = (void *)key;
		rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
		rta->rta_len = RTA_LENGTH(sizeof(*param));

		/*
		 * The next four bytes hold the length of the encryption key
		 */
		param = RTA_DATA(rta);
		param->enckeylen = cpu_to_be32(sop->keylen);

		/* Advance key pointer eight bytes and copy the hmac key */
		key += RTA_SPACE(sizeof(*param));
		if (unlikely(copy_from_user(key, sop->mackey, sop->mackeylen))) {
			ret = -EFAULT;
			goto error;
		}
		/* Advance key pointer past the hmac key */
		key += sop->mackeylen;
	}
	/* now copy the blockcipher key */
	if (unlikely(copy_from_user(key, sop->key, sop->keylen)))
		ret = -EFAULT;

error:
	return ret;
}
Example #4
0
static int netlink_getack(int fd)
{
	struct {
		struct nlmsghdr nlh;
		char buf[SIZE_NLMSG];
	} resp;
	struct iovec iov = { &resp, sizeof(resp), };
	struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1, };
	ssize_t ret;
	struct nlmsghdr *nlh = &resp.nlh;

	ret = recvmsg(fd, &msg, 0);
	if (ret == -1)
		return -errno;

	if (msg.msg_flags & MSG_TRUNC)
		return -EIO;

	for (; NLMSG_OK(nlh, (size_t)ret); nlh = NLMSG_NEXT(nlh, ret)) {

		if (nlh->nlmsg_type == NLMSG_DONE)
			return 0;

		if (nlh->nlmsg_type == NLMSG_ERROR) {
			struct nlmsgerr *err = NLMSG_DATA(nlh);
			return err->error;
		}
	}

	return -EIO;
}

/* Set local address */
static int netlink_setaddr(uint32_t ifa_index, uint8_t ifa_local)
{
	struct ifaddrmsg *ifa;
	struct rtattr *rta;
	uint32_t reqlen = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(*ifa))
				+ RTA_SPACE(1));
	struct req {
		struct nlmsghdr nlh;
		char buf[512];
	} req = {
		.nlh = {
			.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK,
			.nlmsg_type = RTM_NEWADDR,
			.nlmsg_pid = getpid(),
			.nlmsg_len = reqlen,
		},
	};
	int fd;
	int error;
	struct sockaddr_nl addr = { .nl_family = AF_NETLINK, };

	ifa = NLMSG_DATA(&req.nlh);
	ifa->ifa_family = AF_PHONET;
	ifa->ifa_prefixlen = 0;
	ifa->ifa_index = ifa_index;

	rta = IFA_RTA(ifa);
	rta->rta_type = IFA_LOCAL;
	rta->rta_len = RTA_LENGTH(1);
	*(uint8_t *)RTA_DATA(rta) = ifa_local;

	fd = netlink_socket();
	if (fd == -1)
		return -errno;

	if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1)
		error = -errno;
	else
		error = netlink_getack(fd);

	close(fd);

	return error;
}

int g_pn_netlink_set_address(GIsiModem *idx, uint8_t local)
{
	uint32_t ifindex = g_isi_modem_index(idx);

	if (ifindex == 0)
		return -ENODEV;

	if (local != PN_DEV_PC && local != PN_DEV_SOS)
		return -EINVAL;

	return netlink_setaddr(ifindex, local);
}
Example #5
0
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
{
    struct ifinfomsg  *ifm = NLMSG_DATA(in_nlh);
    struct rtattr    **ida = arg;
    struct net_device *dev;
    struct ifinfomsg *r;
    struct nlmsghdr  *nlh;
    int err = -ENOBUFS;
    struct sk_buff *skb;
    unsigned char	 *b;
    char *iw_buf = NULL;
    int iw_buf_len = 0;

    if (ifm->ifi_index >= 0)
        dev = dev_get_by_index(ifm->ifi_index);
    else
        return -EINVAL;
    if (!dev)
        return -ENODEV;

#ifdef CONFIG_NET_WIRELESS_RTNETLINK
    if (ida[IFLA_WIRELESS - 1]) {

        /* Call Wireless Extensions. We need to know the size before
         * we can alloc. Various stuff checked in there... */
        err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
        if (err)
            goto out;
    }
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

    /* Create a skb big enough to include all the data.
     * Some requests are way bigger than 4k... Jean II */
    skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
                    GFP_KERNEL);
    if (!skb)
        goto out;
    b = skb->tail;

    /* Put in the message the usual good stuff */
    nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
                    RTM_NEWLINK, sizeof(*r));
    r = NLMSG_DATA(nlh);
    r->ifi_family = AF_UNSPEC;
    r->__ifi_pad = 0;
    r->ifi_type = dev->type;
    r->ifi_index = dev->ifindex;
    r->ifi_flags = dev->flags;
    r->ifi_change = 0;

    /* Put the wireless payload if it exist */
    if(iw_buf != NULL)
        RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
                iw_buf + IW_EV_POINT_OFF);

    nlh->nlmsg_len = skb->tail - b;

    /* Needed ? */
    NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

    err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
    if (err > 0)
        err = 0;
out:
    if(iw_buf != NULL)
        kfree(iw_buf);
    dev_put(dev);
    return err;

rtattr_failure:
nlmsg_failure:
    kfree_skb(skb);
    goto out;
}
/* Allocate out aead at the time of creation of new out SA. 
   pSA : pointer to out SA
   ptr_aead : pointer to crypto_aead created corresponding to SA
*/
int32_t asf_alloc_aead_out(outSA_t *pSA, struct crypto_aead ** ptr_aead)
{
	struct crypto_aead * aead = NULL;
	struct crypto_authenc_key_param *param;
	struct rtattr *rta;
	char *key;
	char *p;
	char authenc_name[CRYPTO_MAX_ALG_NAME];
	unsigned int keylen;
	int err;
	int aeadAlgo = 0;
	int saltLen=0;

	ASF_FP_LINUX_CRYPTO_FENTRY;	
        err = -EINVAL;
        if(unlikely(!(pSA->SAParams.bEncrypt)))
                goto error;

        err = -ENAMETOOLONG;

	//Check if AEAD algorithm
	if(pSA->SAParams.ucCipherAlgo >= 14 && pSA->SAParams.ucCipherAlgo < 24)
	{
		aeadAlgo = 1;
		if(unlikely(snprintf(authenc_name,CRYPTO_MAX_ALG_NAME,"%s", 
			get_enc_algo(pSA->SAParams.ucCipherAlgo)) >= CRYPTO_MAX_ALG_NAME))
		goto error;
	}
        else
	{
	    ASF_FP_LINUX_CRYPTO_DEBUG("test: asf_alloc_aead_out -Not AEAD ALOGO \
			pSA->SAParams.ucCipherAlgo = %d: %d \n", 
			pSA->SAParams.ucCipherAlgo, __LINE__);
            if (pSA->SAParams.bUseExtendedSequenceNumber)
            {
                if(unlikely(snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
                            "authencesn(%s,%s)",
                            pSA->SAParams.bAuth ? get_auth_algo(pSA->SAParams.ucAuthAlgo) : 
			    "digest_null", 
                            get_enc_algo(pSA->SAParams.ucCipherAlgo)) >= CRYPTO_MAX_ALG_NAME))
                        goto error;
            } 
            else 
            {
                if(unlikely (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME,
                             "authenc(%s,%s)",
                             pSA->SAParams.bAuth ? get_auth_algo(pSA->SAParams.ucAuthAlgo) : 
			     "digest_null", 
                             get_enc_algo(pSA->SAParams.ucCipherAlgo)) >= CRYPTO_MAX_ALG_NAME) )
                        goto error;
            }
	}
	ASF_FP_LINUX_CRYPTO_DEBUG("asf_alloc_aead_out authenc_name = %s: %d\n", 
			authenc_name, __LINE__);
        aead = crypto_alloc_aead(authenc_name, 0, 0);
        err = PTR_ERR(aead);
        if(unlikely (IS_ERR(aead)))
                goto error;
	if(!aeadAlgo)
	{
        	keylen = (pSA->SAParams.bAuth ? pSA->SAParams.AuthKeyLen : 0) +
                	pSA->SAParams.EncKeyLen + RTA_SPACE(sizeof(*param));
        	err = -ENOMEM;
        	key = kmalloc(keylen, GFP_KERNEL);

		ASF_FP_LINUX_CRYPTO_DEBUG("asf_alloc_aead_out keylen = %d \
			pSA->SAParams.EncKeyLen = %d pSA->SAParams.AuthKeyLen = %d \
			: %d\n", keylen, pSA->SAParams.EncKeyLen, 
			pSA->SAParams.AuthKeyLen, __LINE__);

        	if(unlikely (!key))
                	goto error;
	}