/* 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; }
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); }
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; }