blob: 1c9b406c6285b371e48707921185899c81f7cd4b [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
25#include <linux/netlink.h>
Nathan Harold420ceac2017-04-05 19:36:59 -070026#include <linux/udp.h>
Nathan Harold1a371532017-01-30 12:30:48 -080027#include <linux/xfrm.h>
28#include <sysutils/SocketClient.h>
29#include <utils/RWLock.h>
30
31#include "NetdConstants.h"
32
33namespace android {
34namespace net {
35
36// Suggest we avoid the smallest and largest ints
37class XfrmMessage;
38class TransportModeSecurityAssociation;
39
40class XfrmSocket {
41public:
42 virtual void close() {
Nathan Harold420ceac2017-04-05 19:36:59 -070043 if (mSock >= 0) {
Nathan Harold1a371532017-01-30 12:30:48 -080044 ::close(mSock);
45 }
46 mSock = -1;
47 }
48
49 virtual bool open() = 0;
50
51 virtual ~XfrmSocket() { close(); }
52
53 virtual int sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags, uint16_t nlMsgSeqNum,
54 iovec* iov, int iovLen) const = 0;
55
56protected:
57 int mSock;
58};
59
60enum struct XfrmDirection : uint8_t {
61 IN = XFRM_POLICY_IN,
62 OUT = XFRM_POLICY_OUT,
63 FORWARD = XFRM_POLICY_FWD,
64 MASK = XFRM_POLICY_MASK,
65};
66
67enum struct XfrmMode : uint8_t {
68 TRANSPORT = XFRM_MODE_TRANSPORT,
69 TUNNEL = XFRM_MODE_TUNNEL,
70};
71
Nathan Harold420ceac2017-04-05 19:36:59 -070072enum struct XfrmEncapType : uint16_t {
73 NONE = 0,
74 ESPINUDP_NON_IKE = UDP_ENCAP_ESPINUDP_NON_IKE,
75 ESPINUDP = UDP_ENCAP_ESPINUDP
76};
77
Nathan Harold1a371532017-01-30 12:30:48 -080078struct XfrmAlgo {
79 std::string name;
80 std::vector<uint8_t> key;
81 uint16_t truncLenBits;
82};
83
Nathan Harold420ceac2017-04-05 19:36:59 -070084struct XfrmEncap {
85 XfrmEncapType type;
86 uint16_t srcPort;
87 uint16_t dstPort;
88};
89
Nathan Harold1a371532017-01-30 12:30:48 -080090struct XfrmSaId {
91 XfrmDirection direction;
92 xfrm_address_t dstAddr; // network order
93 xfrm_address_t srcAddr;
94 int addrFamily; // AF_INET or AF_INET6
95 int transformId; // requestId
96 int spi;
97};
98
99struct XfrmSaInfo : XfrmSaId {
100 XfrmAlgo auth;
101 XfrmAlgo crypt;
102 int netId;
103 XfrmMode mode;
Nathan Harold420ceac2017-04-05 19:36:59 -0700104 XfrmEncap encap;
Nathan Harold1a371532017-01-30 12:30:48 -0800105};
106
107class XfrmController {
108public:
109 XfrmController();
110
111 int ipSecAllocateSpi(int32_t transformId, int32_t direction, const std::string& localAddress,
112 const std::string& remoteAddress, int32_t inSpi, int32_t* outSpi);
113
114 int ipSecAddSecurityAssociation(
115 int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
116 const std::string& remoteAddress, int64_t underlyingNetworkHandle, int32_t spi,
117 const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
118 const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
119 int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort, int32_t* allocatedSpi);
120
121 int ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
122 const std::string& localAddress,
123 const std::string& remoteAddress, int32_t spi);
124
125 int ipSecApplyTransportModeTransform(const android::base::unique_fd& socket,
126 int32_t transformId, int32_t direction,
127 const std::string& localAddress,
128 const std::string& remoteAddress, int32_t spi);
129
130 int ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket);
131
132private:
133 // prevent concurrent modification of XFRM
134 android::RWLock mLock;
135
136 static constexpr size_t MAX_ALGO_LENGTH = 128;
137
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700138/*
139 * Below is a redefinition of the xfrm_usersa_info struct that is part
140 * of the Linux uapi <linux/xfrm.h> to align the structures to a 64-bit
141 * boundary.
142 */
143#ifdef NETLINK_COMPAT32
144 // Shadow the kernel definition of xfrm_usersa_info with a 64-bit aligned version
145 struct xfrm_usersa_info : ::xfrm_usersa_info {
146 } __attribute__((aligned(8)));
147 // Shadow the kernel's version, using the aligned version of xfrm_usersa_info
148 struct xfrm_userspi_info {
149 struct xfrm_usersa_info info;
150 __u32 min;
151 __u32 max;
152 };
153
154 /*
155 * Anyone who encounters a failure when sending netlink messages should look here
156 * first. Hitting the static_assert() below should be a strong hint that Android
157 * IPsec will probably not work with your current settings.
158 *
159 * Again, experimentally determined, the "flags" field should be the first byte in
160 * the final word of the xfrm_usersa_info struct. The check validates the size of
161 * the padding to be 7.
162 *
163 * This padding is verified to be correct on gcc/x86_64 kernel, and clang/x86 userspace.
164 */
165 static_assert(sizeof(::xfrm_usersa_info) % 8 != 0, "struct xfrm_usersa_info has changed "
166 "alignment. Please consider whether this "
167 "patch is needed.");
168 static_assert(sizeof(xfrm_usersa_info) - offsetof(xfrm_usersa_info, flags) == 8,
169 "struct xfrm_usersa_info probably misaligned with kernel struct.");
170 static_assert(sizeof(xfrm_usersa_info) % 8 == 0, "struct xfrm_usersa_info_t is not 64-bit "
171 "aligned. Please consider whether this patch "
172 "is needed.");
173 static_assert(sizeof(::xfrm_userspi_info) - sizeof(::xfrm_usersa_info) ==
174 sizeof(xfrm_userspi_info) - sizeof(xfrm_usersa_info),
175 "struct xfrm_userspi_info has changed and does not match the kernel struct.");
176#endif
177
Nathan Harold1a371532017-01-30 12:30:48 -0800178 struct nlattr_algo_crypt {
179 nlattr hdr;
180 xfrm_algo crypt;
Nathan Harold420ceac2017-04-05 19:36:59 -0700181 uint8_t key[MAX_ALGO_LENGTH];
Nathan Harold1a371532017-01-30 12:30:48 -0800182 };
183
184 struct nlattr_algo_auth {
185 nlattr hdr;
186 xfrm_algo_auth auth;
Nathan Harold420ceac2017-04-05 19:36:59 -0700187 uint8_t key[MAX_ALGO_LENGTH];
Nathan Harold1a371532017-01-30 12:30:48 -0800188 };
189
190 struct nlattr_user_tmpl {
191 nlattr hdr;
192 xfrm_user_tmpl tmpl;
193 };
194
Nathan Harold420ceac2017-04-05 19:36:59 -0700195 struct nlattr_encap_tmpl {
196 nlattr hdr;
197 xfrm_encap_tmpl tmpl;
198 };
199
200
Nathan Harold1a371532017-01-30 12:30:48 -0800201 // helper function for filling in the XfrmSaInfo structure
202 static int fillXfrmSaId(int32_t direction, const std::string& localAddress,
203 const std::string& remoteAddress, int32_t spi, XfrmSaId* xfrmId);
204
205 // Top level functions for managing a Transport Mode Transform
206 static int addTransportModeTransform(const XfrmSaInfo& record);
207 static int removeTransportModeTransform(const XfrmSaInfo& record);
208
209 // TODO(messagerefactor): FACTOR OUT ALL MESSAGE BUILDING CODE BELOW HERE
210 // Shared between SA and SP
211 static void fillTransportModeSelector(const XfrmSaInfo& record, xfrm_selector* selector);
212
213 // Shared between Transport and Tunnel Mode
214 static int fillNlAttrXfrmAlgoEnc(const XfrmAlgo& in_algo, nlattr_algo_crypt* algo);
215 static int fillNlAttrXfrmAlgoAuth(const XfrmAlgo& in_algo, nlattr_algo_auth* algo);
Nathan Harold420ceac2017-04-05 19:36:59 -0700216 static int fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl);
Nathan Harold1a371532017-01-30 12:30:48 -0800217
218 // Functions for Creating a Transport Mode SA
219 static int createTransportModeSecurityAssociation(const XfrmSaInfo& record,
220 const XfrmSocket& sock);
221 static int fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa);
222
223 // Functions for deleting a Transport Mode SA
224 static int deleteSecurityAssociation(const XfrmSaId& record, const XfrmSocket& sock);
225 static int fillUserSaId(const XfrmSaId& record, xfrm_usersa_id* said);
226 static int fillUserTemplate(const XfrmSaInfo& record, xfrm_user_tmpl* tmpl);
227 static int fillTransportModeUserSpInfo(const XfrmSaInfo& record, xfrm_userpolicy_info* usersp);
228
229 static int allocateSpi(const XfrmSaInfo& record, uint32_t minSpi, uint32_t maxSpi,
230 uint32_t* outSpi, const XfrmSocket& sock);
231
232 // END TODO(messagerefactor)
233};
234
235} // namespace net
236} // namespace android
237
238#endif /* !defined(XFRM_CONTROLLER_H) */