1/* 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> 26#include <linux/udp.h> 27#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() { 43 if (mSock >= 0) { 44 ::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 72enum struct XfrmEncapType : uint16_t { 73 NONE = 0, 74 ESPINUDP_NON_IKE = UDP_ENCAP_ESPINUDP_NON_IKE, 75 ESPINUDP = UDP_ENCAP_ESPINUDP 76}; 77 78struct XfrmAlgo { 79 std::string name; 80 std::vector<uint8_t> key; 81 uint16_t truncLenBits; 82}; 83 84struct XfrmEncap { 85 XfrmEncapType type; 86 uint16_t srcPort; 87 uint16_t dstPort; 88}; 89 90struct 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; 104 XfrmEncap encap; 105}; 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); 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 138/* 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 178 struct nlattr_algo_crypt { 179 nlattr hdr; 180 xfrm_algo crypt; 181 uint8_t key[MAX_ALGO_LENGTH]; 182 }; 183 184 struct nlattr_algo_auth { 185 nlattr hdr; 186 xfrm_algo_auth auth; 187 uint8_t key[MAX_ALGO_LENGTH]; 188 }; 189 190 struct nlattr_user_tmpl { 191 nlattr hdr; 192 xfrm_user_tmpl tmpl; 193 }; 194 195 struct nlattr_encap_tmpl { 196 nlattr hdr; 197 xfrm_encap_tmpl tmpl; 198 }; 199 200 201 // 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); 216 static int fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl); 217 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) */ 239