Add UDP Encap Support to XfrmController
-Add xfrm_encap_tmpl to ADDSA
Bug: 34812052
Test: cts - IpSecManagerTest:testUdpEncapsulation()
Change-Id: I743a2dbe4f5a497b2f77f7713a68e8970adfb7de
diff --git a/server/XfrmController.cpp b/server/XfrmController.cpp
index f1e0e23..344b268 100644
--- a/server/XfrmController.cpp
+++ b/server/XfrmController.cpp
@@ -25,6 +25,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
+#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <arpa/inet.h>
@@ -107,10 +109,14 @@
void* kPadBytes = static_cast<void*>(kPadBytesArray);
#if VDBG
-#define LOG_HEX(__desc16__, __buf__, __len__) \
- do{ logHex(__desc16__, __buf__, __len__); }while(0)
-#define LOG_IOV(__iov__, __iov_len__) \
- do{ logIov(__iov__, __iov_len__); }while(0)
+#define LOG_HEX(__desc16__, __buf__, __len__) \
+ do { \
+ logHex(__desc16__, __buf__, __len__); \
+ } while (0)
+#define LOG_IOV(__iov__, __iov_len__) \
+ do { \
+ logIov(__iov__, __iov_len__); \
+ } while (0)
void logHex(const char* desc16, const char* buf, size_t len) {
char* printBuf = new char[len * 2 + 1 + 26]; // len->ascii, +newline, +prefix strlen
@@ -314,7 +320,6 @@
const std::string& localAddress,
const std::string& remoteAddress, int32_t inSpi,
int32_t* outSpi) {
-
ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
ALOGD("transformId=%d", transformId);
ALOGD("direction=%d", direction);
@@ -351,7 +356,7 @@
int XfrmController::ipSecAddSecurityAssociation(
int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
- const std::string& remoteAddress, int64_t /* underlyingNetworkHandle */, int32_t spi,
+ const std::string& remoteAddress, int64_t underlyingNetworkHandle, int32_t spi,
const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort, int32_t* allocatedSpi) {
@@ -363,6 +368,7 @@
ALOGD("direction=%d", direction);
ALOGD("localAddress=%s", localAddress.c_str());
ALOGD("remoteAddress=%s", remoteAddress.c_str());
+ ALOGD("underlyingNetworkHandle=%" PRIx64, underlyingNetworkHandle);
ALOGD("spi=%0.8x", spi);
ALOGD("authAlgo=%s", authAlgo.c_str());
ALOGD("authTruncBits=%d", authTruncBits);
@@ -406,6 +412,32 @@
// failed to open
}
+ switch (static_cast<XfrmEncapType>(encapType)) {
+ case XfrmEncapType::ESPINUDP:
+ case XfrmEncapType::ESPINUDP_NON_IKE:
+ if (saInfo.addrFamily != AF_INET) {
+ return -EAFNOSUPPORT;
+ }
+ switch (saInfo.direction) {
+ case XfrmDirection::IN:
+ saInfo.encap.srcPort = encapRemotePort;
+ saInfo.encap.dstPort = encapLocalPort;
+ break;
+ case XfrmDirection::OUT:
+ saInfo.encap.srcPort = encapLocalPort;
+ saInfo.encap.dstPort = encapRemotePort;
+ break;
+ default:
+ return -EINVAL;
+ }
+ // fall through
+ case XfrmEncapType::NONE:
+ saInfo.encap.type = static_cast<XfrmEncapType>(encapType);
+ break;
+ default:
+ return -EINVAL;
+ }
+
ret = createTransportModeSecurityAssociation(saInfo, sock);
if (ret < 0) {
ALOGD("Failed creating a Security Association, line=%d", __LINE__);
@@ -419,7 +451,6 @@
int XfrmController::ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
const std::string& localAddress,
const std::string& remoteAddress, int32_t spi) {
-
ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
ALOGD("transformId=%d", transformId);
ALOGD("direction=%d", direction);
@@ -526,8 +557,8 @@
if (saInfo.addrFamily != saddr.ss_family) {
ALOGE("Transform address family(%d) differs from socket address "
- "family(%d)!",
- saInfo.addrFamily, saddr.ss_family);
+ "family(%d)!",
+ saInfo.addrFamily, saddr.ss_family);
return -EINVAL;
}
@@ -581,8 +612,20 @@
xfrm_usersa_info usersa{};
nlattr_algo_crypt crypt{};
nlattr_algo_auth auth{};
+ nlattr_encap_tmpl encap{};
- enum { NLMSG_HDR, USERSA, USERSA_PAD, CRYPT, CRYPT_PAD, AUTH, AUTH_PAD, iovLen };
+ enum {
+ NLMSG_HDR,
+ USERSA,
+ USERSA_PAD,
+ CRYPT,
+ CRYPT_PAD,
+ AUTH,
+ AUTH_PAD,
+ ENCAP,
+ ENCAP_PAD,
+ iovLen
+ };
iovec iov[] = {
{NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
@@ -592,6 +635,8 @@
{kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
{&auth, 0}, // adjust size if auth algo is present
{kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {&encap, 0}, // adjust size if auth algo is present
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
};
int len;
@@ -604,6 +649,8 @@
len = iov[AUTH].iov_len = fillNlAttrXfrmAlgoAuth(record.auth, &auth);
iov[AUTH_PAD].iov_len = NLA_ALIGN(len) - len;
+ len = iov[ENCAP].iov_len = fillNlAttrXfrmEncapTmpl(record, &encap);
+ iov[ENCAP_PAD].iov_len = NLA_ALIGN(len) - len;
return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
}
@@ -632,6 +679,19 @@
return len;
}
+int XfrmController::fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl) {
+ if (record.encap.type == XfrmEncapType::NONE) {
+ return 0;
+ }
+
+ int len = NLA_HDRLEN + sizeof(xfrm_encap_tmpl);
+ tmpl->tmpl.encap_type = static_cast<uint16_t>(record.encap.type);
+ tmpl->tmpl.encap_sport = htons(record.encap.srcPort);
+ tmpl->tmpl.encap_dport = htons(record.encap.dstPort);
+ fillXfrmNlaHdr(&tmpl->hdr, XFRMA_ENCAP, len);
+ return len;
+}
+
int XfrmController::fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa) {
fillTransportModeSelector(record, &usersa->sel);
@@ -712,7 +772,7 @@
if (ret == 0) {
*outSpi = spi;
- ALOGD("Allocated an SPI: %d", *outSpi);
+ ALOGD("Allocated an SPI: %x", *outSpi);
} else {
*outSpi = INVALID_SPI;
ALOGE("SPI Allocation Failed with error %d", ret);
@@ -730,7 +790,8 @@
fillTransportModeSelector(record, &usersp->sel);
fillXfrmLifetimeDefaults(&usersp->lft);
fillXfrmCurLifetimeDefaults(&usersp->curlft);
- /* if (index) index & 0x3 == dir -- must be true xfrm_user.c:verify_newpolicy_info() */
+ /* if (index) index & 0x3 == dir -- must be true
+ * xfrm_user.c:verify_newpolicy_info() */
usersp->index = 0;
usersp->dir = static_cast<uint8_t>(record.direction);
usersp->action = XFRM_POLICY_ALLOW;