source: rtems-libbsd/freebsd/contrib/tcpdump/print-esp.c @ 18fa92c

55-freebsd-126-freebsd-12
Last change on this file since 18fa92c was 18fa92c, checked in by Sebastian Huber <sebastian.huber@…>, on 08/20/18 at 13:53:03

Update to FreeBSD head 2018-02-01

Git mirror commit d079ae0442af8fa3cfd6d7ede190d04e64a2c0d4.

Update #3472.

  • Property mode set to 100644
File size: 20.6 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3#ifdef __rtems__
4#include <machine/rtems-bsd-program.h>
5#include "rtems-bsd-tcpdump-namespace.h"
6#endif /* __rtems__ */
7/*      $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $        */
8
9/*
10 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
11 *      The Regents of the University of California.  All rights reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that: (1) source code distributions
15 * retain the above copyright notice and this paragraph in its entirety, (2)
16 * distributions including binary code include the above copyright notice and
17 * this paragraph in its entirety in the documentation or other materials
18 * provided with the distribution, and (3) all advertising materials mentioning
19 * features or use of this software display the following acknowledgement:
20 * ``This product includes software developed by the University of California,
21 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
22 * the University nor the names of its contributors may be used to endorse
23 * or promote products derived from this software without specific prior
24 * written permission.
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 */
29
30/* \summary: IPSEC Encapsulating Security Payload (ESP) printer */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include <netdissect-stdinc.h>
37
38#include <string.h>
39#include <stdlib.h>
40
41/* Any code in this file that depends on HAVE_LIBCRYPTO depends on
42 * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined
43 * is the simplest way of handling the dependency.
44 */
45#ifdef HAVE_LIBCRYPTO
46#ifdef HAVE_OPENSSL_EVP_H
47#include <openssl/evp.h>
48#else
49#undef HAVE_LIBCRYPTO
50#endif
51#endif
52
53#include "netdissect.h"
54#include "strtoaddr.h"
55#include "extract.h"
56
57#include "ascii_strcasecmp.h"
58
59#include "ip.h"
60#include "ip6.h"
61
62/*
63 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
64 * All rights reserved.
65 *
66 * Redistribution and use in source and binary forms, with or without
67 * modification, are permitted provided that the following conditions
68 * are met:
69 * 1. Redistributions of source code must retain the above copyright
70 *    notice, this list of conditions and the following disclaimer.
71 * 2. Redistributions in binary form must reproduce the above copyright
72 *    notice, this list of conditions and the following disclaimer in the
73 *    documentation and/or other materials provided with the distribution.
74 * 3. Neither the name of the project nor the names of its contributors
75 *    may be used to endorse or promote products derived from this software
76 *    without specific prior written permission.
77 *
78 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
79 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
80 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
81 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
82 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
83 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
84 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
85 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
86 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
87 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
88 * SUCH DAMAGE.
89 */
90
91/*
92 * RFC1827/2406 Encapsulated Security Payload.
93 */
94
95struct newesp {
96        uint32_t        esp_spi;        /* ESP */
97        uint32_t        esp_seq;        /* Sequence number */
98        /*variable size*/               /* (IV and) Payload data */
99        /*variable size*/               /* padding */
100        /*8bit*/                        /* pad size */
101        /*8bit*/                        /* next header */
102        /*8bit*/                        /* next header */
103        /*variable size, 32bit bound*/  /* Authentication data */
104};
105
106#ifdef HAVE_LIBCRYPTO
107union inaddr_u {
108        struct in_addr in4;
109        struct in6_addr in6;
110};
111struct sa_list {
112        struct sa_list  *next;
113        u_int           daddr_version;
114        union inaddr_u  daddr;
115        uint32_t        spi;          /* if == 0, then IKEv2 */
116        int             initiator;
117        u_char          spii[8];      /* for IKEv2 */
118        u_char          spir[8];
119        const EVP_CIPHER *evp;
120        int             ivlen;
121        int             authlen;
122        u_char          authsecret[256];
123        int             authsecret_len;
124        u_char          secret[256];  /* is that big enough for all secrets? */
125        int             secretlen;
126};
127
128#ifndef HAVE_EVP_CIPHER_CTX_NEW
129/*
130 * Allocate an EVP_CIPHER_CTX.
131 * Used if we have an older version of OpenSSL that doesn't provide
132 * routines to allocate and free them.
133 */
134static EVP_CIPHER_CTX *
135EVP_CIPHER_CTX_new(void)
136{
137        EVP_CIPHER_CTX *ctx;
138
139        ctx = malloc(sizeof(*ctx));
140        if (ctx == NULL)
141                return (NULL);
142        memset(ctx, 0, sizeof(*ctx));
143        return (ctx);
144}
145
146static void
147EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
148{
149        EVP_CIPHER_CTX_cleanup(ctx);
150        free(ctx);
151}
152#endif
153
154#ifdef HAVE_EVP_CIPHERINIT_EX
155/*
156 * Initialize the cipher by calling EVP_CipherInit_ex(), because
157 * calling EVP_CipherInit() will reset the cipher context, clearing
158 * the cipher, so calling it twice, with the second call having a
159 * null cipher, will clear the already-set cipher.  EVP_CipherInit_ex(),
160 * however, won't reset the cipher context, so you can use it to specify
161 * the IV oin a second call after a first call to EVP_CipherInit_ex()
162 * to set the cipher and the key.
163 *
164 * XXX - is there some reason why we need to make two calls?
165 */
166static int
167set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
168                      const unsigned char *key,
169                      const unsigned char *iv, int enc)
170{
171        return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc);
172}
173#else
174/*
175 * Initialize the cipher by calling EVP_CipherInit(), because we don't
176 * have EVP_CipherInit_ex(); we rely on it not trashing the context.
177 */
178static int
179set_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
180                      const unsigned char *key,
181                      const unsigned char *iv, int enc)
182{
183        return EVP_CipherInit(ctx, cipher, key, iv, enc);
184}
185#endif
186
187/*
188 * this will adjust ndo_packetp and ndo_snapend to new buffer!
189 */
190USES_APPLE_DEPRECATED_API
191int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
192                                      int initiator,
193                                      u_char spii[8], u_char spir[8],
194                                      const u_char *buf, const u_char *end)
195{
196        struct sa_list *sa;
197        const u_char *iv;
198        unsigned int len;
199        EVP_CIPHER_CTX *ctx;
200        unsigned int block_size, output_buffer_size;
201        u_char *output_buffer;
202
203        /* initiator arg is any non-zero value */
204        if(initiator) initiator=1;
205
206        /* see if we can find the SA, and if so, decode it */
207        for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
208                if (sa->spi == 0
209                    && initiator == sa->initiator
210                    && memcmp(spii, sa->spii, 8) == 0
211                    && memcmp(spir, sa->spir, 8) == 0)
212                        break;
213        }
214
215        if(sa == NULL) return 0;
216        if(sa->evp == NULL) return 0;
217
218        /*
219         * remove authenticator, and see if we still have something to
220         * work with
221         */
222        end = end - sa->authlen;
223        iv  = buf;
224        buf = buf + sa->ivlen;
225        len = end-buf;
226
227        if(end <= buf) return 0;
228
229        ctx = EVP_CIPHER_CTX_new();
230        if (ctx == NULL)
231                return 0;
232        if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0)
233                (*ndo->ndo_warning)(ndo, "espkey init failed");
234        set_cipher_parameters(ctx, NULL, NULL, iv, 0);
235        /*
236         * Allocate a buffer for the decrypted data.
237         * The output buffer must be separate from the input buffer, and
238         * its size must be a multiple of the cipher block size.
239         */
240        block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
241        output_buffer_size = len + (block_size - len % block_size);
242        output_buffer = (u_char *)malloc(output_buffer_size);
243        if (output_buffer == NULL) {
244                (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
245                EVP_CIPHER_CTX_free(ctx);
246                return 0;
247        }
248        EVP_Cipher(ctx, output_buffer, buf, len);
249        EVP_CIPHER_CTX_free(ctx);
250
251        /*
252         * XXX - of course this is wrong, because buf is a const buffer,
253         * but changing this would require a more complicated fix.
254         */
255        memcpy(__DECONST(u_char *, buf), output_buffer, len);
256        free(output_buffer);
257
258        ndo->ndo_packetp = buf;
259        ndo->ndo_snapend = end;
260
261        return 1;
262}
263USES_APPLE_RST
264
265static void esp_print_addsa(netdissect_options *ndo,
266                            struct sa_list *sa, int sa_def)
267{
268        /* copy the "sa" */
269
270        struct sa_list *nsa;
271
272        nsa = (struct sa_list *)malloc(sizeof(struct sa_list));
273        if (nsa == NULL)
274                (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure");
275
276        *nsa = *sa;
277
278        if (sa_def)
279                ndo->ndo_sa_default = nsa;
280
281        nsa->next = ndo->ndo_sa_list_head;
282        ndo->ndo_sa_list_head = nsa;
283}
284
285
286static u_int hexdigit(netdissect_options *ndo, char hex)
287{
288        if (hex >= '0' && hex <= '9')
289                return (hex - '0');
290        else if (hex >= 'A' && hex <= 'F')
291                return (hex - 'A' + 10);
292        else if (hex >= 'a' && hex <= 'f')
293                return (hex - 'a' + 10);
294        else {
295                (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex);
296                return 0;
297        }
298}
299
300static u_int hex2byte(netdissect_options *ndo, char *hexstring)
301{
302        u_int byte;
303
304        byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]);
305        return byte;
306}
307
308/*
309 * returns size of binary, 0 on failure.
310 */
311static
312int espprint_decode_hex(netdissect_options *ndo,
313                        u_char *binbuf, unsigned int binbuf_len,
314                        char *hex)
315{
316        unsigned int len;
317        int i;
318
319        len = strlen(hex) / 2;
320
321        if (len > binbuf_len) {
322                (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len);
323                return 0;
324        }
325
326        i = 0;
327        while (hex[0] != '\0' && hex[1]!='\0') {
328                binbuf[i] = hex2byte(ndo, hex);
329                hex += 2;
330                i++;
331        }
332
333        return i;
334}
335
336/*
337 * decode the form:    SPINUM@IP <tab> ALGONAME:0xsecret
338 */
339
340USES_APPLE_DEPRECATED_API
341static int
342espprint_decode_encalgo(netdissect_options *ndo,
343                        char *decode, struct sa_list *sa)
344{
345        size_t i;
346        const EVP_CIPHER *evp;
347        int authlen = 0;
348        char *colon, *p;
349
350        colon = strchr(decode, ':');
351        if (colon == NULL) {
352                (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
353                return 0;
354        }
355        *colon = '\0';
356
357        if (strlen(decode) > strlen("-hmac96") &&
358            !strcmp(decode + strlen(decode) - strlen("-hmac96"),
359                    "-hmac96")) {
360                p = strstr(decode, "-hmac96");
361                *p = '\0';
362                authlen = 12;
363        }
364        if (strlen(decode) > strlen("-cbc") &&
365            !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) {
366                p = strstr(decode, "-cbc");
367                *p = '\0';
368        }
369        evp = EVP_get_cipherbyname(decode);
370
371        if (!evp) {
372                (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode);
373                sa->evp = NULL;
374                sa->authlen = 0;
375                sa->ivlen = 0;
376                return 0;
377        }
378
379        sa->evp = evp;
380        sa->authlen = authlen;
381        sa->ivlen = EVP_CIPHER_iv_length(evp);
382
383        colon++;
384        if (colon[0] == '0' && colon[1] == 'x') {
385                /* decode some hex! */
386
387                colon += 2;
388                sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon);
389                if(sa->secretlen == 0) return 0;
390        } else {
391                i = strlen(colon);
392
393                if (i < sizeof(sa->secret)) {
394                        memcpy(sa->secret, colon, i);
395                        sa->secretlen = i;
396                } else {
397                        memcpy(sa->secret, colon, sizeof(sa->secret));
398                        sa->secretlen = sizeof(sa->secret);
399                }
400        }
401
402        return 1;
403}
404USES_APPLE_RST
405
406/*
407 * for the moment, ignore the auth algorith, just hard code the authenticator
408 * length. Need to research how openssl looks up HMAC stuff.
409 */
410static int
411espprint_decode_authalgo(netdissect_options *ndo,
412                         char *decode, struct sa_list *sa)
413{
414        char *colon;
415
416        colon = strchr(decode, ':');
417        if (colon == NULL) {
418                (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode);
419                return 0;
420        }
421        *colon = '\0';
422
423        if(ascii_strcasecmp(colon,"sha1") == 0 ||
424           ascii_strcasecmp(colon,"md5") == 0) {
425                sa->authlen = 12;
426        }
427        return 1;
428}
429
430static void esp_print_decode_ikeline(netdissect_options *ndo, char *line,
431                                     const char *file, int lineno)
432{
433        /* it's an IKEv2 secret, store it instead */
434        struct sa_list sa1;
435
436        char *init;
437        char *icookie, *rcookie;
438        int   ilen, rlen;
439        char *authkey;
440        char *enckey;
441
442        init = strsep(&line, " \t");
443        icookie = strsep(&line, " \t");
444        rcookie = strsep(&line, " \t");
445        authkey = strsep(&line, " \t");
446        enckey  = strsep(&line, " \t");
447
448        /* if any fields are missing */
449        if(!init || !icookie || !rcookie || !authkey || !enckey) {
450                (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u",
451                                    file, lineno);
452
453                return;
454        }
455
456        ilen = strlen(icookie);
457        rlen = strlen(rcookie);
458
459        if((init[0]!='I' && init[0]!='R')
460           || icookie[0]!='0' || icookie[1]!='x'
461           || rcookie[0]!='0' || rcookie[1]!='x'
462           || ilen!=18
463           || rlen!=18) {
464                (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.",
465                                    file, lineno);
466
467                (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)",
468                                    init, icookie, ilen, rcookie, rlen);
469
470                return;
471        }
472
473        sa1.spi = 0;
474        sa1.initiator = (init[0] == 'I');
475        if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8)
476                return;
477
478        if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8)
479                return;
480
481        if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return;
482
483        if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return;
484
485        esp_print_addsa(ndo, &sa1, FALSE);
486}
487
488/*
489 *
490 * special form: file /name
491 * causes us to go read from this file instead.
492 *
493 */
494static void esp_print_decode_onesecret(netdissect_options *ndo, char *line,
495                                       const char *file, int lineno)
496{
497        struct sa_list sa1;
498        int sa_def;
499
500        char *spikey;
501        char *decode;
502
503        spikey = strsep(&line, " \t");
504        sa_def = 0;
505        memset(&sa1, 0, sizeof(struct sa_list));
506
507        /* if there is only one token, then it is an algo:key token */
508        if (line == NULL) {
509                decode = spikey;
510                spikey = NULL;
511                /* sa1.daddr.version = 0; */
512                /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */
513                /* sa1.spi = 0; */
514                sa_def    = 1;
515        } else
516                decode = line;
517
518        if (spikey && ascii_strcasecmp(spikey, "file") == 0) {
519                /* open file and read it */
520                FILE *secretfile;
521                char  fileline[1024];
522                int   subfile_lineno=0;
523                char  *nl;
524                char *filename = line;
525
526                secretfile = fopen(filename, FOPEN_READ_TXT);
527                if (secretfile == NULL) {
528                        (*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n",
529                            filename, strerror(errno));
530                        return;
531                }
532
533                while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) {
534                        subfile_lineno++;
535                        /* remove newline from the line */
536                        nl = strchr(fileline, '\n');
537                        if (nl)
538                                *nl = '\0';
539                        if (fileline[0] == '#') continue;
540                        if (fileline[0] == '\0') continue;
541
542                        esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno);
543                }
544                fclose(secretfile);
545
546                return;
547        }
548
549        if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) {
550                esp_print_decode_ikeline(ndo, line, file, lineno);
551                return;
552        }
553
554        if (spikey) {
555
556                char *spistr, *foo;
557                uint32_t spino;
558
559                spistr = strsep(&spikey, "@");
560
561                spino = strtoul(spistr, &foo, 0);
562                if (spistr == foo || !spikey) {
563                        (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo);
564                        return;
565                }
566
567                sa1.spi = spino;
568
569                if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) {
570                        sa1.daddr_version = 6;
571                } else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) {
572                        sa1.daddr_version = 4;
573                } else {
574                        (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey);
575                        return;
576                }
577        }
578
579        if (decode) {
580                /* skip any blank spaces */
581                while (isspace((unsigned char)*decode))
582                        decode++;
583
584                if(!espprint_decode_encalgo(ndo, decode, &sa1)) {
585                        return;
586                }
587        }
588
589        esp_print_addsa(ndo, &sa1, sa_def);
590}
591
592USES_APPLE_DEPRECATED_API
593static void esp_init(netdissect_options *ndo _U_)
594{
595        /*
596         * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so
597         * we check whether it's undefined or it's less than the
598         * value for 1.1.0.
599         */
600#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
601        OpenSSL_add_all_algorithms();
602#endif
603        EVP_add_cipher_alias(SN_des_ede3_cbc, "3des");
604}
605USES_APPLE_RST
606
607void esp_print_decodesecret(netdissect_options *ndo)
608{
609        char *line;
610        char *p;
611        static int initialized = 0;
612
613        if (!initialized) {
614                esp_init(ndo);
615                initialized = 1;
616        }
617
618        p = ndo->ndo_espsecret;
619
620        while (p && p[0] != '\0') {
621                /* pick out the first line or first thing until a comma */
622                if ((line = strsep(&p, "\n,")) == NULL) {
623                        line = p;
624                        p = NULL;
625                }
626
627                esp_print_decode_onesecret(ndo, line, "cmdline", 0);
628        }
629
630        ndo->ndo_espsecret = NULL;
631}
632
633#endif
634
635#ifdef HAVE_LIBCRYPTO
636USES_APPLE_DEPRECATED_API
637#endif
638int
639esp_print(netdissect_options *ndo,
640          const u_char *bp, const int length, const u_char *bp2
641#ifndef HAVE_LIBCRYPTO
642        _U_
643#endif
644        ,
645        int *nhdr
646#ifndef HAVE_LIBCRYPTO
647        _U_
648#endif
649        ,
650        int *padlen
651#ifndef HAVE_LIBCRYPTO
652        _U_
653#endif
654        )
655{
656        register const struct newesp *esp;
657        register const u_char *ep;
658#ifdef HAVE_LIBCRYPTO
659        const struct ip *ip;
660        struct sa_list *sa = NULL;
661        const struct ip6_hdr *ip6 = NULL;
662        int advance;
663        int len;
664        u_char *secret;
665        int ivlen = 0;
666        const u_char *ivoff;
667        const u_char *p;
668        EVP_CIPHER_CTX *ctx;
669        unsigned int block_size, output_buffer_size;
670        u_char *output_buffer;
671#endif
672
673        esp = (const struct newesp *)bp;
674
675#ifdef HAVE_LIBCRYPTO
676        secret = NULL;
677        advance = 0;
678#endif
679
680#if 0
681        /* keep secret out of a register */
682        p = (u_char *)&secret;
683#endif
684
685        /* 'ep' points to the end of available data. */
686        ep = ndo->ndo_snapend;
687
688        if ((const u_char *)(esp + 1) >= ep) {
689                ND_PRINT((ndo, "[|ESP]"));
690                goto fail;
691        }
692        ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)));
693        ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)));
694        ND_PRINT((ndo, ", length %u", length));
695
696#ifndef HAVE_LIBCRYPTO
697        goto fail;
698#else
699        /* initiailize SAs */
700        if (ndo->ndo_sa_list_head == NULL) {
701                if (!ndo->ndo_espsecret)
702                        goto fail;
703
704                esp_print_decodesecret(ndo);
705        }
706
707        if (ndo->ndo_sa_list_head == NULL)
708                goto fail;
709
710        ip = (const struct ip *)bp2;
711        switch (IP_V(ip)) {
712        case 6:
713                ip6 = (const struct ip6_hdr *)bp2;
714                /* we do not attempt to decrypt jumbograms */
715                if (!EXTRACT_16BITS(&ip6->ip6_plen))
716                        goto fail;
717                /* if we can't get nexthdr, we do not need to decrypt it */
718                len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen);
719
720                /* see if we can find the SA, and if so, decode it */
721                for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
722                        if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
723                            sa->daddr_version == 6 &&
724                            UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst,
725                                   sizeof(struct in6_addr)) == 0) {
726                                break;
727                        }
728                }
729                break;
730        case 4:
731                /* nexthdr & padding are in the last fragment */
732                if (EXTRACT_16BITS(&ip->ip_off) & IP_MF)
733                        goto fail;
734                len = EXTRACT_16BITS(&ip->ip_len);
735
736                /* see if we can find the SA, and if so, decode it */
737                for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) {
738                        if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) &&
739                            sa->daddr_version == 4 &&
740                            UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst,
741                                   sizeof(struct in_addr)) == 0) {
742                                break;
743                        }
744                }
745                break;
746        default:
747                goto fail;
748        }
749
750        /* if we didn't find the specific one, then look for
751         * an unspecified one.
752         */
753        if (sa == NULL)
754                sa = ndo->ndo_sa_default;
755
756        /* if not found fail */
757        if (sa == NULL)
758                goto fail;
759
760        /* if we can't get nexthdr, we do not need to decrypt it */
761        if (ep - bp2 < len)
762                goto fail;
763        if (ep - bp2 > len) {
764                /* FCS included at end of frame (NetBSD 1.6 or later) */
765                ep = bp2 + len;
766        }
767
768        /* pointer to the IV, if there is one */
769        ivoff = (const u_char *)(esp + 1) + 0;
770        /* length of the IV, if there is one; 0, if there isn't */
771        ivlen = sa->ivlen;
772        secret = sa->secret;
773        ep = ep - sa->authlen;
774
775        if (sa->evp) {
776                ctx = EVP_CIPHER_CTX_new();
777                if (ctx != NULL) {
778                        if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0)
779                                (*ndo->ndo_warning)(ndo, "espkey init failed");
780
781                        p = ivoff;
782                        set_cipher_parameters(ctx, NULL, NULL, p, 0);
783                        len = ep - (p + ivlen);
784
785                        /*
786                         * Allocate a buffer for the decrypted data.
787                         * The output buffer must be separate from the
788                         * input buffer, and its size must be a multiple
789                         * of the cipher block size.
790                         */
791                        block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx);
792                        output_buffer_size = len + (block_size - len % block_size);
793                        output_buffer = (u_char *)malloc(output_buffer_size);
794                        if (output_buffer == NULL) {
795                                (*ndo->ndo_warning)(ndo, "can't allocate memory for decryption buffer");
796                                EVP_CIPHER_CTX_free(ctx);
797                                return -1;
798                        }
799
800                        EVP_Cipher(ctx, output_buffer, p + ivlen, len);
801                        EVP_CIPHER_CTX_free(ctx);
802                        /*
803                         * XXX - of course this is wrong, because buf is a
804                         * const buffer, but changing this would require a
805                         * more complicated fix.
806                         */
807                        memcpy(__DECONST(u_char *, p + ivlen), output_buffer, len);
808                        free(output_buffer);
809                        advance = ivoff - (const u_char *)esp + ivlen;
810                } else
811                        advance = sizeof(struct newesp);
812        } else
813                advance = sizeof(struct newesp);
814
815        /* sanity check for pad length */
816        if (ep - bp < *(ep - 2))
817                goto fail;
818
819        if (padlen)
820                *padlen = *(ep - 2) + 2;
821
822        if (nhdr)
823                *nhdr = *(ep - 1);
824
825        ND_PRINT((ndo, ": "));
826        return advance;
827#endif
828
829fail:
830        return -1;
831}
832#ifdef HAVE_LIBCRYPTO
833USES_APPLE_RST
834#endif
835
836/*
837 * Local Variables:
838 * c-style: whitesmith
839 * c-basic-offset: 8
840 * End:
841 */
842#ifdef __rtems__
843#include "rtems-bsd-tcpdump-print-esp-data.h"
844#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.