1b0453382SBill Fenner /* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */ 2b0453382SBill Fenner 3b0453382SBill Fenner /* 4b0453382SBill Fenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 5b0453382SBill Fenner * The Regents of the University of California. All rights reserved. 6b0453382SBill Fenner * 7b0453382SBill Fenner * Redistribution and use in source and binary forms, with or without 8b0453382SBill Fenner * modification, are permitted provided that: (1) source code distributions 9b0453382SBill Fenner * retain the above copyright notice and this paragraph in its entirety, (2) 10b0453382SBill Fenner * distributions including binary code include the above copyright notice and 11b0453382SBill Fenner * this paragraph in its entirety in the documentation or other materials 12b0453382SBill Fenner * provided with the distribution, and (3) all advertising materials mentioning 13b0453382SBill Fenner * features or use of this software display the following acknowledgement: 14b0453382SBill Fenner * ``This product includes software developed by the University of California, 15b0453382SBill Fenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16b0453382SBill Fenner * the University nor the names of its contributors may be used to endorse 17b0453382SBill Fenner * or promote products derived from this software without specific prior 18b0453382SBill Fenner * written permission. 19b0453382SBill Fenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20b0453382SBill Fenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21b0453382SBill Fenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22b0453382SBill Fenner */ 23b0453382SBill Fenner 24b0453382SBill Fenner #ifndef lint 255b0fe478SBruce M Simpson static const char rcsid[] _U_ = 26*27df3f5dSRui Paulo "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.58 2007-12-07 00:03:07 mcr Exp $ (LBL)"; 27b0453382SBill Fenner #endif 28b0453382SBill Fenner 29b0453382SBill Fenner #ifdef HAVE_CONFIG_H 30b0453382SBill Fenner #include "config.h" 31b0453382SBill Fenner #endif 32b0453382SBill Fenner 33b0453382SBill Fenner #include <string.h> 345b0fe478SBruce M Simpson 355b0fe478SBruce M Simpson #include <tcpdump-stdinc.h> 365b0fe478SBruce M Simpson 379afd0c29SBill Fenner #include <stdlib.h> 38b0453382SBill Fenner 39685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO 405b0fe478SBruce M Simpson #ifdef HAVE_OPENSSL_EVP_H 415b0fe478SBruce M Simpson #include <openssl/evp.h> 42b0453382SBill Fenner #endif 43b0453382SBill Fenner #endif 44b0453382SBill Fenner 45b0453382SBill Fenner #include <stdio.h> 46b0453382SBill Fenner 47685295f4SBill Fenner #include "ip.h" 48685295f4SBill Fenner #include "esp.h" 49b0453382SBill Fenner #ifdef INET6 50685295f4SBill Fenner #include "ip6.h" 51b0453382SBill Fenner #endif 52b0453382SBill Fenner 531de50e9fSSam Leffler #include "netdissect.h" 54b0453382SBill Fenner #include "addrtoname.h" 555b0fe478SBruce M Simpson #include "extract.h" 56b0453382SBill Fenner 575b0fe478SBruce M Simpson #ifndef HAVE_SOCKADDR_STORAGE 585b0fe478SBruce M Simpson #ifdef INET6 595b0fe478SBruce M Simpson struct sockaddr_storage { 605b0fe478SBruce M Simpson union { 615b0fe478SBruce M Simpson struct sockaddr_in sin; 625b0fe478SBruce M Simpson struct sockaddr_in6 sin6; 635b0fe478SBruce M Simpson } un; 645b0fe478SBruce M Simpson }; 655b0fe478SBruce M Simpson #else 665b0fe478SBruce M Simpson #define sockaddr_storage sockaddr 675b0fe478SBruce M Simpson #endif 685b0fe478SBruce M Simpson #endif /* HAVE_SOCKADDR_STORAGE */ 69a90e161bSBill Fenner 705b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 715b0fe478SBruce M Simpson struct sa_list { 725b0fe478SBruce M Simpson struct sa_list *next; 735b0fe478SBruce M Simpson struct sockaddr_storage daddr; 74*27df3f5dSRui Paulo u_int32_t spi; /* if == 0, then IKEv2 */ 75*27df3f5dSRui Paulo int initiator; 76*27df3f5dSRui Paulo u_char spii[8]; /* for IKEv2 */ 77*27df3f5dSRui Paulo u_char spir[8]; 785b0fe478SBruce M Simpson const EVP_CIPHER *evp; 79a90e161bSBill Fenner int ivlen; 80a90e161bSBill Fenner int authlen; 81*27df3f5dSRui Paulo u_char authsecret[256]; 82*27df3f5dSRui Paulo int authsecret_len; 83f4d0c64aSSam Leffler u_char secret[256]; /* is that big enough for all secrets? */ 845b0fe478SBruce M Simpson int secretlen; 85a90e161bSBill Fenner }; 86a90e161bSBill Fenner 87*27df3f5dSRui Paulo /* 88*27df3f5dSRui Paulo * this will adjust ndo_packetp and ndo_snapend to new buffer! 89*27df3f5dSRui Paulo */ 90*27df3f5dSRui Paulo int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, 91*27df3f5dSRui Paulo int initiator, 92*27df3f5dSRui Paulo u_char spii[8], u_char spir[8], 93*27df3f5dSRui Paulo u_char *buf, u_char *end) 94*27df3f5dSRui Paulo { 95*27df3f5dSRui Paulo struct sa_list *sa; 96*27df3f5dSRui Paulo u_char *iv; 97*27df3f5dSRui Paulo int len; 98*27df3f5dSRui Paulo EVP_CIPHER_CTX ctx; 99*27df3f5dSRui Paulo 100*27df3f5dSRui Paulo /* initiator arg is any non-zero value */ 101*27df3f5dSRui Paulo if(initiator) initiator=1; 102*27df3f5dSRui Paulo 103*27df3f5dSRui Paulo /* see if we can find the SA, and if so, decode it */ 104*27df3f5dSRui Paulo for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 105*27df3f5dSRui Paulo if (sa->spi == 0 106*27df3f5dSRui Paulo && initiator == sa->initiator 107*27df3f5dSRui Paulo && memcmp(spii, sa->spii, 8) == 0 108*27df3f5dSRui Paulo && memcmp(spir, sa->spir, 8) == 0) 109*27df3f5dSRui Paulo break; 110*27df3f5dSRui Paulo } 111*27df3f5dSRui Paulo 112*27df3f5dSRui Paulo if(sa == NULL) return 0; 113*27df3f5dSRui Paulo if(sa->evp == NULL) return 0; 114*27df3f5dSRui Paulo 115*27df3f5dSRui Paulo /* 116*27df3f5dSRui Paulo * remove authenticator, and see if we still have something to 117*27df3f5dSRui Paulo * work with 118*27df3f5dSRui Paulo */ 119*27df3f5dSRui Paulo end = end - sa->authlen; 120*27df3f5dSRui Paulo iv = buf; 121*27df3f5dSRui Paulo buf = buf + sa->ivlen; 122*27df3f5dSRui Paulo len = end-buf; 123*27df3f5dSRui Paulo 124*27df3f5dSRui Paulo if(end <= buf) return 0; 125*27df3f5dSRui Paulo 126*27df3f5dSRui Paulo memset(&ctx, 0, sizeof(ctx)); 127*27df3f5dSRui Paulo if (EVP_CipherInit(&ctx, sa->evp, sa->secret, NULL, 0) < 0) 128*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "espkey init failed"); 129*27df3f5dSRui Paulo EVP_CipherInit(&ctx, NULL, NULL, iv, 0); 130*27df3f5dSRui Paulo EVP_Cipher(&ctx, buf, buf, len); 131*27df3f5dSRui Paulo EVP_CIPHER_CTX_cleanup(&ctx); 132*27df3f5dSRui Paulo 133*27df3f5dSRui Paulo ndo->ndo_packetp = buf; 134*27df3f5dSRui Paulo ndo->ndo_snapend = end; 135*27df3f5dSRui Paulo 136*27df3f5dSRui Paulo return 1; 137*27df3f5dSRui Paulo 138*27df3f5dSRui Paulo } 139*27df3f5dSRui Paulo 1401de50e9fSSam Leffler static void esp_print_addsa(netdissect_options *ndo, 1411de50e9fSSam Leffler struct sa_list *sa, int sa_def) 1425b0fe478SBruce M Simpson { 1435b0fe478SBruce M Simpson /* copy the "sa" */ 1445b0fe478SBruce M Simpson 1455b0fe478SBruce M Simpson struct sa_list *nsa; 1465b0fe478SBruce M Simpson 1475b0fe478SBruce M Simpson nsa = (struct sa_list *)malloc(sizeof(struct sa_list)); 1485b0fe478SBruce M Simpson if (nsa == NULL) 1491de50e9fSSam Leffler (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure"); 1505b0fe478SBruce M Simpson 1515b0fe478SBruce M Simpson *nsa = *sa; 1525b0fe478SBruce M Simpson 1535b0fe478SBruce M Simpson if (sa_def) 1541de50e9fSSam Leffler ndo->ndo_sa_default = nsa; 1555b0fe478SBruce M Simpson 1561de50e9fSSam Leffler nsa->next = ndo->ndo_sa_list_head; 1571de50e9fSSam Leffler ndo->ndo_sa_list_head = nsa; 1585b0fe478SBruce M Simpson } 1595b0fe478SBruce M Simpson 160a90e161bSBill Fenner 161f4d0c64aSSam Leffler static u_int hexdigit(netdissect_options *ndo, char hex) 162a90e161bSBill Fenner { 1635b0fe478SBruce M Simpson if (hex >= '0' && hex <= '9') 164a90e161bSBill Fenner return (hex - '0'); 1655b0fe478SBruce M Simpson else if (hex >= 'A' && hex <= 'F') 166a90e161bSBill Fenner return (hex - 'A' + 10); 1675b0fe478SBruce M Simpson else if (hex >= 'a' && hex <= 'f') 168a90e161bSBill Fenner return (hex - 'a' + 10); 1695b0fe478SBruce M Simpson else { 1701de50e9fSSam Leffler (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex); 171a90e161bSBill Fenner return 0; 172a90e161bSBill Fenner } 173a90e161bSBill Fenner } 174a90e161bSBill Fenner 175f4d0c64aSSam Leffler static u_int hex2byte(netdissect_options *ndo, char *hexstring) 176a90e161bSBill Fenner { 177f4d0c64aSSam Leffler u_int byte; 178a90e161bSBill Fenner 1791de50e9fSSam Leffler byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]); 180a90e161bSBill Fenner return byte; 181a90e161bSBill Fenner } 182a90e161bSBill Fenner 1835b0fe478SBruce M Simpson /* 184*27df3f5dSRui Paulo * returns size of binary, 0 on failure. 185*27df3f5dSRui Paulo */ 186*27df3f5dSRui Paulo static 187*27df3f5dSRui Paulo int espprint_decode_hex(netdissect_options *ndo, 188*27df3f5dSRui Paulo u_char *binbuf, unsigned int binbuf_len, 189*27df3f5dSRui Paulo char *hex) 190*27df3f5dSRui Paulo { 191*27df3f5dSRui Paulo unsigned int len; 192*27df3f5dSRui Paulo int i; 193*27df3f5dSRui Paulo 194*27df3f5dSRui Paulo len = strlen(hex) / 2; 195*27df3f5dSRui Paulo 196*27df3f5dSRui Paulo if (len > binbuf_len) { 197*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len); 198*27df3f5dSRui Paulo return 0; 199*27df3f5dSRui Paulo } 200*27df3f5dSRui Paulo 201*27df3f5dSRui Paulo i = 0; 202*27df3f5dSRui Paulo while (hex[0] != '\0' && hex[1]!='\0') { 203*27df3f5dSRui Paulo binbuf[i] = hex2byte(ndo, hex); 204*27df3f5dSRui Paulo hex += 2; 205*27df3f5dSRui Paulo i++; 206*27df3f5dSRui Paulo } 207*27df3f5dSRui Paulo 208*27df3f5dSRui Paulo return i; 209*27df3f5dSRui Paulo } 210*27df3f5dSRui Paulo 211*27df3f5dSRui Paulo /* 2125b0fe478SBruce M Simpson * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret 213*27df3f5dSRui Paulo */ 214*27df3f5dSRui Paulo 215*27df3f5dSRui Paulo static int 216*27df3f5dSRui Paulo espprint_decode_encalgo(netdissect_options *ndo, 217*27df3f5dSRui Paulo char *decode, struct sa_list *sa) 218*27df3f5dSRui Paulo { 219*27df3f5dSRui Paulo int len; 220*27df3f5dSRui Paulo size_t i; 221*27df3f5dSRui Paulo const EVP_CIPHER *evp; 222*27df3f5dSRui Paulo int authlen = 0; 223*27df3f5dSRui Paulo char *colon, *p; 224*27df3f5dSRui Paulo 225*27df3f5dSRui Paulo colon = strchr(decode, ':'); 226*27df3f5dSRui Paulo if (colon == NULL) { 227*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 228*27df3f5dSRui Paulo return 0; 229*27df3f5dSRui Paulo } 230*27df3f5dSRui Paulo *colon = '\0'; 231*27df3f5dSRui Paulo 232*27df3f5dSRui Paulo len = colon - decode; 233*27df3f5dSRui Paulo if (strlen(decode) > strlen("-hmac96") && 234*27df3f5dSRui Paulo !strcmp(decode + strlen(decode) - strlen("-hmac96"), 235*27df3f5dSRui Paulo "-hmac96")) { 236*27df3f5dSRui Paulo p = strstr(decode, "-hmac96"); 237*27df3f5dSRui Paulo *p = '\0'; 238*27df3f5dSRui Paulo authlen = 12; 239*27df3f5dSRui Paulo } 240*27df3f5dSRui Paulo if (strlen(decode) > strlen("-cbc") && 241*27df3f5dSRui Paulo !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 242*27df3f5dSRui Paulo p = strstr(decode, "-cbc"); 243*27df3f5dSRui Paulo *p = '\0'; 244*27df3f5dSRui Paulo } 245*27df3f5dSRui Paulo evp = EVP_get_cipherbyname(decode); 246*27df3f5dSRui Paulo 247*27df3f5dSRui Paulo if (!evp) { 248*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode); 249*27df3f5dSRui Paulo sa->evp = NULL; 250*27df3f5dSRui Paulo sa->authlen = 0; 251*27df3f5dSRui Paulo sa->ivlen = 0; 252*27df3f5dSRui Paulo return 0; 253*27df3f5dSRui Paulo } 254*27df3f5dSRui Paulo 255*27df3f5dSRui Paulo sa->evp = evp; 256*27df3f5dSRui Paulo sa->authlen = authlen; 257*27df3f5dSRui Paulo sa->ivlen = EVP_CIPHER_iv_length(evp); 258*27df3f5dSRui Paulo 259*27df3f5dSRui Paulo colon++; 260*27df3f5dSRui Paulo if (colon[0] == '0' && colon[1] == 'x') { 261*27df3f5dSRui Paulo /* decode some hex! */ 262*27df3f5dSRui Paulo 263*27df3f5dSRui Paulo colon += 2; 264*27df3f5dSRui Paulo sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon); 265*27df3f5dSRui Paulo if(sa->secretlen == 0) return 0; 266*27df3f5dSRui Paulo } else { 267*27df3f5dSRui Paulo i = strlen(colon); 268*27df3f5dSRui Paulo 269*27df3f5dSRui Paulo if (i < sizeof(sa->secret)) { 270*27df3f5dSRui Paulo memcpy(sa->secret, colon, i); 271*27df3f5dSRui Paulo sa->secretlen = i; 272*27df3f5dSRui Paulo } else { 273*27df3f5dSRui Paulo memcpy(sa->secret, colon, sizeof(sa->secret)); 274*27df3f5dSRui Paulo sa->secretlen = sizeof(sa->secret); 275*27df3f5dSRui Paulo } 276*27df3f5dSRui Paulo } 277*27df3f5dSRui Paulo 278*27df3f5dSRui Paulo return 1; 279*27df3f5dSRui Paulo } 280*27df3f5dSRui Paulo 281*27df3f5dSRui Paulo /* 282*27df3f5dSRui Paulo * for the moment, ignore the auth algorith, just hard code the authenticator 283*27df3f5dSRui Paulo * length. Need to research how openssl looks up HMAC stuff. 284*27df3f5dSRui Paulo */ 285*27df3f5dSRui Paulo static int 286*27df3f5dSRui Paulo espprint_decode_authalgo(netdissect_options *ndo, 287*27df3f5dSRui Paulo char *decode, struct sa_list *sa) 288*27df3f5dSRui Paulo { 289*27df3f5dSRui Paulo char *colon; 290*27df3f5dSRui Paulo 291*27df3f5dSRui Paulo colon = strchr(decode, ':'); 292*27df3f5dSRui Paulo if (colon == NULL) { 293*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 294*27df3f5dSRui Paulo return 0; 295*27df3f5dSRui Paulo } 296*27df3f5dSRui Paulo *colon = '\0'; 297*27df3f5dSRui Paulo 298*27df3f5dSRui Paulo if(strcasecmp(colon,"sha1") == 0 || 299*27df3f5dSRui Paulo strcasecmp(colon,"md5") == 0) { 300*27df3f5dSRui Paulo sa->authlen = 12; 301*27df3f5dSRui Paulo } 302*27df3f5dSRui Paulo return 1; 303*27df3f5dSRui Paulo } 304*27df3f5dSRui Paulo 305*27df3f5dSRui Paulo static void esp_print_decode_ikeline(netdissect_options *ndo, char *line, 306*27df3f5dSRui Paulo const char *file, int lineno) 307*27df3f5dSRui Paulo { 308*27df3f5dSRui Paulo /* it's an IKEv2 secret, store it instead */ 309*27df3f5dSRui Paulo struct sa_list sa1; 310*27df3f5dSRui Paulo 311*27df3f5dSRui Paulo char *init; 312*27df3f5dSRui Paulo char *icookie, *rcookie; 313*27df3f5dSRui Paulo int ilen, rlen; 314*27df3f5dSRui Paulo char *authkey; 315*27df3f5dSRui Paulo char *enckey; 316*27df3f5dSRui Paulo 317*27df3f5dSRui Paulo init = strsep(&line, " \t"); 318*27df3f5dSRui Paulo icookie = strsep(&line, " \t"); 319*27df3f5dSRui Paulo rcookie = strsep(&line, " \t"); 320*27df3f5dSRui Paulo authkey = strsep(&line, " \t"); 321*27df3f5dSRui Paulo enckey = strsep(&line, " \t"); 322*27df3f5dSRui Paulo 323*27df3f5dSRui Paulo /* if any fields are missing */ 324*27df3f5dSRui Paulo if(!init || !icookie || !rcookie || !authkey || !enckey) { 325*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u", 326*27df3f5dSRui Paulo file, lineno); 327*27df3f5dSRui Paulo 328*27df3f5dSRui Paulo return; 329*27df3f5dSRui Paulo } 330*27df3f5dSRui Paulo 331*27df3f5dSRui Paulo ilen = strlen(icookie); 332*27df3f5dSRui Paulo rlen = strlen(rcookie); 333*27df3f5dSRui Paulo 334*27df3f5dSRui Paulo if((init[0]!='I' && init[0]!='R') 335*27df3f5dSRui Paulo || icookie[0]!='0' || icookie[1]!='x' 336*27df3f5dSRui Paulo || rcookie[0]!='0' || rcookie[1]!='x' 337*27df3f5dSRui Paulo || ilen!=18 338*27df3f5dSRui Paulo || rlen!=18) { 339*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.", 340*27df3f5dSRui Paulo file, lineno); 341*27df3f5dSRui Paulo 342*27df3f5dSRui Paulo (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)", 343*27df3f5dSRui Paulo init, icookie, ilen, rcookie, rlen); 344*27df3f5dSRui Paulo 345*27df3f5dSRui Paulo return; 346*27df3f5dSRui Paulo } 347*27df3f5dSRui Paulo 348*27df3f5dSRui Paulo sa1.spi = 0; 349*27df3f5dSRui Paulo sa1.initiator = (init[0] == 'I'); 350*27df3f5dSRui Paulo if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8) 351*27df3f5dSRui Paulo return; 352*27df3f5dSRui Paulo 353*27df3f5dSRui Paulo if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8) 354*27df3f5dSRui Paulo return; 355*27df3f5dSRui Paulo 356*27df3f5dSRui Paulo if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return; 357*27df3f5dSRui Paulo 358*27df3f5dSRui Paulo if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return; 359*27df3f5dSRui Paulo 360*27df3f5dSRui Paulo esp_print_addsa(ndo, &sa1, FALSE); 361*27df3f5dSRui Paulo } 362*27df3f5dSRui Paulo 363*27df3f5dSRui Paulo /* 3645b0fe478SBruce M Simpson * 3655b0fe478SBruce M Simpson * special form: file /name 3665b0fe478SBruce M Simpson * causes us to go read from this file instead. 3675b0fe478SBruce M Simpson * 3685b0fe478SBruce M Simpson */ 369*27df3f5dSRui Paulo static void esp_print_decode_onesecret(netdissect_options *ndo, char *line, 370*27df3f5dSRui Paulo const char *file, int lineno) 371a90e161bSBill Fenner { 3725b0fe478SBruce M Simpson struct sa_list sa1; 3735b0fe478SBruce M Simpson int sa_def; 374a90e161bSBill Fenner 3755b0fe478SBruce M Simpson char *spikey; 3765b0fe478SBruce M Simpson char *decode; 3775b0fe478SBruce M Simpson 3785b0fe478SBruce M Simpson spikey = strsep(&line, " \t"); 3795b0fe478SBruce M Simpson sa_def = 0; 3805b0fe478SBruce M Simpson memset(&sa1, 0, sizeof(struct sa_list)); 3815b0fe478SBruce M Simpson 3825b0fe478SBruce M Simpson /* if there is only one token, then it is an algo:key token */ 3835b0fe478SBruce M Simpson if (line == NULL) { 3845b0fe478SBruce M Simpson decode = spikey; 3855b0fe478SBruce M Simpson spikey = NULL; 3865b0fe478SBruce M Simpson /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 3875b0fe478SBruce M Simpson /* sa1.spi = 0; */ 3885b0fe478SBruce M Simpson sa_def = 1; 3895b0fe478SBruce M Simpson } else 3905b0fe478SBruce M Simpson decode = line; 3915b0fe478SBruce M Simpson 3925b0fe478SBruce M Simpson if (spikey && strcasecmp(spikey, "file") == 0) { 3935b0fe478SBruce M Simpson /* open file and read it */ 3945b0fe478SBruce M Simpson FILE *secretfile; 3955b0fe478SBruce M Simpson char fileline[1024]; 396*27df3f5dSRui Paulo int lineno=0; 3975b0fe478SBruce M Simpson char *nl; 398*27df3f5dSRui Paulo char *filename = line; 3995b0fe478SBruce M Simpson 400*27df3f5dSRui Paulo secretfile = fopen(filename, FOPEN_READ_TXT); 4015b0fe478SBruce M Simpson if (secretfile == NULL) { 402*27df3f5dSRui Paulo perror(filename); 4035b0fe478SBruce M Simpson exit(3); 4045b0fe478SBruce M Simpson } 4055b0fe478SBruce M Simpson 4065b0fe478SBruce M Simpson while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 407*27df3f5dSRui Paulo lineno++; 4085b0fe478SBruce M Simpson /* remove newline from the line */ 4095b0fe478SBruce M Simpson nl = strchr(fileline, '\n'); 4105b0fe478SBruce M Simpson if (nl) 4115b0fe478SBruce M Simpson *nl = '\0'; 4125b0fe478SBruce M Simpson if (fileline[0] == '#') continue; 4135b0fe478SBruce M Simpson if (fileline[0] == '\0') continue; 4145b0fe478SBruce M Simpson 415*27df3f5dSRui Paulo esp_print_decode_onesecret(ndo, fileline, filename, lineno); 4165b0fe478SBruce M Simpson } 4175b0fe478SBruce M Simpson fclose(secretfile); 4185b0fe478SBruce M Simpson 419a90e161bSBill Fenner return; 420a90e161bSBill Fenner } 421a90e161bSBill Fenner 422*27df3f5dSRui Paulo if (spikey && strcasecmp(spikey, "ikev2") == 0) { 423*27df3f5dSRui Paulo esp_print_decode_ikeline(ndo, line, file, lineno); 424*27df3f5dSRui Paulo return; 425*27df3f5dSRui Paulo } 426*27df3f5dSRui Paulo 4275b0fe478SBruce M Simpson if (spikey) { 428*27df3f5dSRui Paulo 4295b0fe478SBruce M Simpson char *spistr, *foo; 4305b0fe478SBruce M Simpson u_int32_t spino; 4315b0fe478SBruce M Simpson struct sockaddr_in *sin; 4325b0fe478SBruce M Simpson #ifdef INET6 4335b0fe478SBruce M Simpson struct sockaddr_in6 *sin6; 4345b0fe478SBruce M Simpson #endif 4355b0fe478SBruce M Simpson 4365b0fe478SBruce M Simpson spistr = strsep(&spikey, "@"); 4375b0fe478SBruce M Simpson 4385b0fe478SBruce M Simpson spino = strtoul(spistr, &foo, 0); 4395b0fe478SBruce M Simpson if (spistr == foo || !spikey) { 4401de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo); 441a90e161bSBill Fenner return; 442a90e161bSBill Fenner } 443a90e161bSBill Fenner 4445b0fe478SBruce M Simpson sa1.spi = spino; 4455b0fe478SBruce M Simpson 4465b0fe478SBruce M Simpson sin = (struct sockaddr_in *)&sa1.daddr; 4475b0fe478SBruce M Simpson #ifdef INET6 4485b0fe478SBruce M Simpson sin6 = (struct sockaddr_in6 *)&sa1.daddr; 4495b0fe478SBruce M Simpson if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) { 4505b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN 4515b0fe478SBruce M Simpson sin6->sin6_len = sizeof(struct sockaddr_in6); 4525b0fe478SBruce M Simpson #endif 4535b0fe478SBruce M Simpson sin6->sin6_family = AF_INET6; 4545b0fe478SBruce M Simpson } else 4555b0fe478SBruce M Simpson #endif 4565b0fe478SBruce M Simpson if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) { 4575b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN 4585b0fe478SBruce M Simpson sin->sin_len = sizeof(struct sockaddr_in); 4595b0fe478SBruce M Simpson #endif 4605b0fe478SBruce M Simpson sin->sin_family = AF_INET; 4615b0fe478SBruce M Simpson } else { 4621de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey); 4635b0fe478SBruce M Simpson return; 4645b0fe478SBruce M Simpson } 4655b0fe478SBruce M Simpson } 4665b0fe478SBruce M Simpson 4675b0fe478SBruce M Simpson if (decode) { 4685b0fe478SBruce M Simpson /* skip any blank spaces */ 4695b0fe478SBruce M Simpson while (isspace((unsigned char)*decode)) 4705b0fe478SBruce M Simpson decode++; 4715b0fe478SBruce M Simpson 472*27df3f5dSRui Paulo if(!espprint_decode_encalgo(ndo, decode, &sa1)) { 473a90e161bSBill Fenner return; 474a90e161bSBill Fenner } 475a90e161bSBill Fenner } 476a90e161bSBill Fenner 4771de50e9fSSam Leffler esp_print_addsa(ndo, &sa1, sa_def); 4785b0fe478SBruce M Simpson } 4795b0fe478SBruce M Simpson 4801de50e9fSSam Leffler static void esp_init(netdissect_options *ndo _U_) 4815b0fe478SBruce M Simpson { 4825b0fe478SBruce M Simpson 4835b0fe478SBruce M Simpson OpenSSL_add_all_algorithms(); 4845b0fe478SBruce M Simpson EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 4855b0fe478SBruce M Simpson } 486*27df3f5dSRui Paulo 487*27df3f5dSRui Paulo void esp_print_decodesecret(netdissect_options *ndo) 488*27df3f5dSRui Paulo { 489*27df3f5dSRui Paulo char *line; 490*27df3f5dSRui Paulo char *p; 491*27df3f5dSRui Paulo static int initialized = 0; 492*27df3f5dSRui Paulo 493*27df3f5dSRui Paulo if (!initialized) { 494*27df3f5dSRui Paulo esp_init(ndo); 495*27df3f5dSRui Paulo initialized = 1; 496*27df3f5dSRui Paulo } 497*27df3f5dSRui Paulo 498*27df3f5dSRui Paulo p = ndo->ndo_espsecret; 499*27df3f5dSRui Paulo 500*27df3f5dSRui Paulo while (p && p[0] != '\0') { 501*27df3f5dSRui Paulo /* pick out the first line or first thing until a comma */ 502*27df3f5dSRui Paulo if ((line = strsep(&p, "\n,")) == NULL) { 503*27df3f5dSRui Paulo line = p; 504*27df3f5dSRui Paulo p = NULL; 505*27df3f5dSRui Paulo } 506*27df3f5dSRui Paulo 507*27df3f5dSRui Paulo esp_print_decode_onesecret(ndo, line, "cmdline", 0); 508*27df3f5dSRui Paulo } 509*27df3f5dSRui Paulo 510*27df3f5dSRui Paulo ndo->ndo_espsecret = NULL; 511*27df3f5dSRui Paulo } 512*27df3f5dSRui Paulo 5135b0fe478SBruce M Simpson #endif 5145b0fe478SBruce M Simpson 5155b0fe478SBruce M Simpson int 5161de50e9fSSam Leffler esp_print(netdissect_options *ndo, 5171de50e9fSSam Leffler const u_char *bp, const int length, const u_char *bp2 5185b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 5195b0fe478SBruce M Simpson _U_ 5205b0fe478SBruce M Simpson #endif 5215b0fe478SBruce M Simpson , 5225b0fe478SBruce M Simpson int *nhdr 5235b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 5245b0fe478SBruce M Simpson _U_ 5255b0fe478SBruce M Simpson #endif 5265b0fe478SBruce M Simpson , 5275b0fe478SBruce M Simpson int *padlen 5285b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 5295b0fe478SBruce M Simpson _U_ 5305b0fe478SBruce M Simpson #endif 5315b0fe478SBruce M Simpson ) 5325b0fe478SBruce M Simpson { 5335b0fe478SBruce M Simpson register const struct newesp *esp; 534b0453382SBill Fenner register const u_char *ep; 5355b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 5365b0fe478SBruce M Simpson struct ip *ip; 5375b0fe478SBruce M Simpson struct sa_list *sa = NULL; 5385b0fe478SBruce M Simpson int espsecret_keylen; 539b0453382SBill Fenner #ifdef INET6 540b0453382SBill Fenner struct ip6_hdr *ip6 = NULL; 541b0453382SBill Fenner #endif 542b0453382SBill Fenner int advance; 543b0453382SBill Fenner int len; 544f4d0c64aSSam Leffler u_char *secret; 545b0453382SBill Fenner int ivlen = 0; 546b0453382SBill Fenner u_char *ivoff; 5471de50e9fSSam Leffler u_char *p; 5485b0fe478SBruce M Simpson EVP_CIPHER_CTX ctx; 5495b0fe478SBruce M Simpson int blocksz; 5505b0fe478SBruce M Simpson #endif 551b0453382SBill Fenner 5525b0fe478SBruce M Simpson esp = (struct newesp *)bp; 5535b0fe478SBruce M Simpson 5545b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 555a90e161bSBill Fenner secret = NULL; 5565b0fe478SBruce M Simpson advance = 0; 5575b0fe478SBruce M Simpson #endif 558a90e161bSBill Fenner 559a90e161bSBill Fenner #if 0 560a90e161bSBill Fenner /* keep secret out of a register */ 561a90e161bSBill Fenner p = (u_char *)&secret; 562a90e161bSBill Fenner #endif 563b0453382SBill Fenner 564685295f4SBill Fenner /* 'ep' points to the end of available data. */ 5651de50e9fSSam Leffler ep = ndo->ndo_snapend; 566b0453382SBill Fenner 5675b0fe478SBruce M Simpson if ((u_char *)(esp + 1) >= ep) { 568b0453382SBill Fenner fputs("[|ESP]", stdout); 569b0453382SBill Fenner goto fail; 570b0453382SBill Fenner } 5711de50e9fSSam Leffler (*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)); 5721de50e9fSSam Leffler (*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)); 5731de50e9fSSam Leffler (*ndo->ndo_printf)(ndo, ", length %u", length); 574b0453382SBill Fenner 5755b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 5765b0fe478SBruce M Simpson goto fail; 5775b0fe478SBruce M Simpson #else 5785b0fe478SBruce M Simpson /* initiailize SAs */ 5791de50e9fSSam Leffler if (ndo->ndo_sa_list_head == NULL) { 5801de50e9fSSam Leffler if (!ndo->ndo_espsecret) 581b0453382SBill Fenner goto fail; 582b0453382SBill Fenner 5831de50e9fSSam Leffler esp_print_decodesecret(ndo); 584a90e161bSBill Fenner } 5855b0fe478SBruce M Simpson 5861de50e9fSSam Leffler if (ndo->ndo_sa_list_head == NULL) 587a90e161bSBill Fenner goto fail; 588b0453382SBill Fenner 589b0453382SBill Fenner ip = (struct ip *)bp2; 590685295f4SBill Fenner switch (IP_V(ip)) { 591b0453382SBill Fenner #ifdef INET6 592b0453382SBill Fenner case 6: 593b0453382SBill Fenner ip6 = (struct ip6_hdr *)bp2; 594b0453382SBill Fenner /* we do not attempt to decrypt jumbograms */ 5955b0fe478SBruce M Simpson if (!EXTRACT_16BITS(&ip6->ip6_plen)) 596b0453382SBill Fenner goto fail; 597b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 5985b0fe478SBruce M Simpson len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 5995b0fe478SBruce M Simpson 6005b0fe478SBruce M Simpson /* see if we can find the SA, and if so, decode it */ 6011de50e9fSSam Leffler for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 6025b0fe478SBruce M Simpson struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr; 603*27df3f5dSRui Paulo if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 6045b0fe478SBruce M Simpson sin6->sin6_family == AF_INET6 && 6055b0fe478SBruce M Simpson memcmp(&sin6->sin6_addr, &ip6->ip6_dst, 6065b0fe478SBruce M Simpson sizeof(struct in6_addr)) == 0) { 6075b0fe478SBruce M Simpson break; 6085b0fe478SBruce M Simpson } 6095b0fe478SBruce M Simpson } 610b0453382SBill Fenner break; 611b0453382SBill Fenner #endif /*INET6*/ 612b0453382SBill Fenner case 4: 613a90e161bSBill Fenner /* nexthdr & padding are in the last fragment */ 6145b0fe478SBruce M Simpson if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 615a90e161bSBill Fenner goto fail; 6165b0fe478SBruce M Simpson len = EXTRACT_16BITS(&ip->ip_len); 6175b0fe478SBruce M Simpson 6185b0fe478SBruce M Simpson /* see if we can find the SA, and if so, decode it */ 6191de50e9fSSam Leffler for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 6205b0fe478SBruce M Simpson struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr; 621*27df3f5dSRui Paulo if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 6225b0fe478SBruce M Simpson sin->sin_family == AF_INET && 6235b0fe478SBruce M Simpson sin->sin_addr.s_addr == ip->ip_dst.s_addr) { 6245b0fe478SBruce M Simpson break; 6255b0fe478SBruce M Simpson } 6265b0fe478SBruce M Simpson } 627b0453382SBill Fenner break; 628b0453382SBill Fenner default: 629b0453382SBill Fenner goto fail; 630b0453382SBill Fenner } 631b0453382SBill Fenner 6325b0fe478SBruce M Simpson /* if we didn't find the specific one, then look for 6335b0fe478SBruce M Simpson * an unspecified one. 6345b0fe478SBruce M Simpson */ 6355b0fe478SBruce M Simpson if (sa == NULL) 6361de50e9fSSam Leffler sa = ndo->ndo_sa_default; 6375b0fe478SBruce M Simpson 6385b0fe478SBruce M Simpson /* if not found fail */ 6395b0fe478SBruce M Simpson if (sa == NULL) 6405b0fe478SBruce M Simpson goto fail; 6415b0fe478SBruce M Simpson 642b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 643b0453382SBill Fenner if (ep - bp2 < len) 644b0453382SBill Fenner goto fail; 6455b0fe478SBruce M Simpson if (ep - bp2 > len) { 6465b0fe478SBruce M Simpson /* FCS included at end of frame (NetBSD 1.6 or later) */ 6475b0fe478SBruce M Simpson ep = bp2 + len; 648b0453382SBill Fenner } 649b0453382SBill Fenner 6505b0fe478SBruce M Simpson ivoff = (u_char *)(esp + 1) + 0; 6515b0fe478SBruce M Simpson ivlen = sa->ivlen; 6525b0fe478SBruce M Simpson secret = sa->secret; 6535b0fe478SBruce M Simpson espsecret_keylen = sa->secretlen; 6541de50e9fSSam Leffler ep = ep - sa->authlen; 655b0453382SBill Fenner 6565b0fe478SBruce M Simpson if (sa->evp) { 6575b0fe478SBruce M Simpson memset(&ctx, 0, sizeof(ctx)); 6585b0fe478SBruce M Simpson if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0) 6591de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "espkey init failed"); 6605b0fe478SBruce M Simpson 6615b0fe478SBruce M Simpson blocksz = EVP_CIPHER_CTX_block_size(&ctx); 6625b0fe478SBruce M Simpson 6635b0fe478SBruce M Simpson p = ivoff; 6645b0fe478SBruce M Simpson EVP_CipherInit(&ctx, NULL, NULL, p, 0); 6655b0fe478SBruce M Simpson EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); 666*27df3f5dSRui Paulo EVP_CIPHER_CTX_cleanup(&ctx); 667b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 6685b0fe478SBruce M Simpson } else 6695b0fe478SBruce M Simpson advance = sizeof(struct newesp); 670b0453382SBill Fenner 671b0453382SBill Fenner /* sanity check for pad length */ 672b0453382SBill Fenner if (ep - bp < *(ep - 2)) 673b0453382SBill Fenner goto fail; 674b0453382SBill Fenner 675a90e161bSBill Fenner if (padlen) 676a90e161bSBill Fenner *padlen = *(ep - 2) + 2; 677a90e161bSBill Fenner 678b0453382SBill Fenner if (nhdr) 679b0453382SBill Fenner *nhdr = *(ep - 1); 680b0453382SBill Fenner 6811de50e9fSSam Leffler (ndo->ndo_printf)(ndo, ": "); 682b0453382SBill Fenner return advance; 6835b0fe478SBruce M Simpson #endif 684b0453382SBill Fenner 685b0453382SBill Fenner fail: 6865b0fe478SBruce M Simpson return -1; 687b0453382SBill Fenner } 6881de50e9fSSam Leffler 6891de50e9fSSam Leffler /* 6901de50e9fSSam Leffler * Local Variables: 6911de50e9fSSam Leffler * c-style: whitesmith 6921de50e9fSSam Leffler * c-basic-offset: 8 6931de50e9fSSam Leffler * End: 6941de50e9fSSam Leffler */ 695