blob: 8437e4b3ea20c1fcbce30428bdfc2ab1c494b386 [file] [log] [blame]
Nathan Harold1a371532017-01-30 12:30:48 -08001/*
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>
Nathan Harold420ceac2017-04-05 19:36:59 -070028
29#define __STDC_FORMAT_MACROS
Nathan Harold1a371532017-01-30 12:30:48 -080030#include <inttypes.h>
31
32#include <arpa/inet.h>
33#include <netinet/in.h>
34
35#include <sys/socket.h>
36#include <sys/stat.h>
37#include <sys/types.h>
38#include <sys/wait.h>
39
40#include <linux/in.h>
41#include <linux/netlink.h>
42#include <linux/xfrm.h>
43
44#include "android-base/stringprintf.h"
45#include "android-base/strings.h"
46#include "android-base/unique_fd.h"
47#define LOG_TAG "XfrmController"
48#include "NetdConstants.h"
49#include "NetlinkCommands.h"
50#include "ResponseCode.h"
51#include "XfrmController.h"
ludi4072ff22017-06-15 08:56:52 -070052#include "netdutils/Fd.h"
53#include "netdutils/Slice.h"
54#include "netdutils/Syscalls.h"
Nathan Harold1a371532017-01-30 12:30:48 -080055#include <cutils/log.h>
56#include <cutils/properties.h>
57#include <logwrap/logwrap.h>
58
59#define VDBG 1 // STOPSHIP if true
60
ludi4072ff22017-06-15 08:56:52 -070061using android::netdutils::Fd;
62using android::netdutils::Slice;
63using android::netdutils::Status;
64using android::netdutils::StatusOr;
65using android::netdutils::Syscalls;
66
Nathan Harold1a371532017-01-30 12:30:48 -080067namespace android {
68namespace net {
69
70namespace {
71
72constexpr uint32_t ALGO_MASK_AUTH_ALL = ~0;
73constexpr uint32_t ALGO_MASK_CRYPT_ALL = ~0;
74
75constexpr uint8_t REPLAY_WINDOW_SIZE = 4;
76
77constexpr uint32_t RAND_SPI_MIN = 1;
78constexpr uint32_t RAND_SPI_MAX = 0xFFFFFFFE;
79
80constexpr uint32_t INVALID_SPI = 0;
81
82#define XFRM_MSG_TRANS(x) \
83 case x: \
84 return #x;
85
86const char* xfrmMsgTypeToString(uint16_t msg) {
87 switch (msg) {
88 XFRM_MSG_TRANS(XFRM_MSG_NEWSA)
89 XFRM_MSG_TRANS(XFRM_MSG_DELSA)
90 XFRM_MSG_TRANS(XFRM_MSG_GETSA)
91 XFRM_MSG_TRANS(XFRM_MSG_NEWPOLICY)
92 XFRM_MSG_TRANS(XFRM_MSG_DELPOLICY)
93 XFRM_MSG_TRANS(XFRM_MSG_GETPOLICY)
94 XFRM_MSG_TRANS(XFRM_MSG_ALLOCSPI)
95 XFRM_MSG_TRANS(XFRM_MSG_ACQUIRE)
96 XFRM_MSG_TRANS(XFRM_MSG_EXPIRE)
97 XFRM_MSG_TRANS(XFRM_MSG_UPDPOLICY)
98 XFRM_MSG_TRANS(XFRM_MSG_UPDSA)
99 XFRM_MSG_TRANS(XFRM_MSG_POLEXPIRE)
100 XFRM_MSG_TRANS(XFRM_MSG_FLUSHSA)
101 XFRM_MSG_TRANS(XFRM_MSG_FLUSHPOLICY)
102 XFRM_MSG_TRANS(XFRM_MSG_NEWAE)
103 XFRM_MSG_TRANS(XFRM_MSG_GETAE)
104 XFRM_MSG_TRANS(XFRM_MSG_REPORT)
105 XFRM_MSG_TRANS(XFRM_MSG_MIGRATE)
106 XFRM_MSG_TRANS(XFRM_MSG_NEWSADINFO)
107 XFRM_MSG_TRANS(XFRM_MSG_GETSADINFO)
108 XFRM_MSG_TRANS(XFRM_MSG_GETSPDINFO)
109 XFRM_MSG_TRANS(XFRM_MSG_NEWSPDINFO)
110 XFRM_MSG_TRANS(XFRM_MSG_MAPPING)
111 default:
112 return "XFRM_MSG UNKNOWN";
113 }
114}
115
116// actually const but cannot be declared as such for reasons
117uint8_t kPadBytesArray[] = {0, 0, 0};
118void* kPadBytes = static_cast<void*>(kPadBytesArray);
119
120#if VDBG
Nathan Harold420ceac2017-04-05 19:36:59 -0700121#define LOG_HEX(__desc16__, __buf__, __len__) \
122 do { \
123 logHex(__desc16__, __buf__, __len__); \
124 } while (0)
125#define LOG_IOV(__iov__, __iov_len__) \
126 do { \
127 logIov(__iov__, __iov_len__); \
128 } while (0)
Nathan Harold1a371532017-01-30 12:30:48 -0800129
130void logHex(const char* desc16, const char* buf, size_t len) {
131 char* printBuf = new char[len * 2 + 1 + 26]; // len->ascii, +newline, +prefix strlen
132 int offset = 0;
133 if (desc16) {
134 sprintf(printBuf, "{%-16s}", desc16);
135 offset += 18; // prefix string length
136 }
137 sprintf(printBuf + offset, "[%4.4u]: ", (len > 9999) ? 9999 : (unsigned)len);
138 offset += 8;
139
140 for (uint32_t j = 0; j < (uint32_t)len; j++) {
141 sprintf(&printBuf[j * 2 + offset], "%0.2x", buf[j]);
142 }
143 ALOGD("%s", printBuf);
144 delete[] printBuf;
145}
146
147void logIov(const iovec* iov, size_t iovLen) {
148 for (uint32_t i = 0; i < (uint32_t)iovLen; i++) {
149 const iovec* row = &iov[i];
150 logHex(0, reinterpret_cast<char*>(row->iov_base), row->iov_len);
151 }
152}
153
ludi4072ff22017-06-15 08:56:52 -0700154inline Syscalls& getSyscallInstance() { return netdutils::sSyscalls.get(); }
155
Nathan Harold1a371532017-01-30 12:30:48 -0800156#else
157#define LOG_HEX(__desc16__, __buf__, __len__)
158#define LOG_IOV(__iov__, __iov_len__)
159#endif
160
161class XfrmSocketImpl : public XfrmSocket {
162private:
163 static constexpr int NLMSG_DEFAULTSIZE = 8192;
164
165 union NetlinkResponse {
166 nlmsghdr hdr;
167 struct _err_ {
168 nlmsghdr hdr;
169 nlmsgerr err;
170 } err;
171
172 struct _buf_ {
173 nlmsghdr hdr;
174 char buf[NLMSG_DEFAULTSIZE];
175 } buf;
176 };
177
178public:
179 virtual bool open() {
180 mSock = openNetlinkSocket(NETLINK_XFRM);
181 if (mSock <= 0) {
182 ALOGW("Could not get a new socket, line=%d", __LINE__);
183 return false;
184 }
185
186 return true;
187 }
188
189 static int validateResponse(NetlinkResponse response, size_t len) {
190 if (len < sizeof(nlmsghdr)) {
191 ALOGW("Invalid response message received over netlink");
192 return -EBADMSG;
193 }
194
195 switch (response.hdr.nlmsg_type) {
196 case NLMSG_NOOP:
197 case NLMSG_DONE:
198 return 0;
199 case NLMSG_OVERRUN:
200 ALOGD("Netlink request overran kernel buffer");
201 return -EBADMSG;
202 case NLMSG_ERROR:
203 if (len < sizeof(NetlinkResponse::_err_)) {
204 ALOGD("Netlink message received malformed error response");
205 return -EBADMSG;
206 }
207 return response.err.err.error; // Netlink errors are negative errno.
208 case XFRM_MSG_NEWSA:
209 break;
210 }
211
212 if (response.hdr.nlmsg_type < XFRM_MSG_BASE /*== NLMSG_MIN_TYPE*/ ||
213 response.hdr.nlmsg_type > XFRM_MSG_MAX) {
214 ALOGD("Netlink message responded with an out-of-range message ID");
215 return -EBADMSG;
216 }
217
218 // TODO Add more message validation here
219 return 0;
220 }
221
222 virtual int sendMessage(uint16_t nlMsgType, uint16_t nlMsgFlags, uint16_t nlMsgSeqNum,
223 iovec* iov, int iovLen) const {
224 nlmsghdr nlMsg = {
225 .nlmsg_type = nlMsgType, .nlmsg_flags = nlMsgFlags, .nlmsg_seq = nlMsgSeqNum,
226 };
227
228 iov[0].iov_base = &nlMsg;
Nathan Harolde2dd4c72017-04-19 11:09:11 -0700229 iov[0].iov_len = NLMSG_HDRLEN;
Nathan Harold1a371532017-01-30 12:30:48 -0800230 for (int i = 0; i < iovLen; ++i) {
231 nlMsg.nlmsg_len += iov[i].iov_len;
232 }
233
ludi4072ff22017-06-15 08:56:52 -0700234 // TODO: Should use std::vector<iovec> from the beginning, should
235 // replace the iovec array declaration with an iovec vector declaration
236 // in other places of the program.
237 // This line should be removed when the parameter of sendMessage is
238 // changed to use iovev vector.
239 const std::vector<iovec> iovs(iov, iov + iovLen);
240
Nathan Harold1a371532017-01-30 12:30:48 -0800241 ALOGD("Sending Netlink XFRM Message: %s", xfrmMsgTypeToString(nlMsgType));
242 if (VDBG)
243 LOG_IOV(iov, iovLen);
244
ludi4072ff22017-06-15 08:56:52 -0700245 StatusOr<size_t> writeResult = getSyscallInstance().writev(mSock, iovs);
246 if (!isOk(writeResult)) {
247 ALOGE("netlink socket writev failed (%s)", toString(writeResult).c_str());
248 return -writeResult.status().code();
Nathan Harold1a371532017-01-30 12:30:48 -0800249 }
250
ludi4072ff22017-06-15 08:56:52 -0700251 if (nlMsg.nlmsg_len != writeResult.value()) {
252 ALOGE("Invalid netlink message length sent %d", static_cast<int>(writeResult.value()));
253 return -EBADMSG;
Nathan Harold1a371532017-01-30 12:30:48 -0800254 }
255
ludi4072ff22017-06-15 08:56:52 -0700256 NetlinkResponse response = {};
Nathan Harold1a371532017-01-30 12:30:48 -0800257
ludi4072ff22017-06-15 08:56:52 -0700258 StatusOr<Slice> readResult =
259 getSyscallInstance().read(Fd(mSock), netdutils::makeSlice(response));
260 if (!isOk(readResult)) {
261 ALOGE("netlink response error (%s)", toString(readResult).c_str());
262 return -readResult.status().code();
263 }
264
265 LOG_HEX("netlink msg resp", reinterpret_cast<char*>(readResult.value().base()),
266 readResult.value().size());
267
268 int retNum = validateResponse(response, readResult.value().size());
269 if (retNum < 0)
270 ALOGE("netlink response contains error (%s)", strerror(-retNum));
271 return retNum;
Nathan Harold1a371532017-01-30 12:30:48 -0800272 }
273};
274
275int convertToXfrmAddr(const std::string& strAddr, xfrm_address_t* xfrmAddr) {
276 if (strAddr.length() == 0) {
277 memset(xfrmAddr, 0, sizeof(*xfrmAddr));
278 return AF_UNSPEC;
279 }
280
281 if (inet_pton(AF_INET6, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
282 return AF_INET6;
283 } else if (inet_pton(AF_INET, strAddr.c_str(), reinterpret_cast<void*>(xfrmAddr))) {
284 return AF_INET;
285 } else {
286 return -EAFNOSUPPORT;
287 }
288}
289
290void fillXfrmNlaHdr(nlattr* hdr, uint16_t type, uint16_t len) {
291 hdr->nla_type = type;
292 hdr->nla_len = len;
293}
294
295void fillXfrmCurLifetimeDefaults(xfrm_lifetime_cur* cur) {
296 memset(reinterpret_cast<char*>(cur), 0, sizeof(*cur));
297}
298void fillXfrmLifetimeDefaults(xfrm_lifetime_cfg* cfg) {
299 cfg->soft_byte_limit = XFRM_INF;
300 cfg->hard_byte_limit = XFRM_INF;
301 cfg->soft_packet_limit = XFRM_INF;
302 cfg->hard_packet_limit = XFRM_INF;
303}
304
305/*
306 * Allocate SPIs within an (inclusive) range of min-max.
307 * returns 0 (INVALID_SPI) once the entire range has been parsed.
308 */
309class RandomSpi {
310public:
311 RandomSpi(int min, int max) : mMin(min) {
312 time_t t;
313 srand((unsigned int)time(&t));
314 // TODO: more random random
315 mNext = rand();
316 mSize = max - min + 1;
317 mCount = mSize;
318 }
319
320 uint32_t next() {
321 if (!mCount)
322 return 0;
323 mCount--;
324 return (mNext++ % mSize) + mMin;
325 }
326
327private:
328 uint32_t mNext;
329 uint32_t mSize;
330 uint32_t mMin;
331 uint32_t mCount;
332};
333
334} // namespace
335
336//
337// Begin XfrmController Impl
338//
339//
340XfrmController::XfrmController(void) {}
341
342int XfrmController::ipSecAllocateSpi(int32_t transformId, int32_t direction,
343 const std::string& localAddress,
344 const std::string& remoteAddress, int32_t inSpi,
345 int32_t* outSpi) {
Nathan Harold1a371532017-01-30 12:30:48 -0800346 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
347 ALOGD("transformId=%d", transformId);
348 ALOGD("direction=%d", direction);
349 ALOGD("localAddress=%s", localAddress.c_str());
350 ALOGD("remoteAddress=%s", remoteAddress.c_str());
351 ALOGD("inSpi=%0.8x", inSpi);
352
353 XfrmSaInfo saInfo{};
354 int ret;
355
356 if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, INVALID_SPI, &saInfo)) < 0) {
357 return ret;
358 }
359
360 XfrmSocketImpl sock;
361 if (!sock.open()) {
362 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
363 return -1; // TODO: return right error; for whatever reason the sock
364 // failed to open
365 }
366
367 int minSpi = RAND_SPI_MIN, maxSpi = RAND_SPI_MAX;
368
369 if (inSpi)
370 minSpi = maxSpi = inSpi;
371 ret = allocateSpi(saInfo, minSpi, maxSpi, reinterpret_cast<uint32_t*>(outSpi), sock);
372 if (ret < 0) {
373 ALOGD("Failed to Allocate an SPI, line=%d", __LINE__);
374 *outSpi = INVALID_SPI;
375 }
376
377 return ret;
378}
379
380int XfrmController::ipSecAddSecurityAssociation(
381 int32_t transformId, int32_t mode, int32_t direction, const std::string& localAddress,
Nathan Harold420ceac2017-04-05 19:36:59 -0700382 const std::string& remoteAddress, int64_t underlyingNetworkHandle, int32_t spi,
Nathan Harold1a371532017-01-30 12:30:48 -0800383 const std::string& authAlgo, const std::vector<uint8_t>& authKey, int32_t authTruncBits,
384 const std::string& cryptAlgo, const std::vector<uint8_t>& cryptKey, int32_t cryptTruncBits,
ludiec836052017-05-20 14:17:05 -0700385 int32_t encapType, int32_t encapLocalPort, int32_t encapRemotePort) {
Nathan Harold1a371532017-01-30 12:30:48 -0800386 android::RWLock::AutoWLock lock(mLock);
387
388 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
389 ALOGD("transformId=%d", transformId);
390 ALOGD("mode=%d", mode);
391 ALOGD("direction=%d", direction);
392 ALOGD("localAddress=%s", localAddress.c_str());
393 ALOGD("remoteAddress=%s", remoteAddress.c_str());
Nathan Harold420ceac2017-04-05 19:36:59 -0700394 ALOGD("underlyingNetworkHandle=%" PRIx64, underlyingNetworkHandle);
Nathan Harold1a371532017-01-30 12:30:48 -0800395 ALOGD("spi=%0.8x", spi);
396 ALOGD("authAlgo=%s", authAlgo.c_str());
397 ALOGD("authTruncBits=%d", authTruncBits);
398 ALOGD("cryptAlgo=%s", cryptAlgo.c_str());
399 ALOGD("cryptTruncBits=%d,", cryptTruncBits);
400 ALOGD("encapType=%d", encapType);
401 ALOGD("encapLocalPort=%d", encapLocalPort);
402 ALOGD("encapRemotePort=%d", encapRemotePort);
403
404 XfrmSaInfo saInfo{};
405 int ret;
406
407 if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saInfo)) < 0) {
408 return ret;
409 }
410
411 saInfo.transformId = transformId;
412
413 // STOPSHIP : range check the key lengths to prevent puncturing and overflow
414 saInfo.auth = XfrmAlgo{
415 .name = authAlgo, .key = authKey, .truncLenBits = static_cast<uint16_t>(authTruncBits)};
416
417 saInfo.crypt = XfrmAlgo{
418 .name = cryptAlgo, .key = cryptKey, .truncLenBits = static_cast<uint16_t>(cryptTruncBits)};
419
420 saInfo.direction = static_cast<XfrmDirection>(direction);
421
422 switch (static_cast<XfrmMode>(mode)) {
423 case XfrmMode::TRANSPORT:
424 case XfrmMode::TUNNEL:
425 saInfo.mode = static_cast<XfrmMode>(mode);
426 break;
427 default:
428 return -EINVAL;
429 }
430
431 XfrmSocketImpl sock;
432 if (!sock.open()) {
433 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
434 return -1; // TODO: return right error; for whatever reason the sock
435 // failed to open
436 }
437
Nathan Harold420ceac2017-04-05 19:36:59 -0700438 switch (static_cast<XfrmEncapType>(encapType)) {
439 case XfrmEncapType::ESPINUDP:
440 case XfrmEncapType::ESPINUDP_NON_IKE:
441 if (saInfo.addrFamily != AF_INET) {
442 return -EAFNOSUPPORT;
443 }
444 switch (saInfo.direction) {
445 case XfrmDirection::IN:
446 saInfo.encap.srcPort = encapRemotePort;
447 saInfo.encap.dstPort = encapLocalPort;
448 break;
449 case XfrmDirection::OUT:
450 saInfo.encap.srcPort = encapLocalPort;
451 saInfo.encap.dstPort = encapRemotePort;
452 break;
453 default:
454 return -EINVAL;
455 }
456 // fall through
457 case XfrmEncapType::NONE:
458 saInfo.encap.type = static_cast<XfrmEncapType>(encapType);
459 break;
460 default:
461 return -EINVAL;
462 }
463
Nathan Harold1a371532017-01-30 12:30:48 -0800464 ret = createTransportModeSecurityAssociation(saInfo, sock);
465 if (ret < 0) {
466 ALOGD("Failed creating a Security Association, line=%d", __LINE__);
467 return ret; // something went wrong creating the SA
468 }
469
Nathan Harold1a371532017-01-30 12:30:48 -0800470 return 0;
471}
472
473int XfrmController::ipSecDeleteSecurityAssociation(int32_t transformId, int32_t direction,
474 const std::string& localAddress,
475 const std::string& remoteAddress, int32_t spi) {
Nathan Harold1a371532017-01-30 12:30:48 -0800476 ALOGD("XfrmController:%s, line=%d", __FUNCTION__, __LINE__);
477 ALOGD("transformId=%d", transformId);
478 ALOGD("direction=%d", direction);
479 ALOGD("localAddress=%s", localAddress.c_str());
480 ALOGD("remoteAddress=%s", remoteAddress.c_str());
481 ALOGD("spi=%0.8x", spi);
482
483 XfrmSaId saId;
484 int ret;
485
486 if ((ret = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saId)) < 0) {
487 return ret;
488 }
489
490 XfrmSocketImpl sock;
491 if (!sock.open()) {
492 ALOGD("Sock open failed for XFRM, line=%d", __LINE__);
493 return -1; // TODO: return right error; for whatever reason the sock
494 // failed to open
495 }
496
497 ret = deleteSecurityAssociation(saId, sock);
498 if (ret < 0) {
499 ALOGD("Failed to delete Security Association, line=%d", __LINE__);
500 return ret; // something went wrong deleting the SA
501 }
502
503 return ret;
504}
505
506int XfrmController::fillXfrmSaId(int32_t direction, const std::string& localAddress,
507 const std::string& remoteAddress, int32_t spi, XfrmSaId* xfrmId) {
508 xfrm_address_t localXfrmAddr{}, remoteXfrmAddr{};
509
510 int addrFamilyLocal, addrFamilyRemote;
511 addrFamilyRemote = convertToXfrmAddr(remoteAddress, &remoteXfrmAddr);
512 addrFamilyLocal = convertToXfrmAddr(localAddress, &localXfrmAddr);
513 if (addrFamilyRemote < 0 || addrFamilyLocal < 0) {
514 return -EINVAL;
515 }
516
517 if (addrFamilyRemote == AF_UNSPEC ||
518 (addrFamilyLocal != AF_UNSPEC && addrFamilyLocal != addrFamilyRemote)) {
519 ALOGD("Invalid or Mismatched Address Families, %d != %d, line=%d", addrFamilyLocal,
520 addrFamilyRemote, __LINE__);
521 return -EINVAL;
522 }
523
524 xfrmId->addrFamily = addrFamilyRemote;
525
526 xfrmId->spi = htonl(spi);
527
528 switch (static_cast<XfrmDirection>(direction)) {
529 case XfrmDirection::IN:
530 xfrmId->dstAddr = localXfrmAddr;
531 xfrmId->srcAddr = remoteXfrmAddr;
532 break;
533
534 case XfrmDirection::OUT:
535 xfrmId->dstAddr = remoteXfrmAddr;
536 xfrmId->srcAddr = localXfrmAddr;
537 break;
538
539 default:
540 ALOGD("Invalid XFRM direction, line=%d", __LINE__);
541 // Invalid direction for Transport mode transform: time to bail
542 return -EINVAL;
543 }
544 return 0;
545}
546
547int XfrmController::ipSecApplyTransportModeTransform(const android::base::unique_fd& socket,
548 int32_t transformId, int32_t direction,
549 const std::string& localAddress,
550 const std::string& remoteAddress,
551 int32_t spi) {
552 ALOGD("XfrmController::%s, line=%d", __FUNCTION__, __LINE__);
553 ALOGD("transformId=%d", transformId);
554 ALOGD("direction=%d", direction);
555 ALOGD("localAddress=%s", localAddress.c_str());
556 ALOGD("remoteAddress=%s", remoteAddress.c_str());
557 ALOGD("spi=%0.8x", spi);
558
559 struct sockaddr_storage saddr;
560
Nathan Harold1a371532017-01-30 12:30:48 -0800561 int err;
Nathan Harold1a371532017-01-30 12:30:48 -0800562
ludi4072ff22017-06-15 08:56:52 -0700563 StatusOr<sockaddr_storage> ret = getSyscallInstance().getsockname<sockaddr_storage>(Fd(socket));
564 if (!isOk(ret)) {
Nathan Harold1a371532017-01-30 12:30:48 -0800565 ALOGE("Failed to get socket info in %s", __FUNCTION__);
ludi4072ff22017-06-15 08:56:52 -0700566 return -ret.status().code();
Nathan Harold1a371532017-01-30 12:30:48 -0800567 }
568
ludi4072ff22017-06-15 08:56:52 -0700569 saddr = ret.value();
570
Nathan Harold1a371532017-01-30 12:30:48 -0800571 XfrmSaInfo saInfo{};
572 saInfo.transformId = transformId;
573 saInfo.direction = static_cast<XfrmDirection>(direction);
574 saInfo.spi = spi;
575
576 if ((err = fillXfrmSaId(direction, localAddress, remoteAddress, spi, &saInfo)) < 0) {
577 ALOGE("Couldn't build SA ID %s", __FUNCTION__);
578 return -err;
579 }
580
581 if (saInfo.addrFamily != saddr.ss_family) {
582 ALOGE("Transform address family(%d) differs from socket address "
Nathan Harold420ceac2017-04-05 19:36:59 -0700583 "family(%d)!",
584 saInfo.addrFamily, saddr.ss_family);
Nathan Harold1a371532017-01-30 12:30:48 -0800585 return -EINVAL;
586 }
587
588 struct {
589 xfrm_userpolicy_info info;
590 xfrm_user_tmpl tmpl;
591 } policy{};
592
593 fillTransportModeUserSpInfo(saInfo, &policy.info);
594 fillUserTemplate(saInfo, &policy.tmpl);
595
596 LOG_HEX("XfrmUserPolicy", reinterpret_cast<char*>(&policy), sizeof(policy));
597
598 int sockOpt, sockLayer;
599 switch (saInfo.addrFamily) {
600 case AF_INET:
601 sockOpt = IP_XFRM_POLICY;
602 sockLayer = SOL_IP;
603 break;
604 case AF_INET6:
605 sockOpt = IPV6_XFRM_POLICY;
606 sockLayer = SOL_IPV6;
607 break;
608 default:
609 return -EAFNOSUPPORT;
610 }
611
ludi4072ff22017-06-15 08:56:52 -0700612 Status status = getSyscallInstance().setsockopt(Fd(socket), sockLayer, sockOpt, policy);
613 if (!isOk(status)) {
614 ALOGE("Error setting socket option for XFRM! (%s)", toString(status).c_str());
Nathan Harold1a371532017-01-30 12:30:48 -0800615 }
ludi4072ff22017-06-15 08:56:52 -0700616 return -status.code();
Nathan Harold1a371532017-01-30 12:30:48 -0800617}
618
619int XfrmController::ipSecRemoveTransportModeTransform(const android::base::unique_fd& socket) {
620 (void)socket;
621 return 0;
622}
623
624void XfrmController::fillTransportModeSelector(const XfrmSaInfo& record, xfrm_selector* selector) {
625 selector->family = record.addrFamily;
626 selector->proto = AF_UNSPEC; // TODO: do we need to match the protocol? it's
627 // possible via the socket
628 selector->ifindex = record.netId; // TODO : still need to sort this out
629}
630
631int XfrmController::createTransportModeSecurityAssociation(const XfrmSaInfo& record,
632 const XfrmSocket& sock) {
633 xfrm_usersa_info usersa{};
634 nlattr_algo_crypt crypt{};
635 nlattr_algo_auth auth{};
Nathan Harold420ceac2017-04-05 19:36:59 -0700636 nlattr_encap_tmpl encap{};
Nathan Harold1a371532017-01-30 12:30:48 -0800637
Nathan Harold420ceac2017-04-05 19:36:59 -0700638 enum {
639 NLMSG_HDR,
640 USERSA,
641 USERSA_PAD,
642 CRYPT,
643 CRYPT_PAD,
644 AUTH,
645 AUTH_PAD,
646 ENCAP,
647 ENCAP_PAD,
648 iovLen
649 };
Nathan Harold1a371532017-01-30 12:30:48 -0800650
651 iovec iov[] = {
652 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
653 {&usersa, 0}, // main usersa_info struct
654 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
655 {&crypt, 0}, // adjust size if crypt algo is present
656 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
657 {&auth, 0}, // adjust size if auth algo is present
658 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Nathan Harold420ceac2017-04-05 19:36:59 -0700659 {&encap, 0}, // adjust size if auth algo is present
660 {kPadBytes, 0}, // up to NLATTR_ALIGNTO pad bytes
Nathan Harold1a371532017-01-30 12:30:48 -0800661 };
662
663 int len;
664 len = iov[USERSA].iov_len = fillUserSaInfo(record, &usersa);
665 iov[USERSA_PAD].iov_len = NLMSG_ALIGN(len) - len;
666
667 len = iov[CRYPT].iov_len = fillNlAttrXfrmAlgoEnc(record.crypt, &crypt);
668 iov[CRYPT_PAD].iov_len = NLA_ALIGN(len) - len;
669
670 len = iov[AUTH].iov_len = fillNlAttrXfrmAlgoAuth(record.auth, &auth);
671 iov[AUTH_PAD].iov_len = NLA_ALIGN(len) - len;
672
Nathan Harold420ceac2017-04-05 19:36:59 -0700673 len = iov[ENCAP].iov_len = fillNlAttrXfrmEncapTmpl(record, &encap);
674 iov[ENCAP_PAD].iov_len = NLA_ALIGN(len) - len;
Nathan Harold1a371532017-01-30 12:30:48 -0800675 return sock.sendMessage(XFRM_MSG_UPDSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
676}
677
678int XfrmController::fillNlAttrXfrmAlgoEnc(const XfrmAlgo& inAlgo, nlattr_algo_crypt* algo) {
679 int len = NLA_HDRLEN + sizeof(xfrm_algo);
680 strncpy(algo->crypt.alg_name, inAlgo.name.c_str(), sizeof(algo->crypt.alg_name));
681 algo->crypt.alg_key_len = inAlgo.key.size() * 8; // bits
682 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size()); // FIXME :safety checks
683 len += inAlgo.key.size();
684 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_CRYPT, len);
685 return len;
686}
687
688int XfrmController::fillNlAttrXfrmAlgoAuth(const XfrmAlgo& inAlgo, nlattr_algo_auth* algo) {
689 int len = NLA_HDRLEN + sizeof(xfrm_algo_auth);
690 strncpy(algo->auth.alg_name, inAlgo.name.c_str(), sizeof(algo->auth.alg_name));
691 algo->auth.alg_key_len = inAlgo.key.size() * 8; // bits
692
693 // This is the extra field for ALG_AUTH_TRUNC
694 algo->auth.alg_trunc_len = inAlgo.truncLenBits;
695
696 memcpy(algo->key, &inAlgo.key[0], inAlgo.key.size()); // FIXME :safety checks
697 len += inAlgo.key.size();
698
699 fillXfrmNlaHdr(&algo->hdr, XFRMA_ALG_AUTH_TRUNC, len);
700 return len;
701}
702
Nathan Harold420ceac2017-04-05 19:36:59 -0700703int XfrmController::fillNlAttrXfrmEncapTmpl(const XfrmSaInfo& record, nlattr_encap_tmpl* tmpl) {
704 if (record.encap.type == XfrmEncapType::NONE) {
705 return 0;
706 }
707
708 int len = NLA_HDRLEN + sizeof(xfrm_encap_tmpl);
709 tmpl->tmpl.encap_type = static_cast<uint16_t>(record.encap.type);
710 tmpl->tmpl.encap_sport = htons(record.encap.srcPort);
711 tmpl->tmpl.encap_dport = htons(record.encap.dstPort);
712 fillXfrmNlaHdr(&tmpl->hdr, XFRMA_ENCAP, len);
713 return len;
714}
715
Nathan Harold1a371532017-01-30 12:30:48 -0800716int XfrmController::fillUserSaInfo(const XfrmSaInfo& record, xfrm_usersa_info* usersa) {
717 fillTransportModeSelector(record, &usersa->sel);
718
719 usersa->id.proto = IPPROTO_ESP;
720 usersa->id.spi = record.spi;
721 usersa->id.daddr = record.dstAddr;
722
723 usersa->saddr = record.srcAddr;
724
725 fillXfrmLifetimeDefaults(&usersa->lft);
726 fillXfrmCurLifetimeDefaults(&usersa->curlft);
727 memset(&usersa->stats, 0, sizeof(usersa->stats)); // leave stats zeroed out
728 usersa->reqid = record.transformId;
729 usersa->family = record.addrFamily;
730 usersa->mode = static_cast<uint8_t>(record.mode);
731 usersa->replay_window = REPLAY_WINDOW_SIZE;
732 usersa->flags = 0; // TODO: should we actually set flags, XFRM_SA_XFLAG_DONT_ENCAP_DSCP?
733 return sizeof(*usersa);
734}
735
736int XfrmController::fillUserSaId(const XfrmSaId& record, xfrm_usersa_id* said) {
737 said->daddr = record.dstAddr;
738 said->spi = record.spi;
739 said->family = record.addrFamily;
740 said->proto = IPPROTO_ESP;
741
742 return sizeof(*said);
743}
744
745int XfrmController::deleteSecurityAssociation(const XfrmSaId& record, const XfrmSocket& sock) {
746 xfrm_usersa_id said{};
747
748 enum { NLMSG_HDR, USERSAID, USERSAID_PAD, iovLen };
749
750 iovec iov[] = {
751 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
752 {&said, 0}, // main usersa_info struct
753 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
754 };
755
756 int len;
757 len = iov[USERSAID].iov_len = fillUserSaId(record, &said);
758 iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
759
760 return sock.sendMessage(XFRM_MSG_DELSA, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
761}
762
763int XfrmController::allocateSpi(const XfrmSaInfo& record, uint32_t minSpi, uint32_t maxSpi,
764 uint32_t* outSpi, const XfrmSocket& sock) {
765 xfrm_userspi_info spiInfo{};
766
767 enum { NLMSG_HDR, USERSAID, USERSAID_PAD, iovLen };
768
769 iovec iov[] = {
770 {NULL, 0}, // reserved for the eventual addition of a NLMSG_HDR
771 {&spiInfo, 0}, // main userspi_info struct
772 {kPadBytes, 0}, // up to NLMSG_ALIGNTO pad bytes of padding
773 };
774
775 int len;
776 if (fillUserSaInfo(record, &spiInfo.info) == 0) {
777 ALOGE("Failed to fill transport SA Info");
778 }
779
780 len = iov[USERSAID].iov_len = sizeof(spiInfo);
781 iov[USERSAID_PAD].iov_len = NLMSG_ALIGN(len) - len;
782
783 RandomSpi spiGen = RandomSpi(minSpi, maxSpi);
784 int spi, ret;
785 while ((spi = spiGen.next()) != INVALID_SPI) {
786 spiInfo.min = spi;
787 spiInfo.max = spi;
788 ret = sock.sendMessage(XFRM_MSG_ALLOCSPI, NETLINK_REQUEST_FLAGS, 0, iov, iovLen);
789
790 /* If the SPI is in use, we'll get ENOENT */
791 if (ret == -ENOENT)
792 continue;
793
794 if (ret == 0) {
795 *outSpi = spi;
Nathan Harold420ceac2017-04-05 19:36:59 -0700796 ALOGD("Allocated an SPI: %x", *outSpi);
Nathan Harold1a371532017-01-30 12:30:48 -0800797 } else {
798 *outSpi = INVALID_SPI;
799 ALOGE("SPI Allocation Failed with error %d", ret);
800 }
801
802 return ret;
803 }
804
805 // Should always be -ENOENT if we get here
806 return ret;
807}
808
809int XfrmController::fillTransportModeUserSpInfo(const XfrmSaInfo& record,
810 xfrm_userpolicy_info* usersp) {
811 fillTransportModeSelector(record, &usersp->sel);
812 fillXfrmLifetimeDefaults(&usersp->lft);
813 fillXfrmCurLifetimeDefaults(&usersp->curlft);
Nathan Harold420ceac2017-04-05 19:36:59 -0700814 /* if (index) index & 0x3 == dir -- must be true
815 * xfrm_user.c:verify_newpolicy_info() */
Nathan Harold1a371532017-01-30 12:30:48 -0800816 usersp->index = 0;
817 usersp->dir = static_cast<uint8_t>(record.direction);
818 usersp->action = XFRM_POLICY_ALLOW;
819 usersp->flags = XFRM_POLICY_LOCALOK;
820 usersp->share = XFRM_SHARE_UNIQUE;
821 return sizeof(*usersp);
822}
823
824int XfrmController::fillUserTemplate(const XfrmSaInfo& record, xfrm_user_tmpl* tmpl) {
825 tmpl->id.daddr = record.dstAddr;
826 tmpl->id.spi = record.spi;
827 tmpl->id.proto = IPPROTO_ESP;
828
829 tmpl->family = record.addrFamily;
830 tmpl->saddr = record.srcAddr;
831 tmpl->reqid = record.transformId;
832 tmpl->mode = static_cast<uint8_t>(record.mode);
833 tmpl->share = XFRM_SHARE_UNIQUE;
834 tmpl->optional = 0; // if this is true, then a failed state lookup will be considered OK:
835 // http://lxr.free-electrons.com/source/net/xfrm/xfrm_policy.c#L1492
836 tmpl->aalgos = ALGO_MASK_AUTH_ALL; // TODO: if there's a bitmask somewhere of
837 // algos, we should find it and apply it.
838 // I can't find one.
839 tmpl->ealgos = ALGO_MASK_CRYPT_ALL; // TODO: if there's a bitmask somewhere...
840 return 0;
841}
842
843} // namespace net
844} // namespace android