• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (C) 2017 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <string>
19 #include <vector>
20 
21 #include <ctype.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <inttypes.h>
29 
30 #include <arpa/inet.h>
31 #include <netinet/in.h>
32 
33 #include <sys/socket.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 
38 #include <linux/in.h>
39 #include <linux/netlink.h>
40 #include <linux/xfrm.h>
41 
42 #include "android-base/stringprintf.h"
43 #include "android-base/strings.h"
44 #include "android-base/unique_fd.h"
45 #define LOG_TAG "XfrmController"
46 #include "NetdConstants.h"
47 #include "NetlinkCommands.h"
48 #include "ResponseCode.h"
49 #include "XfrmController.h"
50 #include <cutils/log.h>
51 #include <cutils/properties.h>
52 #include <logwrap/logwrap.h>
53 
54 #define VDBG 1 // STOPSHIP if true
55 
56 namespace android {
57 namespace net {
58 
59 namespace {
60 
61 constexpr uint32_t ALGO_MASK_AUTH_ALL = ~0;
62 constexpr uint32_t ALGO_MASK_CRYPT_ALL = ~0;
63 
64 constexpr uint8_t REPLAY_WINDOW_SIZE = 4;
65 
66 constexpr uint32_t RAND_SPI_MIN = 1;
67 constexpr uint32_t RAND_SPI_MAX = 0xFFFFFFFE;
68 
69 constexpr uint32_t INVALID_SPI = 0;
70 
71 #define XFRM_MSG_TRANS(x)                                                                          \
72     case x:                                                                                        \
73         return #x;
74 
xfrmMsgTypeToString(uint16_t msg)75 const char* xfrmMsgTypeToString(uint16_t msg) {
76     switch (msg) {
77         XFRM_MSG_TRANS(XFRM_MSG_NEWSA)
78         XFRM_MSG_TRANS(XFRM_MSG_DELSA)
79         XFRM_MSG_TRANS(XFRM_MSG_GETSA)
80         XFRM_MSG_TRANS(XFRM_MSG_NEWPOLICY)
81         XFRM_MSG_TRANS(XFRM_MSG_DELPOLICY)
82         XFRM_MSG_TRANS(XFRM_MSG_GETPOLICY)
83         XFRM_MSG_TRANS(XFRM_MSG_ALLOCSPI)
84         XFRM_MSG_TRANS(XFRM_MSG_ACQUIRE)
85         XFRM_MSG_TRANS(XFRM_MSG_EXPIRE)
86         XFRM_MSG_TRANS(XFRM_MSG_UPDPOLICY)
87         XFRM_MSG_TRANS(XFRM_MSG_UPDSA)
88         XFRM_MSG_TRANS(XFRM_MSG_POLEXPIRE)
89         XFRM_MSG_TRANS(XFRM_MSG_FLUSHSA)
90         XFRM_MSG_TRANS(XFRM_MSG_FLUSHPOLICY)
91         XFRM_MSG_TRANS(XFRM_MSG_NEWAE)
92         XFRM_MSG_TRANS(XFRM_MSG_GETAE)
93         XFRM_MSG_TRANS(XFRM_MSG_REPORT)
94         XFRM_MSG_TRANS(XFRM_MSG_MIGRATE)
95         XFRM_MSG_TRANS(XFRM_MSG_NEWSADINFO)
96         XFRM_MSG_TRANS(XFRM_MSG_GETSADINFO)
97         XFRM_MSG_TRANS(XFRM_MSG_GETSPDINFO)
98         XFRM_MSG_TRANS(XFRM_MSG_NEWSPDINFO)
99         XFRM_MSG_TRANS(XFRM_MSG_MAPPING)
100         default:
101             return "XFRM_MSG UNKNOWN";
102     }
103 }
104 
105 // actually const but cannot be declared as such for reasons
106 uint8_t kPadBytesArray[] = {0, 0, 0};
107 void* kPadBytes = static_cast<void*>(kPadBytesArray);
108 
109 #if VDBG
110 #define LOG_HEX(__desc16__, __buf__, __len__) \
111     do{ logHex(__desc16__, __buf__, __len__); }while(0)
112 #define LOG_IOV(__iov__, __iov_len__) \
113     do{ logIov(__iov__, __iov_len__); }while(0)
114 
logHex(const char * desc16,const char * buf,size_t len)115 void logHex(const char* desc16, const char* buf, size_t len) {
116     char* printBuf = new char[len * 2 + 1 + 26]; // len->ascii, +newline, +prefix strlen
117     int offset = 0;
118     if (desc16) {
119         sprintf(printBuf, "{%-16s}", desc16);
120         offset += 18; // prefix string length
121     }
122     sprintf(printBuf + offset, "[%4.4u]: ", (len > 9999) ? 9999 : (unsigned)len);
123     offset += 8;
124 
125     for (uint32_t j = 0; j < (uint32_t)len; j++) {
126         sprintf(&printBuf[j * 2 + offset], "%0.2x", buf[j]);
127     }
128     ALOGD("%s", printBuf);
129     delete[] printBuf;
130 }
131 
logIov(const iovec * iov,size_t iovLen)132 void logIov(const iovec* iov, size_t iovLen) {
133     for (uint32_t i = 0; i < (uint32_t)iovLen; i++) {
134         const iovec* row = &iov[i];
135         logHex(0, reinterpret_cast<char*>(row->iov_base), row->iov_len);
136     }
137 }
138 
139 #else
140 #define LOG_HEX(__desc16__, __buf__, __len__)
141 #define LOG_IOV(__iov__, __iov_len__)
142 #endif
143 
144 class XfrmSocketImpl : public XfrmSocket {
145 private:
146     static constexpr int NLMSG_DEFAULTSIZE = 8192;
147 
148     union NetlinkResponse {
149         nlmsghdr hdr;
150         struct _err_ {
151             nlmsghdr hdr;
152             nlmsgerr err;
153         } err;
154 
155         struct _buf_ {
156             nlmsghdr hdr;
157             char buf[NLMSG_DEFAULTSIZE];
158         } buf;
159     };
160 
161 public:
open()162     virtual bool open() {
163         mSock = openNetlinkSocket(NETLINK_XFRM);
164         if (mSock <= 0) {
165             ALOGW("Could not get a new socket, line=%d", __LINE__);
166             return false;
167         }
168 
169         return true;
170     }
171 
validateResponse(NetlinkResponse response,size_t len)172     static int validateResponse(NetlinkResponse response, size_t len) {
173         if (len < sizeof(nlmsghdr)) {
174             ALOGW("Invalid response message received over netlink");
175             return -EBADMSG;
176         }
177 
178         switch (response.hdr.nlmsg_type) {
179             case NLMSG_NOOP:
180             case NLMSG_DONE:
181                 return 0;
182             case NLMSG_OVERRUN:
183                 ALOGD("Netlink request overran kernel buffer");
184                 return -EBADMSG;
185             case NLMSG_ERROR:
186                 if (len < sizeof(NetlinkResponse::_err_)) {
187                     ALOGD("Netlink message received malformed error response");
188                     return -EBADMSG;
189                 }
190                 return response.err.err.error; // Netlink errors are negative errno.
191             case XFRM_MSG_NEWSA:
192                 break;
193         }
194 
195         if (response.hdr.nlmsg_type < XFRM_MSG_BASE /*== NLMSG_MIN_TYPE*/ ||
196             response.hdr.nlmsg_type > XFRM_MSG_MAX) {
197             ALOGD("Netlink message responded with an out-of-range message ID");
198             return -EBADMSG;
199         }
200 
201         // TODO Add more message validation here
202         return 0;
203     }
204 
sendMessage(uint16_t nlMsgType,uint16_t nlMsgFlags,uint16_t nlMsgSeqNum,iovec * iov,int iovLen) const205     virtual int sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags, uint16_t nlMsgSeqNum,
206                             iovec* iov, int iovLen) const {
207         nlmsghdr nlMsg = {
208             .nlmsg_type = nlMsgType, .nlmsg_flags = nlMsgFlags, .nlmsg_seq = nlMsgSeqNum,
209         };
210 
211         iov[0].iov_base = &nlMsg;
212         iov[0].iov_len = NLMSG_HDRLEN;
213         for (int i = 0; i < iovLen; ++i) {
214             nlMsg.nlmsg_len += iov[i].iov_len;
215         }
216 
217         ALOGD("Sending Netlink XFRM Message: %s", xfrmMsgTypeToString(nlMsgType));
218         if (VDBG)
219             LOG_IOV(iov, iovLen);
220 
221         int ret;
222 
223         if (writev(mSock, iov, iovLen) < 0) {
224             ALOGE("netlink socket writev failed (%s)", strerror(errno));
225             return -errno;
226         }
227 
228         NetlinkResponse* response = new NetlinkResponse{};
229 
230         if ((ret = recv(mSock, response, sizeof(*response), 0)) < 0) {
231             ALOGE("netlink response contains error (%s)", strerror(errno));
232             delete response;
233             return -errno;
234         }
235 
236         LOG_HEX("netlink msg resp", reinterpret_cast<char*>(response), ret);
237 
238         ret = validateResponse(*response, ret);
239         delete response;
240         if (ret < 0)
241             ALOGE("netlink response contains error (%s)", strerror(-ret));
242         return ret;
243     }
244 };
245 
convertToXfrmAddr(const std::string & strAddr,xfrm_address_t * xfrmAddr)246 int convertToXfrmAddr(const std::string& strAddr, xfrm_address_t* xfrmAddr) {
247     if (strAddr.length() == 0) {
248         memset(xfrmAddr, 0, sizeof(*xfrmAddr));
249         return AF_UNSPEC;
250     }
251 
252     if (inet_pton(AF_INET6, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
253         return AF_INET6;
254     } else if (inet_pton(AF_INET, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
255         return AF_INET;
256     } else {
257         return -EAFNOSUPPORT;
258     }
259 }
260 
fillXfrmNlaHdr(nlattr * hdr,uint16_t type,uint16_t len)261 void fillXfrmNlaHdr(nlattr* hdr, uint16_t type, uint16_t len) {
262     hdr->nla_type = type;
263     hdr->nla_len = len;
264 }
265 
fillXfrmCurLifetimeDefaults(xfrm_lifetime_cur * cur)266 void fillXfrmCurLifetimeDefaults(xfrm_lifetime_cur* cur) {
267     memset(reinterpret_cast<char*>(cur), 0, sizeof(*cur));
268 }
fillXfrmLifetimeDefaults(xfrm_lifetime_cfg * cfg)269 void fillXfrmLifetimeDefaults(xfrm_lifetime_cfg* cfg) {
270     cfg->soft_byte_limit = XFRM_INF;
271     cfg->hard_byte_limit = XFRM_INF;
272     cfg->soft_packet_limit = XFRM_INF;
273     cfg->hard_packet_limit = XFRM_INF;
274 }
275 
276 /*
277  * Allocate SPIs within an (inclusive) range of min-max.
278  * returns 0 (INVALID_SPI) once the entire range has been parsed.
279  */
280 class RandomSpi {
281 public:
RandomSpi(int min,int max)282     RandomSpi(int min, int max) : mMin(min) {
283         time_t t;
284         srand((unsigned int)time(&t));
285         // TODO: more random random
286         mNext = rand();
287         mSize = max - min + 1;
288         mCount = mSize;
289     }
290 
next()291     uint32_t next() {
292         if (!mCount)
293             return 0;
294         mCount--;
295         return (mNext++ % mSize) + mMin;
296     }
297 
298 private:
299     uint32_t mNext;
300     uint32_t mSize;
301     uint32_t mMin;
302     uint32_t mCount;
303 };
304 
305 } // namespace
306 
307 //
308 // Begin XfrmController Impl
309 //
310 //
XfrmController(void)311 XfrmController::XfrmController(void) {}
312 
ipSecAllocateSpi(int32_t transformId,int32_t direction,const std::string & localAddress,const std::string & remoteAddress,int32_t inSpi,int32_t * outSpi)313 int XfrmController::ipSecAllocateSpi(int32_t transformId, int32_t direction,
314                                      const std::string& localAddress,
315                                      const std::string& remoteAddress, int32_t inSpi,
316                                      int32_t* outSpi) {
317 
318     ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
319     ALOGD("transformId=%d", transformId);
320     ALOGD("direction=%d", direction);
321     ALOGD("localAddress=%s", localAddress.c_str());
322     ALOGD("remoteAddress=%s", remoteAddress.c_str());
323     ALOGD("inSpi=%0.8x", inSpi);
324 
325     XfrmSaInfo saInfo{};
326     int ret;
327 
328     if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, INVALID_SPI, &saInfo)) < 0) {
329         return ret;
330     }
331 
332     XfrmSocketImpl sock;
333     if (!sock.open()) {
334         ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
335         return -1; // TODO: return right error; for whatever reason the sock
336                    // failed to open
337     }
338 
339     int minSpi = RAND_SPI_MIN, maxSpi = RAND_SPI_MAX;
340 
341     if (inSpi)
342         minSpi = maxSpi = inSpi;
343     ret = allocateSpi(saInfo, minSpi, maxSpi, reinterpret_cast<uint32_t*>(outSpi), sock);
344     if (ret < 0) {
345         ALOGD("Failed to Allocate an SPI, line=%d", __LINE__);
346         *outSpi = INVALID_SPI;
347     }
348 
349     return ret;
350 }
351 
ipSecAddSecurityAssociation(int32_t transformId,int32_t mode,int32_t direction,const std::string & localAddress,const std::string & remoteAddress,int64_t,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)352 int XfrmController::ipSecAddSecurityAssociation(
353     int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
354     const std::string& remoteAddress, int64_t /* underlyingNetworkHandle */, int32_t spi,
355     const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
356     const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
357     int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort, int32_t* allocatedSpi) {
358     android::RWLock::AutoWLock lock(mLock);
359 
360     ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
361     ALOGD("transformId=%d", transformId);
362     ALOGD("mode=%d", mode);
363     ALOGD("direction=%d", direction);
364     ALOGD("localAddress=%s", localAddress.c_str());
365     ALOGD("remoteAddress=%s", remoteAddress.c_str());
366     ALOGD("spi=%0.8x", spi);
367     ALOGD("authAlgo=%s", authAlgo.c_str());
368     ALOGD("authTruncBits=%d", authTruncBits);
369     ALOGD("cryptAlgo=%s", cryptAlgo.c_str());
370     ALOGD("cryptTruncBits=%d,", cryptTruncBits);
371     ALOGD("encapType=%d", encapType);
372     ALOGD("encapLocalPort=%d", encapLocalPort);
373     ALOGD("encapRemotePort=%d", encapRemotePort);
374 
375     XfrmSaInfo saInfo{};
376     int ret;
377 
378     if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saInfo)) < 0) {
379         return ret;
380     }
381 
382     saInfo.transformId = transformId;
383 
384     // STOPSHIP : range check the key lengths to prevent puncturing and overflow
385     saInfo.auth = XfrmAlgo{
386         .name = authAlgo, .key = authKey, .truncLenBits = static_cast<uint16_t>(authTruncBits)};
387 
388     saInfo.crypt = XfrmAlgo{
389         .name = cryptAlgo, .key = cryptKey, .truncLenBits = static_cast<uint16_t>(cryptTruncBits)};
390 
391     saInfo.direction = static_cast<XfrmDirection>(direction);
392 
393     switch (static_cast<XfrmMode>(mode)) {
394         case XfrmMode::TRANSPORT:
395         case XfrmMode::TUNNEL:
396             saInfo.mode = static_cast<XfrmMode>(mode);
397             break;
398         default:
399             return -EINVAL;
400     }
401 
402     XfrmSocketImpl sock;
403     if (!sock.open()) {
404         ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
405         return -1; // TODO: return right error; for whatever reason the sock
406                    // failed to open
407     }
408 
409     ret = createTransportModeSecurityAssociation(saInfo, sock);
410     if (ret < 0) {
411         ALOGD("Failed creating a Security Association, line=%d", __LINE__);
412         return ret; // something went wrong creating the SA
413     }
414 
415     *allocatedSpi = spi;
416     return 0;
417 }
418 
ipSecDeleteSecurityAssociation(int32_t transformId,int32_t direction,const std::string & localAddress,const std::string & remoteAddress,int32_t spi)419 int XfrmController::ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
420                                                    const std::string& localAddress,
421                                                    const std::string& remoteAddress, int32_t spi) {
422 
423     ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
424     ALOGD("transformId=%d", transformId);
425     ALOGD("direction=%d", direction);
426     ALOGD("localAddress=%s", localAddress.c_str());
427     ALOGD("remoteAddress=%s", remoteAddress.c_str());
428     ALOGD("spi=%0.8x", spi);
429 
430     XfrmSaId saId;
431     int ret;
432 
433     if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saId)) < 0) {
434         return ret;
435     }
436 
437     XfrmSocketImpl sock;
438     if (!sock.open()) {
439         ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
440         return -1; // TODO: return right error; for whatever reason the sock
441                    // failed to open
442     }
443 
444     ret = deleteSecurityAssociation(saId, sock);
445     if (ret < 0) {
446         ALOGD("Failed to delete Security Association, line=%d", __LINE__);
447         return ret; // something went wrong deleting the SA
448     }
449 
450     return ret;
451 }
452 
fillXfrmSaId(int32_t direction,const std::string & localAddress,const std::string & remoteAddress,int32_t spi,XfrmSaId * xfrmId)453 int XfrmController::fillXfrmSaId(int32_t direction, const std::string& localAddress,
454                                  const std::string& remoteAddress, int32_t spi, XfrmSaId* xfrmId) {
455     xfrm_address_t localXfrmAddr{}, remoteXfrmAddr{};
456 
457     int addrFamilyLocal, addrFamilyRemote;
458     addrFamilyRemote = convertToXfrmAddr(remoteAddress, &remoteXfrmAddr);
459     addrFamilyLocal = convertToXfrmAddr(localAddress, &localXfrmAddr);
460     if (addrFamilyRemote < 0 || addrFamilyLocal < 0) {
461         return -EINVAL;
462     }
463 
464     if (addrFamilyRemote == AF_UNSPEC ||
465         (addrFamilyLocal != AF_UNSPEC && addrFamilyLocal != addrFamilyRemote)) {
466         ALOGD("Invalid or Mismatched Address Families, %d != %d, line=%d", addrFamilyLocal,
467               addrFamilyRemote, __LINE__);
468         return -EINVAL;
469     }
470 
471     xfrmId->addrFamily = addrFamilyRemote;
472 
473     xfrmId->spi = htonl(spi);
474 
475     switch (static_cast<XfrmDirection>(direction)) {
476         case XfrmDirection::IN:
477             xfrmId->dstAddr = localXfrmAddr;
478             xfrmId->srcAddr = remoteXfrmAddr;
479             break;
480 
481         case XfrmDirection::OUT:
482             xfrmId->dstAddr = remoteXfrmAddr;
483             xfrmId->srcAddr = localXfrmAddr;
484             break;
485 
486         default:
487             ALOGD("Invalid XFRM direction, line=%d", __LINE__);
488             // Invalid direction for Transport mode transform: time to bail
489             return -EINVAL;
490     }
491     return 0;
492 }
493 
ipSecApplyTransportModeTransform(const android::base::unique_fd & socket,int32_t transformId,int32_t direction,const std::string & localAddress,const std::string & remoteAddress,int32_t spi)494 int XfrmController::ipSecApplyTransportModeTransform(const android::base::unique_fd& socket,
495                                                      int32_t transformId, int32_t direction,
496                                                      const std::string& localAddress,
497                                                      const std::string& remoteAddress,
498                                                      int32_t spi) {
499     ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
500     ALOGD("transformId=%d", transformId);
501     ALOGD("direction=%d", direction);
502     ALOGD("localAddress=%s", localAddress.c_str());
503     ALOGD("remoteAddress=%s", remoteAddress.c_str());
504     ALOGD("spi=%0.8x", spi);
505 
506     struct sockaddr_storage saddr;
507 
508     socklen_t len = sizeof(saddr);
509     int err;
510     int userSocket = socket.get();
511 
512     if ((err = getsockname(userSocket, reinterpret_cast<struct sockaddr*>(&saddr), &len)) < 0) {
513         ALOGE("Failed to get socket info in %s", __FUNCTION__);
514         return -err;
515     }
516 
517     XfrmSaInfo saInfo{};
518     saInfo.transformId = transformId;
519     saInfo.direction = static_cast<XfrmDirection>(direction);
520     saInfo.spi = spi;
521 
522     if ((err = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saInfo)) < 0) {
523         ALOGE("Couldn't build SA ID %s", __FUNCTION__);
524         return -err;
525     }
526 
527     if (saInfo.addrFamily != saddr.ss_family) {
528         ALOGE("Transform address family(%d) differs from socket address "
529                 "family(%d)!",
530                 saInfo.addrFamily, saddr.ss_family);
531         return -EINVAL;
532     }
533 
534     struct {
535         xfrm_userpolicy_info info;
536         xfrm_user_tmpl tmpl;
537     } policy{};
538 
539     fillTransportModeUserSpInfo(saInfo, &policy.info);
540     fillUserTemplate(saInfo, &policy.tmpl);
541 
542     LOG_HEX("XfrmUserPolicy", reinterpret_cast<char*>(&policy), sizeof(policy));
543 
544     int sockOpt, sockLayer;
545     switch (saInfo.addrFamily) {
546         case AF_INET:
547             sockOpt = IP_XFRM_POLICY;
548             sockLayer = SOL_IP;
549             break;
550         case AF_INET6:
551             sockOpt = IPV6_XFRM_POLICY;
552             sockLayer = SOL_IPV6;
553             break;
554         default:
555             return -EAFNOSUPPORT;
556     }
557 
558     err = setsockopt(userSocket, sockLayer, sockOpt, &policy, sizeof(policy));
559     if (err < 0) {
560         err = errno;
561         ALOGE("Error setting socket option for XFRM! (%s)", strerror(err));
562     }
563 
564     return -err;
565 }
566 
ipSecRemoveTransportModeTransform(const android::base::unique_fd & socket)567 int XfrmController::ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket) {
568     (void)socket;
569     return 0;
570 }
571 
fillTransportModeSelector(const XfrmSaInfo & record,xfrm_selector * selector)572 void XfrmController::fillTransportModeSelector(const XfrmSaInfo& record, xfrm_selector* selector) {
573     selector->family = record.addrFamily;
574     selector->proto = AF_UNSPEC;      // TODO: do we need to match the protocol? it's
575                                       // possible via the socket
576     selector->ifindex = record.netId; // TODO : still need to sort this out
577 }
578 
createTransportModeSecurityAssociation(const XfrmSaInfo & record,const XfrmSocket & sock)579 int XfrmController::createTransportModeSecurityAssociation(const XfrmSaInfo& record,
580                                                            const XfrmSocket& sock) {
581     xfrm_usersa_info usersa{};
582     nlattr_algo_crypt crypt{};
583     nlattr_algo_auth auth{};
584 
585     enum { NLMSG_HDR, USERSA, USERSA_PAD, CRYPT, CRYPT_PAD, AUTH, AUTH_PAD, iovLen };
586 
587     iovec iov[] = {
588         {NULL, 0},      // reserved for the eventual addition of a NLMSG_HDR
589         {&usersa, 0},   // main usersa_info struct
590         {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
591         {&crypt, 0},    // adjust size if crypt algo is present
592         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
593         {&auth, 0},     // adjust size if auth algo is present
594         {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
595     };
596 
597     int len;
598     len = iov[USERSA].iov_len = fillUserSaInfo(record, &usersa);
599     iov[USERSA_PAD].iov_len = NLMSG_ALIGN(len) - len;
600 
601     len = iov[CRYPT].iov_len = fillNlAttrXfrmAlgoEnc(record.crypt, &crypt);
602     iov[CRYPT_PAD].iov_len = NLA_ALIGN(len) - len;
603 
604     len = iov[AUTH].iov_len = fillNlAttrXfrmAlgoAuth(record.auth, &auth);
605     iov[AUTH_PAD].iov_len = NLA_ALIGN(len) - len;
606 
607     return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
608 }
609 
fillNlAttrXfrmAlgoEnc(const XfrmAlgo & inAlgo,nlattr_algo_crypt * algo)610 int XfrmController::fillNlAttrXfrmAlgoEnc(const XfrmAlgo& inAlgo, nlattr_algo_crypt* algo) {
611     int len = NLA_HDRLEN + sizeof(xfrm_algo);
612     strncpy(algo->crypt.alg_name, inAlgo.name.c_str(), sizeof(algo->crypt.alg_name));
613     algo->crypt.alg_key_len = inAlgo.key.size() * 8;      // bits
614     memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size()); // FIXME :safety checks
615     len += inAlgo.key.size();
616     fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_CRYPT, len);
617     return len;
618 }
619 
fillNlAttrXfrmAlgoAuth(const XfrmAlgo & inAlgo,nlattr_algo_auth * algo)620 int XfrmController::fillNlAttrXfrmAlgoAuth(const XfrmAlgo& inAlgo, nlattr_algo_auth* algo) {
621     int len = NLA_HDRLEN + sizeof(xfrm_algo_auth);
622     strncpy(algo->auth.alg_name, inAlgo.name.c_str(), sizeof(algo->auth.alg_name));
623     algo->auth.alg_key_len = inAlgo.key.size() * 8; // bits
624 
625     // This is the extra field for ALG_AUTH_TRUNC
626     algo->auth.alg_trunc_len = inAlgo.truncLenBits;
627 
628     memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size()); // FIXME :safety checks
629     len += inAlgo.key.size();
630 
631     fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_AUTH_TRUNC, len);
632     return len;
633 }
634 
fillUserSaInfo(const XfrmSaInfo & record,xfrm_usersa_info * usersa)635 int XfrmController::fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa) {
636     fillTransportModeSelector(record, &usersa->sel);
637 
638     usersa->id.proto = IPPROTO_ESP;
639     usersa->id.spi = record.spi;
640     usersa->id.daddr = record.dstAddr;
641 
642     usersa->saddr = record.srcAddr;
643 
644     fillXfrmLifetimeDefaults(&usersa->lft);
645     fillXfrmCurLifetimeDefaults(&usersa->curlft);
646     memset(&usersa->stats, 0, sizeof(usersa->stats)); // leave stats zeroed out
647     usersa->reqid = record.transformId;
648     usersa->family = record.addrFamily;
649     usersa->mode = static_cast<uint8_t>(record.mode);
650     usersa->replay_window = REPLAY_WINDOW_SIZE;
651     usersa->flags = 0; // TODO: should we actually set flags, XFRM_SA_XFLAG_DONT_ENCAP_DSCP?
652     return sizeof(*usersa);
653 }
654 
fillUserSaId(const XfrmSaId & record,xfrm_usersa_id * said)655 int XfrmController::fillUserSaId(const XfrmSaId& record, xfrm_usersa_id* said) {
656     said->daddr = record.dstAddr;
657     said->spi = record.spi;
658     said->family = record.addrFamily;
659     said->proto = IPPROTO_ESP;
660 
661     return sizeof(*said);
662 }
663 
deleteSecurityAssociation(const XfrmSaId & record,const XfrmSocket & sock)664 int XfrmController::deleteSecurityAssociation(const XfrmSaId& record, const XfrmSocket& sock) {
665     xfrm_usersa_id said{};
666 
667     enum { NLMSG_HDR, USERSAID, USERSAID_PAD, iovLen };
668 
669     iovec iov[] = {
670         {NULL, 0},      // reserved for the eventual addition of a NLMSG_HDR
671         {&said, 0},     // main usersa_info struct
672         {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
673     };
674 
675     int len;
676     len = iov[USERSAID].iov_len = fillUserSaId(record, &said);
677     iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
678 
679     return sock.sendMessage(XFRM_MSG_DELSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
680 }
681 
allocateSpi(const XfrmSaInfo & record,uint32_t minSpi,uint32_t maxSpi,uint32_t * outSpi,const XfrmSocket & sock)682 int XfrmController::allocateSpi(const XfrmSaInfo& record, uint32_t minSpi, uint32_t maxSpi,
683                                 uint32_t* outSpi, const XfrmSocket& sock) {
684     xfrm_userspi_info spiInfo{};
685 
686     enum { NLMSG_HDR, USERSAID, USERSAID_PAD, iovLen };
687 
688     iovec iov[] = {
689         {NULL, 0},      // reserved for the eventual addition of a NLMSG_HDR
690         {&spiInfo, 0},  // main userspi_info struct
691         {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
692     };
693 
694     int len;
695     if (fillUserSaInfo(record, &spiInfo.info) == 0) {
696         ALOGE("Failed to fill transport SA Info");
697     }
698 
699     len = iov[USERSAID].iov_len = sizeof(spiInfo);
700     iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
701 
702     RandomSpi spiGen = RandomSpi(minSpi, maxSpi);
703     int spi, ret;
704     while ((spi = spiGen.next()) != INVALID_SPI) {
705         spiInfo.min = spi;
706         spiInfo.max = spi;
707         ret = sock.sendMessage(XFRM_MSG_ALLOCSPI, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
708 
709         /* If the SPI is in use, we'll get ENOENT */
710         if (ret == -ENOENT)
711             continue;
712 
713         if (ret == 0) {
714             *outSpi = spi;
715             ALOGD("Allocated an SPI: %d", *outSpi);
716         } else {
717             *outSpi = INVALID_SPI;
718             ALOGE("SPI Allocation Failed with error %d", ret);
719         }
720 
721         return ret;
722     }
723 
724     // Should always be -ENOENT if we get here
725     return ret;
726 }
727 
fillTransportModeUserSpInfo(const XfrmSaInfo & record,xfrm_userpolicy_info * usersp)728 int XfrmController::fillTransportModeUserSpInfo(const XfrmSaInfo& record,
729                                                 xfrm_userpolicy_info* usersp) {
730     fillTransportModeSelector(record, &usersp->sel);
731     fillXfrmLifetimeDefaults(&usersp->lft);
732     fillXfrmCurLifetimeDefaults(&usersp->curlft);
733     /* if (index) index & 0x3 == dir -- must be true xfrm_user.c:verify_newpolicy_info() */
734     usersp->index = 0;
735     usersp->dir = static_cast<uint8_t>(record.direction);
736     usersp->action = XFRM_POLICY_ALLOW;
737     usersp->flags = XFRM_POLICY_LOCALOK;
738     usersp->share = XFRM_SHARE_UNIQUE;
739     return sizeof(*usersp);
740 }
741 
fillUserTemplate(const XfrmSaInfo & record,xfrm_user_tmpl * tmpl)742 int XfrmController::fillUserTemplate(const XfrmSaInfo& record, xfrm_user_tmpl* tmpl) {
743     tmpl->id.daddr = record.dstAddr;
744     tmpl->id.spi = record.spi;
745     tmpl->id.proto = IPPROTO_ESP;
746 
747     tmpl->family = record.addrFamily;
748     tmpl->saddr = record.srcAddr;
749     tmpl->reqid = record.transformId;
750     tmpl->mode = static_cast<uint8_t>(record.mode);
751     tmpl->share = XFRM_SHARE_UNIQUE;
752     tmpl->optional = 0; // if this is true, then a failed state lookup will be considered OK:
753                         // http://lxr.free-electrons.com/source/net/xfrm/xfrm_policy.c#L1492
754     tmpl->aalgos = ALGO_MASK_AUTH_ALL;  // TODO: if there's a bitmask somewhere of
755                                         // algos, we should find it and apply it.
756                                         // I can't find one.
757     tmpl->ealgos = ALGO_MASK_CRYPT_ALL; // TODO: if there's a bitmask somewhere...
758     return 0;
759 }
760 
761 } // namespace net
762 } // namespace android
763