blob: 784c04665fef5c279e0f770274b2caa6b283929d [file] [log] [blame]
Nathan Harold1a371532017-01-30 12:30:48 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef _XFRM_CONTROLLER_H
17#define _XFRM_CONTROLLER_H
18
19#include <atomic>
20#include <list>
21#include <map>
22#include <string>
23#include <utility> // for pair
24
manojboopathi8707f232018-01-02 14:45:47 -080025#include <linux/if_link.h>
26#include <linux/if_tunnel.h>
Nathan Harold1a371532017-01-30 12:30:48 -080027#include <linux/netlink.h>
Nathan Harold420ceac2017-04-05 19:36:59 -070028#include <linux/udp.h>
Nathan Harold1a371532017-01-30 12:30:48 -080029#include <linux/xfrm.h>
Bernie Innocenti97f388f2018-10-16 19:17:08 +090030#include <unistd.h>
Nathan Harold1a371532017-01-30 12:30:48 -080031
32#include "NetdConstants.h"
Bernie Innocenti97f388f2018-10-16 19:17:08 +090033#include "android-base/unique_fd.h"
manojboopathi8707f232018-01-02 14:45:47 -080034#include "netdutils/Slice.h"
ludi6e8eccd2017-08-14 14:40:37 -070035#include "netdutils/Status.h"
Bernie Innocenti97f388f2018-10-16 19:17:08 +090036#include "sysutils/SocketClient.h"
Nathan Harold1a371532017-01-30 12:30:48 -080037
38namespace android {
39namespace net {
40
Nathan Harold39b5df42017-08-02 18:45:25 -070041// Exposed for testing
42extern const uint32_t ALGO_MASK_AUTH_ALL;
43// Exposed for testing
44extern const uint32_t ALGO_MASK_CRYPT_ALL;
45// Exposed for testing
Benedict Wongbe65b432017-08-22 21:43:14 -070046extern const uint32_t ALGO_MASK_AEAD_ALL;
47// Exposed for testing
Nathan Harold39b5df42017-08-02 18:45:25 -070048extern const uint8_t REPLAY_WINDOW_SIZE;
49
Nathan Harold1a371532017-01-30 12:30:48 -080050// Suggest we avoid the smallest and largest ints
51class XfrmMessage;
52class TransportModeSecurityAssociation;
53
54class XfrmSocket {
55public:
56 virtual void close() {
Nathan Harold420ceac2017-04-05 19:36:59 -070057 if (mSock >= 0) {
Nathan Harold1a371532017-01-30 12:30:48 -080058 ::close(mSock);
59 }
60 mSock = -1;
61 }
62
ludi6e8eccd2017-08-14 14:40:37 -070063 virtual netdutils::Status open() = 0;
Nathan Harold1a371532017-01-30 12:30:48 -080064
65 virtual ~XfrmSocket() { close(); }
66
ludie51e3862017-08-15 19:28:12 -070067 // Sends the netlink message contained in iovecs. This populates iovecs[0] with
68 // a valid netlink message header.
ludi6e8eccd2017-08-14 14:40:37 -070069 virtual netdutils::Status sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags,
70 uint16_t nlMsgSeqNum,
71 std::vector<iovec>* iovecs) const = 0;
Nathan Harold1a371532017-01-30 12:30:48 -080072
73protected:
74 int mSock;
75};
76
77enum struct XfrmDirection : uint8_t {
78 IN = XFRM_POLICY_IN,
79 OUT = XFRM_POLICY_OUT,
80 FORWARD = XFRM_POLICY_FWD,
81 MASK = XFRM_POLICY_MASK,
82};
83
84enum struct XfrmMode : uint8_t {
85 TRANSPORT = XFRM_MODE_TRANSPORT,
86 TUNNEL = XFRM_MODE_TUNNEL,
87};
88
Nathan Harold420ceac2017-04-05 19:36:59 -070089enum struct XfrmEncapType : uint16_t {
90 NONE = 0,
91 ESPINUDP_NON_IKE = UDP_ENCAP_ESPINUDP_NON_IKE,
92 ESPINUDP = UDP_ENCAP_ESPINUDP
93};
94
Nathan Harold1a371532017-01-30 12:30:48 -080095struct XfrmAlgo {
96 std::string name;
97 std::vector<uint8_t> key;
98 uint16_t truncLenBits;
99};
100
Nathan Harold420ceac2017-04-05 19:36:59 -0700101struct XfrmEncap {
102 XfrmEncapType type;
103 uint16_t srcPort;
104 uint16_t dstPort;
105};
106
Nathan Harold7441c692017-12-12 21:25:01 -0800107// minimally sufficient structure to match either an SA or a Policy
Benedict Wonga04ffa72018-05-09 21:42:42 -0700108struct XfrmCommonInfo {
Nathan Harold1a371532017-01-30 12:30:48 -0800109 xfrm_address_t dstAddr; // network order
110 xfrm_address_t srcAddr;
111 int addrFamily; // AF_INET or AF_INET6
112 int transformId; // requestId
113 int spi;
Di Lu2ccb3e52018-01-03 16:19:20 -0800114 xfrm_mark mark;
Nathan Harold1a371532017-01-30 12:30:48 -0800115};
116
Benedict Wonga04ffa72018-05-09 21:42:42 -0700117struct XfrmSaInfo : XfrmCommonInfo {
Nathan Harold1a371532017-01-30 12:30:48 -0800118 XfrmAlgo auth;
119 XfrmAlgo crypt;
Benedict Wongbe65b432017-08-22 21:43:14 -0700120 XfrmAlgo aead;
Nathan Harold1a371532017-01-30 12:30:48 -0800121 int netId;
122 XfrmMode mode;
Nathan Harold420ceac2017-04-05 19:36:59 -0700123 XfrmEncap encap;
Nathan Harold1a371532017-01-30 12:30:48 -0800124};
125
Benedict Wonga04ffa72018-05-09 21:42:42 -0700126struct XfrmSpInfo : XfrmSaInfo {
127 // Address family in XfrmCommonInfo used for template/SA matching, need separate addrFamily
128 // for selectors
129 int selAddrFamily; // AF_INET or AF_INET6
130};
131
Nathan Harold1a371532017-01-30 12:30:48 -0800132class XfrmController {
133public:
134 XfrmController();
135
Nathan Harold21299f72018-03-16 20:13:03 -0700136 static netdutils::Status Init();
Benedict Wongb2daefb2017-12-06 22:05:46 -0800137
Nathan Harold21299f72018-03-16 20:13:03 -0700138 static netdutils::Status ipSecSetEncapSocketOwner(const android::base::unique_fd& socket,
139 int newUid, uid_t callerUid);
Nathan Harold1a371532017-01-30 12:30:48 -0800140
Nathan Harold21299f72018-03-16 20:13:03 -0700141 static netdutils::Status ipSecAllocateSpi(int32_t transformId, const std::string& localAddress,
142 const std::string& remoteAddress, int32_t inSpi,
143 int32_t* outSpi);
144
145 static netdutils::Status ipSecAddSecurityAssociation(
Nathan Haroldda54f122018-01-09 16:42:57 -0800146 int32_t transformId, int32_t mode, const std::string& sourceAddress,
Benedict Wong96abf482018-01-22 13:56:41 -0800147 const std::string& destinationAddress, int32_t underlyingNetId, int32_t spi,
Di Lu2ccb3e52018-01-03 16:19:20 -0800148 int32_t markValue, int32_t markMask, const std::string& authAlgo,
149 const std::vector<uint8_t>& authKey, int32_t authTruncBits, const std::string& cryptAlgo,
150 const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits, const std::string& aeadAlgo,
151 const std::vector<uint8_t>& aeadKey, int32_t aeadIcvBits, int32_t encapType,
152 int32_t encapLocalPort, int32_t encapRemotePort);
Nathan Harold1a371532017-01-30 12:30:48 -0800153
Nathan Harold21299f72018-03-16 20:13:03 -0700154 static netdutils::Status ipSecDeleteSecurityAssociation(int32_t transformId,
155 const std::string& sourceAddress,
156 const std::string& destinationAddress,
157 int32_t spi, int32_t markValue,
158 int32_t markMask);
Nathan Harold1a371532017-01-30 12:30:48 -0800159
Nathan Harold21299f72018-03-16 20:13:03 -0700160 static netdutils::Status
161 ipSecApplyTransportModeTransform(const android::base::unique_fd& socket, int32_t transformId,
162 int32_t direction, const std::string& localAddress,
163 const std::string& remoteAddress, int32_t spi);
Nathan Harold1a371532017-01-30 12:30:48 -0800164
Nathan Harold21299f72018-03-16 20:13:03 -0700165 static netdutils::Status
166 ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket);
Nathan Harold1a371532017-01-30 12:30:48 -0800167
Benedict Wonga04ffa72018-05-09 21:42:42 -0700168 static netdutils::Status ipSecAddSecurityPolicy(int32_t transformId, int32_t selAddrFamily,
169 int32_t direction,
Benedict Wongad600cb2018-05-14 17:22:35 -0700170 const std::string& tmplSrcAddress,
171 const std::string& tmplDstAddress, int32_t spi,
172 int32_t markValue, int32_t markMask);
ludi771b8002017-11-20 15:09:05 -0800173
Benedict Wonga04ffa72018-05-09 21:42:42 -0700174 static netdutils::Status ipSecUpdateSecurityPolicy(int32_t transformId, int32_t selAddrFamily,
175 int32_t direction,
Benedict Wongad600cb2018-05-14 17:22:35 -0700176 const std::string& tmplSrcAddress,
177 const std::string& tmplDstAddress,
Nathan Harold21299f72018-03-16 20:13:03 -0700178 int32_t spi, int32_t markValue,
179 int32_t markMask);
ludi771b8002017-11-20 15:09:05 -0800180
Benedict Wonga04ffa72018-05-09 21:42:42 -0700181 static netdutils::Status ipSecDeleteSecurityPolicy(int32_t transformId, int32_t selAddrFamily,
182 int32_t direction, int32_t markValue,
183 int32_t markMask);
ludi771b8002017-11-20 15:09:05 -0800184
Nathan Harold21299f72018-03-16 20:13:03 -0700185 static int addVirtualTunnelInterface(const std::string& deviceName,
186 const std::string& localAddress,
187 const std::string& remoteAddress, int32_t ikey,
188 int32_t okey, bool isUpdate);
manojboopathi8707f232018-01-02 14:45:47 -0800189
Nathan Harold21299f72018-03-16 20:13:03 -0700190 static int removeVirtualTunnelInterface(const std::string& deviceName);
manojboopathi8707f232018-01-02 14:45:47 -0800191
Jonathan Basseric6461a62017-08-31 14:47:33 -0700192 // Some XFRM netlink attributes comprise a header, a struct, and some data
193 // after the struct. We wrap all of those in one struct for easier
194 // marshalling. The structs below must be ABI compatible with the kernel and
195 // are composed from kernel structures; thus, they use the kernel naming
196 // convention.
197
Nathan Harold39b5df42017-08-02 18:45:25 -0700198 // Exposed for testing
Benedict Wong4f60ee12017-10-10 12:27:25 -0700199 static constexpr size_t MAX_KEY_LENGTH = 128;
Nathan Harold39b5df42017-08-02 18:45:25 -0700200
Jonathan Basseric6461a62017-08-31 14:47:33 -0700201 // Container for the content of an XFRMA_ALG_CRYPT netlink attribute.
Nathan Harold39b5df42017-08-02 18:45:25 -0700202 // Exposed for testing
203 struct nlattr_algo_crypt {
204 nlattr hdr;
205 xfrm_algo crypt;
Benedict Wong4f60ee12017-10-10 12:27:25 -0700206 uint8_t key[MAX_KEY_LENGTH];
Nathan Harold39b5df42017-08-02 18:45:25 -0700207 };
208
Jonathan Basseric6461a62017-08-31 14:47:33 -0700209 // Container for the content of an XFRMA_ALG_AUTH_TRUNC netlink attribute.
Nathan Harold39b5df42017-08-02 18:45:25 -0700210 // Exposed for testing
211 struct nlattr_algo_auth {
212 nlattr hdr;
213 xfrm_algo_auth auth;
Benedict Wong4f60ee12017-10-10 12:27:25 -0700214 uint8_t key[MAX_KEY_LENGTH];
Nathan Harold39b5df42017-08-02 18:45:25 -0700215 };
216
Jonathan Basseric6461a62017-08-31 14:47:33 -0700217 // Container for the content of an XFRMA_TMPL netlink attribute.
Nathan Harold39b5df42017-08-02 18:45:25 -0700218 // Exposed for testing
Benedict Wongbe65b432017-08-22 21:43:14 -0700219 struct nlattr_algo_aead {
220 nlattr hdr;
221 xfrm_algo_aead aead;
Benedict Wong4f60ee12017-10-10 12:27:25 -0700222 uint8_t key[MAX_KEY_LENGTH];
Benedict Wongbe65b432017-08-22 21:43:14 -0700223 };
224
225 // Exposed for testing
Nathan Harold39b5df42017-08-02 18:45:25 -0700226 struct nlattr_user_tmpl {
227 nlattr hdr;
228 xfrm_user_tmpl tmpl;
229 };
230
Jonathan Basseric6461a62017-08-31 14:47:33 -0700231 // Container for the content of an XFRMA_ENCAP netlink attribute.
Nathan Harold39b5df42017-08-02 18:45:25 -0700232 // Exposed for testing
233 struct nlattr_encap_tmpl {
234 nlattr hdr;
235 xfrm_encap_tmpl tmpl;
236 };
237
Di Lu2ccb3e52018-01-03 16:19:20 -0800238 // Container for the content of an XFRMA_MARK netlink attribute.
239 // Exposed for testing
240 struct nlattr_xfrm_mark {
241 nlattr hdr;
242 xfrm_mark mark;
243 };
244
Benedict Wong96abf482018-01-22 13:56:41 -0800245 // Container for the content of an XFRMA_OUTPUT_MARK netlink attribute.
246 // Exposed for testing
247 struct nlattr_xfrm_output_mark {
248 nlattr hdr;
249 __u32 outputMark;
250 };
251
Nathan Harold1a371532017-01-30 12:30:48 -0800252private:
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700253/*
Bernie Innocentiedf68352018-07-05 17:50:38 +0900254 * This is a workaround for a kernel bug in the 32bit netlink compat layer
255 * that has been present on x86_64 kernels since 2010 with no fix on the
256 * horizon.
257 *
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700258 * Below is a redefinition of the xfrm_usersa_info struct that is part
259 * of the Linux uapi <linux/xfrm.h> to align the structures to a 64-bit
260 * boundary.
Bernie Innocentiedf68352018-07-05 17:50:38 +0900261 *
262 * Note that we turn this on for all x86 32bit targets, under the assumption
263 * that nowadays all x86 targets are running 64bit kernels.
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700264 */
Bernie Innocentiedf68352018-07-05 17:50:38 +0900265#if defined(__i386__)
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700266 // Shadow the kernel definition of xfrm_usersa_info with a 64-bit aligned version
267 struct xfrm_usersa_info : ::xfrm_usersa_info {
268 } __attribute__((aligned(8)));
269 // Shadow the kernel's version, using the aligned version of xfrm_usersa_info
270 struct xfrm_userspi_info {
271 struct xfrm_usersa_info info;
272 __u32 min;
273 __u32 max;
274 };
Bjoern Johansson83977442018-05-25 16:55:28 -0700275 struct xfrm_userpolicy_info : ::xfrm_userpolicy_info {
276 } __attribute__((aligned(8)));
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700277
278 /*
279 * Anyone who encounters a failure when sending netlink messages should look here
280 * first. Hitting the static_assert() below should be a strong hint that Android
281 * IPsec will probably not work with your current settings.
282 *
283 * Again, experimentally determined, the "flags" field should be the first byte in
284 * the final word of the xfrm_usersa_info struct. The check validates the size of
285 * the padding to be 7.
286 *
287 * This padding is verified to be correct on gcc/x86_64 kernel, and clang/x86 userspace.
288 */
289 static_assert(sizeof(::xfrm_usersa_info) % 8 != 0, "struct xfrm_usersa_info has changed "
290 "alignment. Please consider whether this "
291 "patch is needed.");
292 static_assert(sizeof(xfrm_usersa_info) - offsetof(xfrm_usersa_info, flags) == 8,
293 "struct xfrm_usersa_info probably misaligned with kernel struct.");
294 static_assert(sizeof(xfrm_usersa_info) % 8 == 0, "struct xfrm_usersa_info_t is not 64-bit "
295 "aligned. Please consider whether this patch "
296 "is needed.");
297 static_assert(sizeof(::xfrm_userspi_info) - sizeof(::xfrm_usersa_info) ==
298 sizeof(xfrm_userspi_info) - sizeof(xfrm_usersa_info),
299 "struct xfrm_userspi_info has changed and does not match the kernel struct.");
Bjoern Johansson83977442018-05-25 16:55:28 -0700300 static_assert(sizeof(::xfrm_userpolicy_info) % 8 != 0,
301 "struct xfrm_userpolicy_info has changed "
302 "alignment. Please consider whether this "
303 "patch is needed.");
304 static_assert(sizeof(xfrm_userpolicy_info) - offsetof(xfrm_userpolicy_info, share) == 5,
305 "struct xfrm_userpolicy_info probably misaligned with kernel struct.");
306 static_assert(sizeof(xfrm_userpolicy_info) % 8 == 0,
307 "struct xfrm_userpolicy_info is not 64-bit "
308 "aligned. Please consider whether this patch "
309 "is needed.");
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700310#endif
311
Benedict Wonga04ffa72018-05-09 21:42:42 -0700312 // helper functions for filling in the XfrmCommonInfo (and XfrmSaInfo) structure
313 static netdutils::Status fillXfrmCommonInfo(const std::string& sourceAddress,
314 const std::string& destinationAddress, int32_t spi,
315 int32_t markValue, int32_t markMask,
316 int32_t transformId, XfrmCommonInfo* info);
317 static netdutils::Status fillXfrmCommonInfo(int32_t spi, int32_t markValue, int32_t markMask,
318 int32_t transformId, XfrmCommonInfo* info);
Nathan Harold1a371532017-01-30 12:30:48 -0800319
320 // Top level functions for managing a Transport Mode Transform
ludi6e8eccd2017-08-14 14:40:37 -0700321 static netdutils::Status addTransportModeTransform(const XfrmSaInfo& record);
Nathan Harold1a371532017-01-30 12:30:48 -0800322 static int removeTransportModeTransform(const XfrmSaInfo& record);
323
324 // TODO(messagerefactor): FACTOR OUT ALL MESSAGE BUILDING CODE BELOW HERE
325 // Shared between SA and SP
Benedict Wonga04ffa72018-05-09 21:42:42 -0700326 static void fillXfrmSelector(const int record, xfrm_selector* selector);
Nathan Harold1a371532017-01-30 12:30:48 -0800327
328 // Shared between Transport and Tunnel Mode
329 static int fillNlAttrXfrmAlgoEnc(const XfrmAlgo& in_algo, nlattr_algo_crypt* algo);
330 static int fillNlAttrXfrmAlgoAuth(const XfrmAlgo& in_algo, nlattr_algo_auth* algo);
Benedict Wongbe65b432017-08-22 21:43:14 -0700331 static int fillNlAttrXfrmAlgoAead(const XfrmAlgo& in_algo, nlattr_algo_aead* algo);
Nathan Harold420ceac2017-04-05 19:36:59 -0700332 static int fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl);
Nathan Harold1a371532017-01-30 12:30:48 -0800333
Di Lu0e16b5e2018-01-12 10:37:53 -0800334 // Functions for updating a Transport Mode SA
335 static netdutils::Status updateSecurityAssociation(const XfrmSaInfo& record,
manojboopathi4d2d6f12017-12-06 11:11:31 -0800336 const XfrmSocket& sock);
Nathan Harold1a371532017-01-30 12:30:48 -0800337 static int fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa);
338
339 // Functions for deleting a Transport Mode SA
Benedict Wonga04ffa72018-05-09 21:42:42 -0700340 static netdutils::Status deleteSecurityAssociation(const XfrmCommonInfo& record,
ludi6e8eccd2017-08-14 14:40:37 -0700341 const XfrmSocket& sock);
Benedict Wonga04ffa72018-05-09 21:42:42 -0700342 static int fillUserSaId(const XfrmCommonInfo& record, xfrm_usersa_id* said);
343 static int fillUserTemplate(const XfrmSpInfo& record, xfrm_user_tmpl* tmpl);
ludi771b8002017-11-20 15:09:05 -0800344
Benedict Wonga04ffa72018-05-09 21:42:42 -0700345 static int fillUserSpInfo(const XfrmSpInfo& record, XfrmDirection direction,
346 xfrm_userpolicy_info* usersp);
347 static int fillNlAttrUserTemplate(const XfrmSpInfo& record, nlattr_user_tmpl* tmpl);
348 static int fillUserPolicyId(const XfrmSpInfo& record, XfrmDirection direction,
ludi771b8002017-11-20 15:09:05 -0800349 xfrm_userpolicy_id* policy_id);
Benedict Wonga04ffa72018-05-09 21:42:42 -0700350 static int fillNlAttrXfrmMark(const XfrmCommonInfo& record, nlattr_xfrm_mark* mark);
Benedict Wongd8b6a382018-09-18 17:16:10 -0700351 static int fillNlAttrXfrmOutputMark(const __u32 underlyingNetId,
Benedict Wong96abf482018-01-22 13:56:41 -0800352 nlattr_xfrm_output_mark* output_mark);
Nathan Harold1a371532017-01-30 12:30:48 -0800353
ludi6e8eccd2017-08-14 14:40:37 -0700354 static netdutils::Status allocateSpi(const XfrmSaInfo& record, uint32_t minSpi, uint32_t maxSpi,
355 uint32_t* outSpi, const XfrmSocket& sock);
Nathan Harold1a371532017-01-30 12:30:48 -0800356
Benedict Wonga04ffa72018-05-09 21:42:42 -0700357 static netdutils::Status processSecurityPolicy(int32_t transformId, int32_t selAddrFamily,
358 int32_t direction,
Benedict Wongad600cb2018-05-14 17:22:35 -0700359 const std::string& tmplSrcAddress,
360 const std::string& tmplDstAddress, int32_t spi,
Nathan Harold21299f72018-03-16 20:13:03 -0700361 int32_t markValue, int32_t markMask,
362 int32_t msgType);
Benedict Wonga04ffa72018-05-09 21:42:42 -0700363 static netdutils::Status updateTunnelModeSecurityPolicy(const XfrmSpInfo& record,
ludi771b8002017-11-20 15:09:05 -0800364 const XfrmSocket& sock,
365 XfrmDirection direction,
366 uint16_t msgType);
Benedict Wonga04ffa72018-05-09 21:42:42 -0700367 static netdutils::Status deleteTunnelModeSecurityPolicy(const XfrmSpInfo& record,
ludi771b8002017-11-20 15:09:05 -0800368 const XfrmSocket& sock,
369 XfrmDirection direction);
Nathan Harold21299f72018-03-16 20:13:03 -0700370 static netdutils::Status flushInterfaces();
371 static netdutils::Status flushSaDb(const XfrmSocket& s);
372 static netdutils::Status flushPolicyDb(const XfrmSocket& s);
373
Nathan Harold1a371532017-01-30 12:30:48 -0800374 // END TODO(messagerefactor)
375};
376
377} // namespace net
378} // namespace android
379
380#endif /* !defined(XFRM_CONTROLLER_H) */