summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-06-17 01:26:40 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-06-17 01:26:40 +0000
commit0b149da0e1ca74a753ba92dae7a479769fe61593 (patch)
treeefd407b9dfab40d7c9d92285791fb0a9c8260812
parent8de691236f7364060b2a6656c980be7812c419fd (diff)
parentea2001b4ca25164eebb00cb9d6c90f321849c7a5 (diff)
downloadnetd-android14-s2-release.tar.gz
Change-Id: If549641f0786d824d9cf8d5552cc07a153f1f6c9
-rw-r--r--server/XfrmController.cpp56
-rw-r--r--server/XfrmController.h10
-rw-r--r--server/XfrmControllerTest.cpp12
3 files changed, 58 insertions, 20 deletions
diff --git a/server/XfrmController.cpp b/server/XfrmController.cpp
index ed34f736..51c4197a 100644
--- a/server/XfrmController.cpp
+++ b/server/XfrmController.cpp
@@ -87,7 +87,9 @@ constexpr uint32_t ALGO_MASK_CRYPT_ALL = ~0;
// Exposed for testing
constexpr uint32_t ALGO_MASK_AEAD_ALL = ~0;
// Exposed for testing
-constexpr uint8_t REPLAY_WINDOW_SIZE = 32;
+constexpr uint8_t REPLAY_WINDOW_SIZE = 0;
+// Exposed for testing
+constexpr uint32_t REPLAY_WINDOW_SIZE_ESN = 4096;
namespace {
@@ -946,6 +948,7 @@ netdutils::Status XfrmController::updateSecurityAssociation(const XfrmSaInfo& re
nlattr_xfrm_output_mark xfrmoutputmark{};
nlattr_encap_tmpl encap{};
nlattr_xfrm_interface_id xfrm_if_id{};
+ nlattr_xfrm_replay_esn xfrm_replay_esn{};
enum {
NLMSG_HDR,
@@ -965,26 +968,30 @@ netdutils::Status XfrmController::updateSecurityAssociation(const XfrmSaInfo& re
ENCAP_PAD,
INTF_ID,
INTF_ID_PAD,
+ REPLAY_ESN, // Used to enable BMP (extended replay window) mode
+ REPLAY_ESN_PAD,
};
std::vector<iovec> iov = {
- {nullptr, 0}, // reserved for the eventual addition of a NLMSG_HDR
- {&usersa, 0}, // main usersa_info struct
- {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
- {&crypt, 0}, // adjust size if crypt algo is present
- {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
- {&aead, 0}, // adjust size if aead algo is present
- {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
- {&xfrmmark, 0}, // adjust size if xfrm mark is present
- {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
- {&xfrmoutputmark, 0}, // adjust size if xfrm output mark is present
- {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
- {&encap, 0}, // adjust size if encapsulating
- {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
- {&xfrm_if_id, 0}, // adjust size if interface ID is present
- {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {nullptr, 0}, // reserved for the eventual addition of a NLMSG_HDR
+ {&usersa, 0}, // main usersa_info struct
+ {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
+ {&crypt, 0}, // adjust size if crypt algo is present
+ {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
+ {&aead, 0}, // adjust size if aead algo is present
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {&xfrmmark, 0}, // adjust size if xfrm mark is present
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {&xfrmoutputmark, 0}, // adjust size if xfrm output mark is present
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {&encap, 0}, // adjust size if encapsulating
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {&xfrm_if_id, 0}, // adjust size if interface ID is present
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
+ {&xfrm_replay_esn, 0}, // Always use BMP mode with a large replay window
+ {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
};
if (!record.aead.name.empty() && (!record.auth.name.empty() || !record.crypt.name.empty())) {
@@ -1032,6 +1039,9 @@ netdutils::Status XfrmController::updateSecurityAssociation(const XfrmSaInfo& re
len = iov[INTF_ID].iov_len = fillNlAttrXfrmIntfId(record.xfrm_if_id, &xfrm_if_id);
iov[INTF_ID_PAD].iov_len = NLA_ALIGN(len) - len;
+ len = iov[REPLAY_ESN].iov_len = fillNlAttrXfrmReplayEsn(&xfrm_replay_esn);
+ iov[REPLAY_ESN_PAD].iov_len = NLA_ALIGN(len) - len;
+
return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, &iov);
}
@@ -1423,6 +1433,16 @@ int XfrmController::fillNlAttrXfrmIntfId(const uint32_t intfIdValue,
return len;
}
+int XfrmController::fillNlAttrXfrmReplayEsn(nlattr_xfrm_replay_esn* replay_esn) {
+ replay_esn->replay_state.replay_window = REPLAY_WINDOW_SIZE_ESN;
+ replay_esn->replay_state.bmp_len = (REPLAY_WINDOW_SIZE_ESN + 31) / 32;
+
+ // bmp array allocated in kernel, this does NOT account for that.
+ const int len = NLA_HDRLEN + sizeof(xfrm_replay_state_esn);
+ fillXfrmNlaHdr(&replay_esn->hdr, XFRMA_REPLAY_ESN_VAL, len);
+ return len;
+}
+
int XfrmController::fillNlAttrXfrmMigrate(const XfrmMigrateInfo& record,
nlattr_xfrm_user_migrate* migrate) {
migrate->migrate.old_daddr = record.dstAddr;
diff --git a/server/XfrmController.h b/server/XfrmController.h
index 781bc5e5..798284c9 100644
--- a/server/XfrmController.h
+++ b/server/XfrmController.h
@@ -48,6 +48,8 @@ extern const uint32_t ALGO_MASK_CRYPT_ALL;
extern const uint32_t ALGO_MASK_AEAD_ALL;
// Exposed for testing
extern const uint8_t REPLAY_WINDOW_SIZE;
+// Exposed for testing
+extern const uint32_t REPLAY_WINDOW_SIZE_ESN;
// Suggest we avoid the smallest and largest ints
class XfrmMessage;
@@ -316,6 +318,13 @@ public:
uint8_t key[MAX_KEY_LENGTH];
};
+ // Container for the content of an XFRMA_REPLAY_ESN_VAL netlink attribute.
+ // Exposed for testing
+ struct nlattr_xfrm_replay_esn {
+ nlattr hdr;
+ xfrm_replay_state_esn replay_state;
+ };
+
#pragma clang diagnostic pop
// Exposed for testing
@@ -413,6 +422,7 @@ public:
static int fillNlAttrXfrmOutputMark(const XfrmSaInfo& record,
nlattr_xfrm_output_mark* output_mark);
static int fillNlAttrXfrmIntfId(const __u32 intf_id_value, nlattr_xfrm_interface_id* intf_id);
+ static int fillNlAttrXfrmReplayEsn(nlattr_xfrm_replay_esn* replay_esn);
static int fillNlAttrXfrmMigrate(const XfrmMigrateInfo& record,
nlattr_xfrm_user_migrate* migrate);
diff --git a/server/XfrmControllerTest.cpp b/server/XfrmControllerTest.cpp
index ca53839b..c65e1f91 100644
--- a/server/XfrmControllerTest.cpp
+++ b/server/XfrmControllerTest.cpp
@@ -329,7 +329,8 @@ void testIpSecAddSecurityAssociation(testCaseParams params, const MockSyscalls&
size_t expectedMsgLength =
NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(xfrm_usersa_info)) +
NLA_ALIGN(offsetof(XfrmController::nlattr_algo_crypt, key) + KEY_LENGTH) +
- NLA_ALIGN(offsetof(XfrmController::nlattr_algo_auth, key) + KEY_LENGTH);
+ NLA_ALIGN(offsetof(XfrmController::nlattr_algo_auth, key) + KEY_LENGTH) +
+ NLA_ALIGN(sizeof(XfrmController::nlattr_xfrm_replay_esn));
uint32_t testIfId = 0;
uint32_t testMark = 0;
@@ -392,6 +393,7 @@ void testIpSecAddSecurityAssociation(testCaseParams params, const MockSyscalls&
// Extract and check the encryption/authentication algorithm
XfrmController::nlattr_algo_crypt _encryptAlgo{};
XfrmController::nlattr_algo_auth _authAlgo{};
+ XfrmController::nlattr_xfrm_replay_esn _replayEsn{};
// Need to use a pointer since you can't pass a structure with a variable
// sized array in a lambda.
XfrmController::nlattr_algo_crypt* const encryptAlgo = &_encryptAlgo;
@@ -399,7 +401,8 @@ void testIpSecAddSecurityAssociation(testCaseParams params, const MockSyscalls&
XfrmController::nlattr_xfrm_mark mark{};
XfrmController::nlattr_xfrm_output_mark outputmark{};
XfrmController::nlattr_xfrm_interface_id xfrm_if_id{};
- auto attrHandler = [&encryptAlgo, &authAlgo, &mark, &outputmark, &xfrm_if_id](
+ XfrmController::nlattr_xfrm_replay_esn* const replay_esn = &_replayEsn;
+ auto attrHandler = [&encryptAlgo, &authAlgo, &mark, &outputmark, &xfrm_if_id, &replay_esn](
const nlattr& attr, const Slice& attr_payload) {
Slice buf = attr_payload;
if (attr.nla_type == XFRMA_ALG_CRYPT) {
@@ -421,6 +424,9 @@ void testIpSecAddSecurityAssociation(testCaseParams params, const MockSyscalls&
} else if (attr.nla_type == XFRMA_IF_ID) {
xfrm_if_id.hdr = attr;
netdutils::extract(buf, xfrm_if_id.if_id);
+ } else if (attr.nla_type == XFRMA_REPLAY_ESN_VAL) {
+ replay_esn->hdr = attr;
+ netdutils::extract(buf, replay_esn->replay_state);
} else {
FAIL() << "Unexpected nlattr type: " << attr.nla_type;
}
@@ -432,6 +438,8 @@ void testIpSecAddSecurityAssociation(testCaseParams params, const MockSyscalls&
reinterpret_cast<void*>(&encryptAlgo->key), KEY_LENGTH));
EXPECT_EQ(0, memcmp(reinterpret_cast<void*>(authKey.data()),
reinterpret_cast<void*>(&authAlgo->key), KEY_LENGTH));
+ EXPECT_EQ(REPLAY_WINDOW_SIZE_ESN, replay_esn->replay_state.replay_window);
+ EXPECT_EQ((REPLAY_WINDOW_SIZE_ESN + 31) / 32, replay_esn->replay_state.bmp_len);
if (mode == XfrmMode::TUNNEL) {
if (params.xfrmInterfacesEnabled) {