print-esp.c revision 313537
156893Sfenner/* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */ 256893Sfenner 356893Sfenner/* 456893Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 556893Sfenner * The Regents of the University of California. All rights reserved. 656893Sfenner * 756893Sfenner * Redistribution and use in source and binary forms, with or without 856893Sfenner * modification, are permitted provided that: (1) source code distributions 956893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 1056893Sfenner * distributions including binary code include the above copyright notice and 1156893Sfenner * this paragraph in its entirety in the documentation or other materials 1256893Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1356893Sfenner * features or use of this software display the following acknowledgement: 1456893Sfenner * ``This product includes software developed by the University of California, 1556893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1656893Sfenner * the University nor the names of its contributors may be used to endorse 1756893Sfenner * or promote products derived from this software without specific prior 1856893Sfenner * written permission. 1956893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 2056893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 2156893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2256893Sfenner */ 2356893Sfenner 24313537Sglebius/* \summary: IPSEC Encapsulating Security Payload (ESP) printer */ 25313537Sglebius 2656893Sfenner#ifdef HAVE_CONFIG_H 2756893Sfenner#include "config.h" 2856893Sfenner#endif 2956893Sfenner 30313537Sglebius#include <netdissect-stdinc.h> 31127668Sbms 32276788Sdelphij#include <string.h> 33111726Sfenner#include <stdlib.h> 3456893Sfenner 35276788Sdelphij/* Any code in this file that depends on HAVE_LIBCRYPTO depends on 36276788Sdelphij * HAVE_OPENSSL_EVP_H too. Undefining the former when the latter isn't defined 37276788Sdelphij * is the simplest way of handling the dependency. 38276788Sdelphij */ 3975115Sfenner#ifdef HAVE_LIBCRYPTO 40127668Sbms#ifdef HAVE_OPENSSL_EVP_H 41127668Sbms#include <openssl/evp.h> 42276788Sdelphij#else 43276788Sdelphij#undef HAVE_LIBCRYPTO 4456893Sfenner#endif 4556893Sfenner#endif 4656893Sfenner 47313537Sglebius#include "netdissect.h" 48313537Sglebius#include "strtoaddr.h" 49313537Sglebius#include "extract.h" 50313537Sglebius 51313537Sglebius#include "ascii_strcasecmp.h" 52313537Sglebius 5375115Sfenner#include "ip.h" 5475115Sfenner#include "ip6.h" 5556893Sfenner 56276788Sdelphij/* 57276788Sdelphij * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 58276788Sdelphij * All rights reserved. 59276788Sdelphij * 60276788Sdelphij * Redistribution and use in source and binary forms, with or without 61276788Sdelphij * modification, are permitted provided that the following conditions 62276788Sdelphij * are met: 63276788Sdelphij * 1. Redistributions of source code must retain the above copyright 64276788Sdelphij * notice, this list of conditions and the following disclaimer. 65276788Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 66276788Sdelphij * notice, this list of conditions and the following disclaimer in the 67276788Sdelphij * documentation and/or other materials provided with the distribution. 68276788Sdelphij * 3. Neither the name of the project nor the names of its contributors 69276788Sdelphij * may be used to endorse or promote products derived from this software 70276788Sdelphij * without specific prior written permission. 71276788Sdelphij * 72276788Sdelphij * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 73276788Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 74276788Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 75276788Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 76276788Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 77276788Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 78276788Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 79276788Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 80276788Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 81276788Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 82276788Sdelphij * SUCH DAMAGE. 83276788Sdelphij */ 84276788Sdelphij 85276788Sdelphij/* 86276788Sdelphij * RFC1827/2406 Encapsulated Security Payload. 87276788Sdelphij */ 88276788Sdelphij 89276788Sdelphijstruct newesp { 90276788Sdelphij uint32_t esp_spi; /* ESP */ 91276788Sdelphij uint32_t esp_seq; /* Sequence number */ 92276788Sdelphij /*variable size*/ /* (IV and) Payload data */ 93276788Sdelphij /*variable size*/ /* padding */ 94276788Sdelphij /*8bit*/ /* pad size */ 95276788Sdelphij /*8bit*/ /* next header */ 96276788Sdelphij /*8bit*/ /* next header */ 97276788Sdelphij /*variable size, 32bit bound*/ /* Authentication data */ 98127668Sbms}; 9998524Sfenner 100127668Sbms#ifdef HAVE_LIBCRYPTO 101276788Sdelphijunion inaddr_u { 102276788Sdelphij struct in_addr in4; 103276788Sdelphij struct in6_addr in6; 104276788Sdelphij}; 105127668Sbmsstruct sa_list { 106127668Sbms struct sa_list *next; 107276788Sdelphij u_int daddr_version; 108276788Sdelphij union inaddr_u daddr; 109276788Sdelphij uint32_t spi; /* if == 0, then IKEv2 */ 110214478Srpaulo int initiator; 111214478Srpaulo u_char spii[8]; /* for IKEv2 */ 112214478Srpaulo u_char spir[8]; 113127668Sbms const EVP_CIPHER *evp; 114127668Sbms int ivlen; 115127668Sbms int authlen; 116214478Srpaulo u_char authsecret[256]; 117214478Srpaulo int authsecret_len; 118147899Ssam u_char secret[256]; /* is that big enough for all secrets? */ 119127668Sbms int secretlen; 120127668Sbms}; 12198524Sfenner 122313537Sglebius#ifndef HAVE_EVP_CIPHER_CTX_NEW 123214478Srpaulo/* 124313537Sglebius * Allocate an EVP_CIPHER_CTX. 125313537Sglebius * Used if we have an older version of OpenSSL that doesn't provide 126313537Sglebius * routines to allocate and free them. 127313537Sglebius */ 128313537Sglebiusstatic EVP_CIPHER_CTX * 129313537SglebiusEVP_CIPHER_CTX_new(void) 130313537Sglebius{ 131313537Sglebius EVP_CIPHER_CTX *ctx; 132313537Sglebius 133313537Sglebius ctx = malloc(sizeof(*ctx)); 134313537Sglebius if (ctx == NULL) 135313537Sglebius return (NULL); 136313537Sglebius memset(ctx, 0, sizeof(*ctx)); 137313537Sglebius return (ctx); 138313537Sglebius} 139313537Sglebius 140313537Sglebiusstatic void 141313537SglebiusEVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) 142313537Sglebius{ 143313537Sglebius EVP_CIPHER_CTX_cleanup(ctx); 144313537Sglebius free(ctx); 145313537Sglebius} 146313537Sglebius#endif 147313537Sglebius 148313537Sglebius/* 149214478Srpaulo * this will adjust ndo_packetp and ndo_snapend to new buffer! 150214478Srpaulo */ 151276788SdelphijUSES_APPLE_DEPRECATED_API 152214478Srpauloint esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, 153214478Srpaulo int initiator, 154214478Srpaulo u_char spii[8], u_char spir[8], 155313537Sglebius const u_char *buf, const u_char *end) 156214478Srpaulo{ 157214478Srpaulo struct sa_list *sa; 158313537Sglebius const u_char *iv; 159214478Srpaulo int len; 160313537Sglebius EVP_CIPHER_CTX *ctx; 161214478Srpaulo 162214478Srpaulo /* initiator arg is any non-zero value */ 163214478Srpaulo if(initiator) initiator=1; 164276788Sdelphij 165214478Srpaulo /* see if we can find the SA, and if so, decode it */ 166214478Srpaulo for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 167214478Srpaulo if (sa->spi == 0 168214478Srpaulo && initiator == sa->initiator 169214478Srpaulo && memcmp(spii, sa->spii, 8) == 0 170214478Srpaulo && memcmp(spir, sa->spir, 8) == 0) 171214478Srpaulo break; 172214478Srpaulo } 173214478Srpaulo 174214478Srpaulo if(sa == NULL) return 0; 175214478Srpaulo if(sa->evp == NULL) return 0; 176214478Srpaulo 177214478Srpaulo /* 178214478Srpaulo * remove authenticator, and see if we still have something to 179214478Srpaulo * work with 180214478Srpaulo */ 181214478Srpaulo end = end - sa->authlen; 182214478Srpaulo iv = buf; 183214478Srpaulo buf = buf + sa->ivlen; 184214478Srpaulo len = end-buf; 185214478Srpaulo 186214478Srpaulo if(end <= buf) return 0; 187214478Srpaulo 188313537Sglebius ctx = EVP_CIPHER_CTX_new(); 189313537Sglebius if (ctx == NULL) 190313537Sglebius return 0; 191313537Sglebius if (EVP_CipherInit(ctx, sa->evp, sa->secret, NULL, 0) < 0) 192214478Srpaulo (*ndo->ndo_warning)(ndo, "espkey init failed"); 193313537Sglebius EVP_CipherInit(ctx, NULL, NULL, iv, 0); 194313537Sglebius EVP_Cipher(ctx, __DECONST(u_char *, buf), buf, len); 195313537Sglebius EVP_CIPHER_CTX_free(ctx); 196214478Srpaulo 197214478Srpaulo ndo->ndo_packetp = buf; 198214478Srpaulo ndo->ndo_snapend = end; 199214478Srpaulo 200214478Srpaulo return 1; 201276788Sdelphij 202214478Srpaulo} 203276788SdelphijUSES_APPLE_RST 204214478Srpaulo 205146773Ssamstatic void esp_print_addsa(netdissect_options *ndo, 206146773Ssam struct sa_list *sa, int sa_def) 207127668Sbms{ 208127668Sbms /* copy the "sa" */ 20998524Sfenner 210127668Sbms struct sa_list *nsa; 21198524Sfenner 212127668Sbms nsa = (struct sa_list *)malloc(sizeof(struct sa_list)); 213127668Sbms if (nsa == NULL) 214146773Ssam (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure"); 21598524Sfenner 216127668Sbms *nsa = *sa; 21798524Sfenner 218127668Sbms if (sa_def) 219146773Ssam ndo->ndo_sa_default = nsa; 220127668Sbms 221146773Ssam nsa->next = ndo->ndo_sa_list_head; 222146773Ssam ndo->ndo_sa_list_head = nsa; 223127668Sbms} 224127668Sbms 225127668Sbms 226147899Ssamstatic u_int hexdigit(netdissect_options *ndo, char hex) 22798524Sfenner{ 228127668Sbms if (hex >= '0' && hex <= '9') 22998524Sfenner return (hex - '0'); 230127668Sbms else if (hex >= 'A' && hex <= 'F') 23198524Sfenner return (hex - 'A' + 10); 232127668Sbms else if (hex >= 'a' && hex <= 'f') 23398524Sfenner return (hex - 'a' + 10); 234127668Sbms else { 235146773Ssam (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex); 23698524Sfenner return 0; 23798524Sfenner } 23898524Sfenner} 23998524Sfenner 240147899Ssamstatic u_int hex2byte(netdissect_options *ndo, char *hexstring) 24198524Sfenner{ 242147899Ssam u_int byte; 24398524Sfenner 244146773Ssam byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]); 24598524Sfenner return byte; 24698524Sfenner} 24798524Sfenner 248127668Sbms/* 249214478Srpaulo * returns size of binary, 0 on failure. 250214478Srpaulo */ 251214478Srpaulostatic 252214478Srpauloint espprint_decode_hex(netdissect_options *ndo, 253214478Srpaulo u_char *binbuf, unsigned int binbuf_len, 254214478Srpaulo char *hex) 255214478Srpaulo{ 256214478Srpaulo unsigned int len; 257214478Srpaulo int i; 258214478Srpaulo 259214478Srpaulo len = strlen(hex) / 2; 260276788Sdelphij 261214478Srpaulo if (len > binbuf_len) { 262214478Srpaulo (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len); 263214478Srpaulo return 0; 264214478Srpaulo } 265276788Sdelphij 266214478Srpaulo i = 0; 267214478Srpaulo while (hex[0] != '\0' && hex[1]!='\0') { 268214478Srpaulo binbuf[i] = hex2byte(ndo, hex); 269214478Srpaulo hex += 2; 270214478Srpaulo i++; 271214478Srpaulo } 272214478Srpaulo 273214478Srpaulo return i; 274214478Srpaulo} 275214478Srpaulo 276214478Srpaulo/* 277127668Sbms * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret 278214478Srpaulo */ 279214478Srpaulo 280276788SdelphijUSES_APPLE_DEPRECATED_API 281214478Srpaulostatic int 282214478Srpauloespprint_decode_encalgo(netdissect_options *ndo, 283214478Srpaulo char *decode, struct sa_list *sa) 284214478Srpaulo{ 285214478Srpaulo size_t i; 286214478Srpaulo const EVP_CIPHER *evp; 287214478Srpaulo int authlen = 0; 288214478Srpaulo char *colon, *p; 289276788Sdelphij 290214478Srpaulo colon = strchr(decode, ':'); 291214478Srpaulo if (colon == NULL) { 292214478Srpaulo (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 293214478Srpaulo return 0; 294214478Srpaulo } 295214478Srpaulo *colon = '\0'; 296276788Sdelphij 297214478Srpaulo if (strlen(decode) > strlen("-hmac96") && 298214478Srpaulo !strcmp(decode + strlen(decode) - strlen("-hmac96"), 299214478Srpaulo "-hmac96")) { 300214478Srpaulo p = strstr(decode, "-hmac96"); 301214478Srpaulo *p = '\0'; 302214478Srpaulo authlen = 12; 303214478Srpaulo } 304214478Srpaulo if (strlen(decode) > strlen("-cbc") && 305214478Srpaulo !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 306214478Srpaulo p = strstr(decode, "-cbc"); 307214478Srpaulo *p = '\0'; 308214478Srpaulo } 309214478Srpaulo evp = EVP_get_cipherbyname(decode); 310214478Srpaulo 311214478Srpaulo if (!evp) { 312214478Srpaulo (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode); 313214478Srpaulo sa->evp = NULL; 314214478Srpaulo sa->authlen = 0; 315214478Srpaulo sa->ivlen = 0; 316214478Srpaulo return 0; 317214478Srpaulo } 318276788Sdelphij 319214478Srpaulo sa->evp = evp; 320214478Srpaulo sa->authlen = authlen; 321214478Srpaulo sa->ivlen = EVP_CIPHER_iv_length(evp); 322276788Sdelphij 323214478Srpaulo colon++; 324214478Srpaulo if (colon[0] == '0' && colon[1] == 'x') { 325214478Srpaulo /* decode some hex! */ 326214478Srpaulo 327214478Srpaulo colon += 2; 328214478Srpaulo sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon); 329214478Srpaulo if(sa->secretlen == 0) return 0; 330214478Srpaulo } else { 331214478Srpaulo i = strlen(colon); 332276788Sdelphij 333214478Srpaulo if (i < sizeof(sa->secret)) { 334214478Srpaulo memcpy(sa->secret, colon, i); 335214478Srpaulo sa->secretlen = i; 336214478Srpaulo } else { 337214478Srpaulo memcpy(sa->secret, colon, sizeof(sa->secret)); 338214478Srpaulo sa->secretlen = sizeof(sa->secret); 339214478Srpaulo } 340214478Srpaulo } 341214478Srpaulo 342214478Srpaulo return 1; 343214478Srpaulo} 344276788SdelphijUSES_APPLE_RST 345214478Srpaulo 346214478Srpaulo/* 347214478Srpaulo * for the moment, ignore the auth algorith, just hard code the authenticator 348214478Srpaulo * length. Need to research how openssl looks up HMAC stuff. 349214478Srpaulo */ 350214478Srpaulostatic int 351214478Srpauloespprint_decode_authalgo(netdissect_options *ndo, 352214478Srpaulo char *decode, struct sa_list *sa) 353214478Srpaulo{ 354214478Srpaulo char *colon; 355214478Srpaulo 356214478Srpaulo colon = strchr(decode, ':'); 357214478Srpaulo if (colon == NULL) { 358214478Srpaulo (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 359214478Srpaulo return 0; 360214478Srpaulo } 361214478Srpaulo *colon = '\0'; 362276788Sdelphij 363313537Sglebius if(ascii_strcasecmp(colon,"sha1") == 0 || 364313537Sglebius ascii_strcasecmp(colon,"md5") == 0) { 365214478Srpaulo sa->authlen = 12; 366214478Srpaulo } 367214478Srpaulo return 1; 368214478Srpaulo} 369214478Srpaulo 370214478Srpaulostatic void esp_print_decode_ikeline(netdissect_options *ndo, char *line, 371214478Srpaulo const char *file, int lineno) 372214478Srpaulo{ 373214478Srpaulo /* it's an IKEv2 secret, store it instead */ 374214478Srpaulo struct sa_list sa1; 375214478Srpaulo 376214478Srpaulo char *init; 377214478Srpaulo char *icookie, *rcookie; 378214478Srpaulo int ilen, rlen; 379214478Srpaulo char *authkey; 380214478Srpaulo char *enckey; 381276788Sdelphij 382214478Srpaulo init = strsep(&line, " \t"); 383214478Srpaulo icookie = strsep(&line, " \t"); 384214478Srpaulo rcookie = strsep(&line, " \t"); 385214478Srpaulo authkey = strsep(&line, " \t"); 386214478Srpaulo enckey = strsep(&line, " \t"); 387276788Sdelphij 388214478Srpaulo /* if any fields are missing */ 389214478Srpaulo if(!init || !icookie || !rcookie || !authkey || !enckey) { 390214478Srpaulo (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u", 391214478Srpaulo file, lineno); 392276788Sdelphij 393214478Srpaulo return; 394214478Srpaulo } 395276788Sdelphij 396214478Srpaulo ilen = strlen(icookie); 397214478Srpaulo rlen = strlen(rcookie); 398214478Srpaulo 399214478Srpaulo if((init[0]!='I' && init[0]!='R') 400214478Srpaulo || icookie[0]!='0' || icookie[1]!='x' 401214478Srpaulo || rcookie[0]!='0' || rcookie[1]!='x' 402214478Srpaulo || ilen!=18 403214478Srpaulo || rlen!=18) { 404214478Srpaulo (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.", 405214478Srpaulo file, lineno); 406214478Srpaulo 407214478Srpaulo (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)", 408214478Srpaulo init, icookie, ilen, rcookie, rlen); 409276788Sdelphij 410214478Srpaulo return; 411214478Srpaulo } 412214478Srpaulo 413214478Srpaulo sa1.spi = 0; 414214478Srpaulo sa1.initiator = (init[0] == 'I'); 415214478Srpaulo if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8) 416214478Srpaulo return; 417214478Srpaulo 418214478Srpaulo if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8) 419214478Srpaulo return; 420214478Srpaulo 421214478Srpaulo if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return; 422214478Srpaulo 423214478Srpaulo if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return; 424276788Sdelphij 425214478Srpaulo esp_print_addsa(ndo, &sa1, FALSE); 426214478Srpaulo} 427214478Srpaulo 428214478Srpaulo/* 429127668Sbms * 430127668Sbms * special form: file /name 431127668Sbms * causes us to go read from this file instead. 432127668Sbms * 433127668Sbms */ 434214478Srpaulostatic void esp_print_decode_onesecret(netdissect_options *ndo, char *line, 435214478Srpaulo const char *file, int lineno) 43698524Sfenner{ 437127668Sbms struct sa_list sa1; 438127668Sbms int sa_def; 43998524Sfenner 440127668Sbms char *spikey; 441127668Sbms char *decode; 44298524Sfenner 443127668Sbms spikey = strsep(&line, " \t"); 444127668Sbms sa_def = 0; 445127668Sbms memset(&sa1, 0, sizeof(struct sa_list)); 446127668Sbms 447127668Sbms /* if there is only one token, then it is an algo:key token */ 448127668Sbms if (line == NULL) { 449127668Sbms decode = spikey; 450127668Sbms spikey = NULL; 451276788Sdelphij /* sa1.daddr.version = 0; */ 452127668Sbms /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 453127668Sbms /* sa1.spi = 0; */ 454127668Sbms sa_def = 1; 455127668Sbms } else 456127668Sbms decode = line; 457127668Sbms 458313537Sglebius if (spikey && ascii_strcasecmp(spikey, "file") == 0) { 459127668Sbms /* open file and read it */ 460127668Sbms FILE *secretfile; 461127668Sbms char fileline[1024]; 462313537Sglebius int subfile_lineno=0; 463127668Sbms char *nl; 464214478Srpaulo char *filename = line; 465127668Sbms 466214478Srpaulo secretfile = fopen(filename, FOPEN_READ_TXT); 467127668Sbms if (secretfile == NULL) { 468313537Sglebius (*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n", 469313537Sglebius filename, strerror(errno)); 470313537Sglebius return; 471127668Sbms } 472127668Sbms 473127668Sbms while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 474313537Sglebius subfile_lineno++; 475127668Sbms /* remove newline from the line */ 476127668Sbms nl = strchr(fileline, '\n'); 477127668Sbms if (nl) 478127668Sbms *nl = '\0'; 479127668Sbms if (fileline[0] == '#') continue; 480127668Sbms if (fileline[0] == '\0') continue; 481127668Sbms 482313537Sglebius esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno); 483127668Sbms } 484127668Sbms fclose(secretfile); 485127668Sbms 48698524Sfenner return; 48798524Sfenner } 48898524Sfenner 489313537Sglebius if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) { 490214478Srpaulo esp_print_decode_ikeline(ndo, line, file, lineno); 491214478Srpaulo return; 492276788Sdelphij } 493214478Srpaulo 494127668Sbms if (spikey) { 495276788Sdelphij 496127668Sbms char *spistr, *foo; 497276788Sdelphij uint32_t spino; 498276788Sdelphij 499127668Sbms spistr = strsep(&spikey, "@"); 500276788Sdelphij 501127668Sbms spino = strtoul(spistr, &foo, 0); 502127668Sbms if (spistr == foo || !spikey) { 503146773Ssam (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo); 504127668Sbms return; 505127668Sbms } 506276788Sdelphij 507127668Sbms sa1.spi = spino; 508276788Sdelphij 509313537Sglebius if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) { 510276788Sdelphij sa1.daddr_version = 6; 511313537Sglebius } else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) { 512313537Sglebius sa1.daddr_version = 4; 513313537Sglebius } else { 514313537Sglebius (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey); 515313537Sglebius return; 516313537Sglebius } 51798524Sfenner } 51898524Sfenner 519127668Sbms if (decode) { 520127668Sbms /* skip any blank spaces */ 521127668Sbms while (isspace((unsigned char)*decode)) 522127668Sbms decode++; 523276788Sdelphij 524214478Srpaulo if(!espprint_decode_encalgo(ndo, decode, &sa1)) { 525127668Sbms return; 52698524Sfenner } 52798524Sfenner } 528127668Sbms 529146773Ssam esp_print_addsa(ndo, &sa1, sa_def); 53098524Sfenner} 53198524Sfenner 532276788SdelphijUSES_APPLE_DEPRECATED_API 533214478Srpaulostatic void esp_init(netdissect_options *ndo _U_) 534127668Sbms{ 535313537Sglebius /* 536313537Sglebius * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so 537313537Sglebius * we check whether it's undefined or it's less than the 538313537Sglebius * value for 1.1.0. 539313537Sglebius */ 540313537Sglebius#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L 541214478Srpaulo OpenSSL_add_all_algorithms(); 542313537Sglebius#endif 543214478Srpaulo EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 544214478Srpaulo} 545276788SdelphijUSES_APPLE_RST 546214478Srpaulo 547214478Srpaulovoid esp_print_decodesecret(netdissect_options *ndo) 548214478Srpaulo{ 549127668Sbms char *line; 550127668Sbms char *p; 551214478Srpaulo static int initialized = 0; 552127668Sbms 553214478Srpaulo if (!initialized) { 554214478Srpaulo esp_init(ndo); 555214478Srpaulo initialized = 1; 556214478Srpaulo } 557214478Srpaulo 558146773Ssam p = ndo->ndo_espsecret; 559127668Sbms 560214478Srpaulo while (p && p[0] != '\0') { 561127668Sbms /* pick out the first line or first thing until a comma */ 562214478Srpaulo if ((line = strsep(&p, "\n,")) == NULL) { 563214478Srpaulo line = p; 564214478Srpaulo p = NULL; 565127668Sbms } 566127668Sbms 567214478Srpaulo esp_print_decode_onesecret(ndo, line, "cmdline", 0); 568127668Sbms } 569214478Srpaulo 570214478Srpaulo ndo->ndo_espsecret = NULL; 571127668Sbms} 572127668Sbms 573127668Sbms#endif 574127668Sbms 575276788Sdelphij#ifdef HAVE_LIBCRYPTO 576276788SdelphijUSES_APPLE_DEPRECATED_API 577276788Sdelphij#endif 57856893Sfennerint 579146773Ssamesp_print(netdissect_options *ndo, 580146773Ssam const u_char *bp, const int length, const u_char *bp2 581127668Sbms#ifndef HAVE_LIBCRYPTO 582127668Sbms _U_ 583127668Sbms#endif 584127668Sbms , 585127668Sbms int *nhdr 586127668Sbms#ifndef HAVE_LIBCRYPTO 587127668Sbms _U_ 588127668Sbms#endif 589127668Sbms , 590127668Sbms int *padlen 591127668Sbms#ifndef HAVE_LIBCRYPTO 592127668Sbms _U_ 593127668Sbms#endif 594127668Sbms ) 59556893Sfenner{ 596127668Sbms register const struct newesp *esp; 59756893Sfenner register const u_char *ep; 598127668Sbms#ifdef HAVE_LIBCRYPTO 599313537Sglebius const struct ip *ip; 600127668Sbms struct sa_list *sa = NULL; 601313537Sglebius const struct ip6_hdr *ip6 = NULL; 60256893Sfenner int advance; 60356893Sfenner int len; 604147899Ssam u_char *secret; 60556893Sfenner int ivlen = 0; 606313537Sglebius const u_char *ivoff; 607313537Sglebius const u_char *p; 608313537Sglebius EVP_CIPHER_CTX *ctx; 609127668Sbms#endif 610127668Sbms 611313537Sglebius esp = (const struct newesp *)bp; 612127668Sbms 613127668Sbms#ifdef HAVE_LIBCRYPTO 61498524Sfenner secret = NULL; 615127668Sbms advance = 0; 616127668Sbms#endif 617127668Sbms 61898524Sfenner#if 0 61998524Sfenner /* keep secret out of a register */ 62098524Sfenner p = (u_char *)&secret; 62198524Sfenner#endif 62298524Sfenner 62375115Sfenner /* 'ep' points to the end of available data. */ 624146773Ssam ep = ndo->ndo_snapend; 62556893Sfenner 626313537Sglebius if ((const u_char *)(esp + 1) >= ep) { 627276788Sdelphij ND_PRINT((ndo, "[|ESP]")); 62856893Sfenner goto fail; 62956893Sfenner } 630276788Sdelphij ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi))); 631276788Sdelphij ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq))); 632276788Sdelphij ND_PRINT((ndo, ", length %u", length)); 63356893Sfenner 634127668Sbms#ifndef HAVE_LIBCRYPTO 635127668Sbms goto fail; 636127668Sbms#else 637127668Sbms /* initiailize SAs */ 638146773Ssam if (ndo->ndo_sa_list_head == NULL) { 639146773Ssam if (!ndo->ndo_espsecret) 640127668Sbms goto fail; 64156893Sfenner 642146773Ssam esp_print_decodesecret(ndo); 64356893Sfenner } 644127668Sbms 645146773Ssam if (ndo->ndo_sa_list_head == NULL) 64698524Sfenner goto fail; 64756893Sfenner 648313537Sglebius ip = (const struct ip *)bp2; 64975115Sfenner switch (IP_V(ip)) { 65056893Sfenner case 6: 651313537Sglebius ip6 = (const struct ip6_hdr *)bp2; 65256893Sfenner /* we do not attempt to decrypt jumbograms */ 653127668Sbms if (!EXTRACT_16BITS(&ip6->ip6_plen)) 65456893Sfenner goto fail; 65556893Sfenner /* if we can't get nexthdr, we do not need to decrypt it */ 656127668Sbms len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 657127668Sbms 658127668Sbms /* see if we can find the SA, and if so, decode it */ 659146773Ssam for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 660214478Srpaulo if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 661276788Sdelphij sa->daddr_version == 6 && 662276788Sdelphij UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst, 663127668Sbms sizeof(struct in6_addr)) == 0) { 664127668Sbms break; 665127668Sbms } 666127668Sbms } 66756893Sfenner break; 66856893Sfenner case 4: 66998524Sfenner /* nexthdr & padding are in the last fragment */ 670127668Sbms if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 67198524Sfenner goto fail; 672127668Sbms len = EXTRACT_16BITS(&ip->ip_len); 673127668Sbms 674127668Sbms /* see if we can find the SA, and if so, decode it */ 675146773Ssam for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 676214478Srpaulo if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 677276788Sdelphij sa->daddr_version == 4 && 678276788Sdelphij UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst, 679276788Sdelphij sizeof(struct in_addr)) == 0) { 680127668Sbms break; 681127668Sbms } 682127668Sbms } 68356893Sfenner break; 68456893Sfenner default: 68556893Sfenner goto fail; 68656893Sfenner } 68756893Sfenner 688127668Sbms /* if we didn't find the specific one, then look for 689127668Sbms * an unspecified one. 690127668Sbms */ 691127668Sbms if (sa == NULL) 692146773Ssam sa = ndo->ndo_sa_default; 693276788Sdelphij 694127668Sbms /* if not found fail */ 695127668Sbms if (sa == NULL) 696127668Sbms goto fail; 697127668Sbms 69856893Sfenner /* if we can't get nexthdr, we do not need to decrypt it */ 69956893Sfenner if (ep - bp2 < len) 70056893Sfenner goto fail; 701127668Sbms if (ep - bp2 > len) { 702127668Sbms /* FCS included at end of frame (NetBSD 1.6 or later) */ 703127668Sbms ep = bp2 + len; 704127668Sbms } 70556893Sfenner 706313537Sglebius ivoff = (const u_char *)(esp + 1) + 0; 707127668Sbms ivlen = sa->ivlen; 708127668Sbms secret = sa->secret; 709146773Ssam ep = ep - sa->authlen; 71056893Sfenner 711127668Sbms if (sa->evp) { 712313537Sglebius ctx = EVP_CIPHER_CTX_new(); 713313537Sglebius if (ctx != NULL) { 714313537Sglebius if (EVP_CipherInit(ctx, sa->evp, secret, NULL, 0) < 0) 715313537Sglebius (*ndo->ndo_warning)(ndo, "espkey init failed"); 71656893Sfenner 717313537Sglebius p = ivoff; 718313537Sglebius EVP_CipherInit(ctx, NULL, NULL, p, 0); 719313537Sglebius EVP_Cipher(ctx, __DECONST(u_char *, p + ivlen), 720313537Sglebius p + ivlen, ep - (p + ivlen)); 721313537Sglebius EVP_CIPHER_CTX_free(ctx); 722313537Sglebius advance = ivoff - (const u_char *)esp + ivlen; 723313537Sglebius } else 724313537Sglebius advance = sizeof(struct newesp); 725127668Sbms } else 726127668Sbms advance = sizeof(struct newesp); 72756893Sfenner 72856893Sfenner /* sanity check for pad length */ 72956893Sfenner if (ep - bp < *(ep - 2)) 73056893Sfenner goto fail; 73156893Sfenner 73298524Sfenner if (padlen) 73398524Sfenner *padlen = *(ep - 2) + 2; 73498524Sfenner 73556893Sfenner if (nhdr) 73656893Sfenner *nhdr = *(ep - 1); 73756893Sfenner 738276788Sdelphij ND_PRINT((ndo, ": ")); 73956893Sfenner return advance; 740127668Sbms#endif 74156893Sfenner 74256893Sfennerfail: 743127668Sbms return -1; 74456893Sfenner} 745276788Sdelphij#ifdef HAVE_LIBCRYPTO 746276788SdelphijUSES_APPLE_RST 747276788Sdelphij#endif 748146773Ssam 749146773Ssam/* 750146773Ssam * Local Variables: 751146773Ssam * c-style: whitesmith 752146773Ssam * c-basic-offset: 8 753146773Ssam * End: 754146773Ssam */ 755