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 148327234Semaste#ifdef HAVE_EVP_CIPHERINIT_EX 149313537Sglebius/* 150327234Semaste * Initialize the cipher by calling EVP_CipherInit_ex(), because 151327234Semaste * calling EVP_CipherInit() will reset the cipher context, clearing 152327234Semaste * the cipher, so calling it twice, with the second call having a 153327234Semaste * null cipher, will clear the already-set cipher. EVP_CipherInit_ex(), 154327234Semaste * however, won't reset the cipher context, so you can use it to specify 155327234Semaste * the IV oin a second call after a first call to EVP_CipherInit_ex() 156327234Semaste * to set the cipher and the key. 157327234Semaste * 158327234Semaste * XXX - is there some reason why we need to make two calls? 159327234Semaste */ 160327234Semastestatic int 161327234Semasteset_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, 162327234Semaste const unsigned char *key, 163327234Semaste const unsigned char *iv, int enc) 164327234Semaste{ 165327234Semaste return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); 166327234Semaste} 167327234Semaste#else 168327234Semaste/* 169327234Semaste * Initialize the cipher by calling EVP_CipherInit(), because we don't 170327234Semaste * have EVP_CipherInit_ex(); we rely on it not trashing the context. 171327234Semaste */ 172327234Semastestatic int 173327234Semasteset_cipher_parameters(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, 174327234Semaste const unsigned char *key, 175327234Semaste const unsigned char *iv, int enc) 176327234Semaste{ 177327234Semaste return EVP_CipherInit(ctx, cipher, key, iv, enc); 178327234Semaste} 179327234Semaste#endif 180327234Semaste 181327234Semaste/* 182214478Srpaulo * this will adjust ndo_packetp and ndo_snapend to new buffer! 183214478Srpaulo */ 184276788SdelphijUSES_APPLE_DEPRECATED_API 185214478Srpauloint esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo, 186214478Srpaulo int initiator, 187214478Srpaulo u_char spii[8], u_char spir[8], 188313537Sglebius const u_char *buf, const u_char *end) 189214478Srpaulo{ 190214478Srpaulo struct sa_list *sa; 191313537Sglebius const u_char *iv; 192327234Semaste unsigned int len; 193313537Sglebius EVP_CIPHER_CTX *ctx; 194356341Scy unsigned int block_size, buffer_size; 195356341Scy u_char *input_buffer, *output_buffer; 196214478Srpaulo 197214478Srpaulo /* initiator arg is any non-zero value */ 198214478Srpaulo if(initiator) initiator=1; 199276788Sdelphij 200214478Srpaulo /* see if we can find the SA, and if so, decode it */ 201214478Srpaulo for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 202214478Srpaulo if (sa->spi == 0 203214478Srpaulo && initiator == sa->initiator 204214478Srpaulo && memcmp(spii, sa->spii, 8) == 0 205214478Srpaulo && memcmp(spir, sa->spir, 8) == 0) 206214478Srpaulo break; 207214478Srpaulo } 208214478Srpaulo 209214478Srpaulo if(sa == NULL) return 0; 210214478Srpaulo if(sa->evp == NULL) return 0; 211214478Srpaulo 212214478Srpaulo /* 213214478Srpaulo * remove authenticator, and see if we still have something to 214214478Srpaulo * work with 215214478Srpaulo */ 216214478Srpaulo end = end - sa->authlen; 217214478Srpaulo iv = buf; 218214478Srpaulo buf = buf + sa->ivlen; 219214478Srpaulo len = end-buf; 220214478Srpaulo 221214478Srpaulo if(end <= buf) return 0; 222214478Srpaulo 223313537Sglebius ctx = EVP_CIPHER_CTX_new(); 224313537Sglebius if (ctx == NULL) 225313537Sglebius return 0; 226327234Semaste if (set_cipher_parameters(ctx, sa->evp, sa->secret, NULL, 0) < 0) 227214478Srpaulo (*ndo->ndo_warning)(ndo, "espkey init failed"); 228327234Semaste set_cipher_parameters(ctx, NULL, NULL, iv, 0); 229327234Semaste /* 230356341Scy * Allocate buffers for the encrypted and decrypted data. 231356341Scy * Both buffers' sizes must be a multiple of the cipher block 232356341Scy * size, and the output buffer must be separate from the input 233356341Scy * buffer. 234327234Semaste */ 235327234Semaste block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx); 236356341Scy buffer_size = len + (block_size - len % block_size); 237356341Scy 238356341Scy /* 239356341Scy * Attempt to allocate the input buffer. 240356341Scy */ 241356341Scy input_buffer = (u_char *)malloc(buffer_size); 242356341Scy if (input_buffer == NULL) { 243356341Scy EVP_CIPHER_CTX_free(ctx); 244356341Scy (*ndo->ndo_error)(ndo, "can't allocate memory for encrypted data buffer"); 245356341Scy } 246356341Scy /* 247356341Scy * Copy the input data to the encrypted data buffer, and pad it 248356341Scy * with zeroes. 249356341Scy */ 250356341Scy memcpy(input_buffer, buf, len); 251356341Scy memset(input_buffer + len, 0, buffer_size - len); 252356341Scy 253356341Scy /* 254356341Scy * Attempt to allocate the output buffer. 255356341Scy */ 256356341Scy output_buffer = (u_char *)malloc(buffer_size); 257327234Semaste if (output_buffer == NULL) { 258356341Scy free(input_buffer); 259327234Semaste EVP_CIPHER_CTX_free(ctx); 260356341Scy (*ndo->ndo_error)(ndo, "can't allocate memory for decryption buffer"); 261327234Semaste } 262356341Scy EVP_Cipher(ctx, output_buffer, input_buffer, len); 263313537Sglebius EVP_CIPHER_CTX_free(ctx); 264214478Srpaulo 265327234Semaste /* 266327234Semaste * XXX - of course this is wrong, because buf is a const buffer, 267327234Semaste * but changing this would require a more complicated fix. 268327234Semaste */ 269327234Semaste memcpy(__DECONST(u_char *, buf), output_buffer, len); 270356341Scy free(input_buffer); 271327234Semaste free(output_buffer); 272327234Semaste 273214478Srpaulo ndo->ndo_packetp = buf; 274214478Srpaulo ndo->ndo_snapend = end; 275214478Srpaulo 276214478Srpaulo return 1; 277214478Srpaulo} 278276788SdelphijUSES_APPLE_RST 279214478Srpaulo 280146773Ssamstatic void esp_print_addsa(netdissect_options *ndo, 281146773Ssam struct sa_list *sa, int sa_def) 282127668Sbms{ 283127668Sbms /* copy the "sa" */ 28498524Sfenner 285127668Sbms struct sa_list *nsa; 28698524Sfenner 287127668Sbms nsa = (struct sa_list *)malloc(sizeof(struct sa_list)); 288127668Sbms if (nsa == NULL) 289146773Ssam (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure"); 29098524Sfenner 291127668Sbms *nsa = *sa; 29298524Sfenner 293127668Sbms if (sa_def) 294146773Ssam ndo->ndo_sa_default = nsa; 295127668Sbms 296146773Ssam nsa->next = ndo->ndo_sa_list_head; 297146773Ssam ndo->ndo_sa_list_head = nsa; 298127668Sbms} 299127668Sbms 300127668Sbms 301147899Ssamstatic u_int hexdigit(netdissect_options *ndo, char hex) 30298524Sfenner{ 303127668Sbms if (hex >= '0' && hex <= '9') 30498524Sfenner return (hex - '0'); 305127668Sbms else if (hex >= 'A' && hex <= 'F') 30698524Sfenner return (hex - 'A' + 10); 307127668Sbms else if (hex >= 'a' && hex <= 'f') 30898524Sfenner return (hex - 'a' + 10); 309127668Sbms else { 310146773Ssam (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex); 31198524Sfenner } 31298524Sfenner} 31398524Sfenner 314147899Ssamstatic u_int hex2byte(netdissect_options *ndo, char *hexstring) 31598524Sfenner{ 316147899Ssam u_int byte; 31798524Sfenner 318146773Ssam byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]); 31998524Sfenner return byte; 32098524Sfenner} 32198524Sfenner 322127668Sbms/* 323214478Srpaulo * returns size of binary, 0 on failure. 324214478Srpaulo */ 325214478Srpaulostatic 326214478Srpauloint espprint_decode_hex(netdissect_options *ndo, 327214478Srpaulo u_char *binbuf, unsigned int binbuf_len, 328214478Srpaulo char *hex) 329214478Srpaulo{ 330214478Srpaulo unsigned int len; 331214478Srpaulo int i; 332214478Srpaulo 333214478Srpaulo len = strlen(hex) / 2; 334276788Sdelphij 335214478Srpaulo if (len > binbuf_len) { 336214478Srpaulo (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len); 337214478Srpaulo return 0; 338214478Srpaulo } 339276788Sdelphij 340214478Srpaulo i = 0; 341214478Srpaulo while (hex[0] != '\0' && hex[1]!='\0') { 342214478Srpaulo binbuf[i] = hex2byte(ndo, hex); 343214478Srpaulo hex += 2; 344214478Srpaulo i++; 345214478Srpaulo } 346214478Srpaulo 347214478Srpaulo return i; 348214478Srpaulo} 349214478Srpaulo 350214478Srpaulo/* 351127668Sbms * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret 352214478Srpaulo */ 353214478Srpaulo 354276788SdelphijUSES_APPLE_DEPRECATED_API 355214478Srpaulostatic int 356214478Srpauloespprint_decode_encalgo(netdissect_options *ndo, 357214478Srpaulo char *decode, struct sa_list *sa) 358214478Srpaulo{ 359214478Srpaulo size_t i; 360214478Srpaulo const EVP_CIPHER *evp; 361214478Srpaulo int authlen = 0; 362214478Srpaulo char *colon, *p; 363276788Sdelphij 364214478Srpaulo colon = strchr(decode, ':'); 365214478Srpaulo if (colon == NULL) { 366214478Srpaulo (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 367214478Srpaulo return 0; 368214478Srpaulo } 369214478Srpaulo *colon = '\0'; 370276788Sdelphij 371214478Srpaulo if (strlen(decode) > strlen("-hmac96") && 372214478Srpaulo !strcmp(decode + strlen(decode) - strlen("-hmac96"), 373214478Srpaulo "-hmac96")) { 374214478Srpaulo p = strstr(decode, "-hmac96"); 375214478Srpaulo *p = '\0'; 376214478Srpaulo authlen = 12; 377214478Srpaulo } 378214478Srpaulo if (strlen(decode) > strlen("-cbc") && 379214478Srpaulo !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 380214478Srpaulo p = strstr(decode, "-cbc"); 381214478Srpaulo *p = '\0'; 382214478Srpaulo } 383214478Srpaulo evp = EVP_get_cipherbyname(decode); 384214478Srpaulo 385214478Srpaulo if (!evp) { 386214478Srpaulo (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode); 387214478Srpaulo sa->evp = NULL; 388214478Srpaulo sa->authlen = 0; 389214478Srpaulo sa->ivlen = 0; 390214478Srpaulo return 0; 391214478Srpaulo } 392276788Sdelphij 393214478Srpaulo sa->evp = evp; 394214478Srpaulo sa->authlen = authlen; 395214478Srpaulo sa->ivlen = EVP_CIPHER_iv_length(evp); 396276788Sdelphij 397214478Srpaulo colon++; 398214478Srpaulo if (colon[0] == '0' && colon[1] == 'x') { 399214478Srpaulo /* decode some hex! */ 400214478Srpaulo 401214478Srpaulo colon += 2; 402214478Srpaulo sa->secretlen = espprint_decode_hex(ndo, sa->secret, sizeof(sa->secret), colon); 403214478Srpaulo if(sa->secretlen == 0) return 0; 404214478Srpaulo } else { 405214478Srpaulo i = strlen(colon); 406276788Sdelphij 407214478Srpaulo if (i < sizeof(sa->secret)) { 408214478Srpaulo memcpy(sa->secret, colon, i); 409214478Srpaulo sa->secretlen = i; 410214478Srpaulo } else { 411214478Srpaulo memcpy(sa->secret, colon, sizeof(sa->secret)); 412214478Srpaulo sa->secretlen = sizeof(sa->secret); 413214478Srpaulo } 414214478Srpaulo } 415214478Srpaulo 416214478Srpaulo return 1; 417214478Srpaulo} 418276788SdelphijUSES_APPLE_RST 419214478Srpaulo 420214478Srpaulo/* 421356341Scy * for the moment, ignore the auth algorithm, just hard code the authenticator 422214478Srpaulo * length. Need to research how openssl looks up HMAC stuff. 423214478Srpaulo */ 424214478Srpaulostatic int 425214478Srpauloespprint_decode_authalgo(netdissect_options *ndo, 426214478Srpaulo char *decode, struct sa_list *sa) 427214478Srpaulo{ 428214478Srpaulo char *colon; 429214478Srpaulo 430214478Srpaulo colon = strchr(decode, ':'); 431214478Srpaulo if (colon == NULL) { 432214478Srpaulo (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 433214478Srpaulo return 0; 434214478Srpaulo } 435214478Srpaulo *colon = '\0'; 436276788Sdelphij 437313537Sglebius if(ascii_strcasecmp(colon,"sha1") == 0 || 438313537Sglebius ascii_strcasecmp(colon,"md5") == 0) { 439214478Srpaulo sa->authlen = 12; 440214478Srpaulo } 441214478Srpaulo return 1; 442214478Srpaulo} 443214478Srpaulo 444214478Srpaulostatic void esp_print_decode_ikeline(netdissect_options *ndo, char *line, 445214478Srpaulo const char *file, int lineno) 446214478Srpaulo{ 447214478Srpaulo /* it's an IKEv2 secret, store it instead */ 448214478Srpaulo struct sa_list sa1; 449214478Srpaulo 450214478Srpaulo char *init; 451214478Srpaulo char *icookie, *rcookie; 452214478Srpaulo int ilen, rlen; 453214478Srpaulo char *authkey; 454214478Srpaulo char *enckey; 455276788Sdelphij 456214478Srpaulo init = strsep(&line, " \t"); 457214478Srpaulo icookie = strsep(&line, " \t"); 458214478Srpaulo rcookie = strsep(&line, " \t"); 459214478Srpaulo authkey = strsep(&line, " \t"); 460214478Srpaulo enckey = strsep(&line, " \t"); 461276788Sdelphij 462214478Srpaulo /* if any fields are missing */ 463214478Srpaulo if(!init || !icookie || !rcookie || !authkey || !enckey) { 464214478Srpaulo (*ndo->ndo_warning)(ndo, "print_esp: failed to find all fields for ikev2 at %s:%u", 465214478Srpaulo file, lineno); 466276788Sdelphij 467214478Srpaulo return; 468214478Srpaulo } 469276788Sdelphij 470214478Srpaulo ilen = strlen(icookie); 471214478Srpaulo rlen = strlen(rcookie); 472214478Srpaulo 473214478Srpaulo if((init[0]!='I' && init[0]!='R') 474214478Srpaulo || icookie[0]!='0' || icookie[1]!='x' 475214478Srpaulo || rcookie[0]!='0' || rcookie[1]!='x' 476214478Srpaulo || ilen!=18 477214478Srpaulo || rlen!=18) { 478214478Srpaulo (*ndo->ndo_warning)(ndo, "print_esp: line %s:%u improperly formatted.", 479214478Srpaulo file, lineno); 480214478Srpaulo 481214478Srpaulo (*ndo->ndo_warning)(ndo, "init=%s icookie=%s(%u) rcookie=%s(%u)", 482214478Srpaulo init, icookie, ilen, rcookie, rlen); 483276788Sdelphij 484214478Srpaulo return; 485214478Srpaulo } 486214478Srpaulo 487214478Srpaulo sa1.spi = 0; 488214478Srpaulo sa1.initiator = (init[0] == 'I'); 489214478Srpaulo if(espprint_decode_hex(ndo, sa1.spii, sizeof(sa1.spii), icookie+2)!=8) 490214478Srpaulo return; 491214478Srpaulo 492214478Srpaulo if(espprint_decode_hex(ndo, sa1.spir, sizeof(sa1.spir), rcookie+2)!=8) 493214478Srpaulo return; 494214478Srpaulo 495214478Srpaulo if(!espprint_decode_encalgo(ndo, enckey, &sa1)) return; 496214478Srpaulo 497214478Srpaulo if(!espprint_decode_authalgo(ndo, authkey, &sa1)) return; 498276788Sdelphij 499214478Srpaulo esp_print_addsa(ndo, &sa1, FALSE); 500214478Srpaulo} 501214478Srpaulo 502214478Srpaulo/* 503127668Sbms * 504127668Sbms * special form: file /name 505127668Sbms * causes us to go read from this file instead. 506127668Sbms * 507127668Sbms */ 508214478Srpaulostatic void esp_print_decode_onesecret(netdissect_options *ndo, char *line, 509214478Srpaulo const char *file, int lineno) 51098524Sfenner{ 511127668Sbms struct sa_list sa1; 512127668Sbms int sa_def; 51398524Sfenner 514127668Sbms char *spikey; 515127668Sbms char *decode; 51698524Sfenner 517127668Sbms spikey = strsep(&line, " \t"); 518127668Sbms sa_def = 0; 519127668Sbms memset(&sa1, 0, sizeof(struct sa_list)); 520127668Sbms 521127668Sbms /* if there is only one token, then it is an algo:key token */ 522127668Sbms if (line == NULL) { 523127668Sbms decode = spikey; 524127668Sbms spikey = NULL; 525276788Sdelphij /* sa1.daddr.version = 0; */ 526127668Sbms /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 527127668Sbms /* sa1.spi = 0; */ 528127668Sbms sa_def = 1; 529127668Sbms } else 530127668Sbms decode = line; 531127668Sbms 532313537Sglebius if (spikey && ascii_strcasecmp(spikey, "file") == 0) { 533127668Sbms /* open file and read it */ 534127668Sbms FILE *secretfile; 535127668Sbms char fileline[1024]; 536313537Sglebius int subfile_lineno=0; 537127668Sbms char *nl; 538214478Srpaulo char *filename = line; 539127668Sbms 540214478Srpaulo secretfile = fopen(filename, FOPEN_READ_TXT); 541127668Sbms if (secretfile == NULL) { 542313537Sglebius (*ndo->ndo_error)(ndo, "print_esp: can't open %s: %s\n", 543313537Sglebius filename, strerror(errno)); 544127668Sbms } 545127668Sbms 546127668Sbms while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 547313537Sglebius subfile_lineno++; 548127668Sbms /* remove newline from the line */ 549127668Sbms nl = strchr(fileline, '\n'); 550127668Sbms if (nl) 551127668Sbms *nl = '\0'; 552127668Sbms if (fileline[0] == '#') continue; 553127668Sbms if (fileline[0] == '\0') continue; 554127668Sbms 555313537Sglebius esp_print_decode_onesecret(ndo, fileline, filename, subfile_lineno); 556127668Sbms } 557127668Sbms fclose(secretfile); 558127668Sbms 55998524Sfenner return; 56098524Sfenner } 56198524Sfenner 562313537Sglebius if (spikey && ascii_strcasecmp(spikey, "ikev2") == 0) { 563214478Srpaulo esp_print_decode_ikeline(ndo, line, file, lineno); 564214478Srpaulo return; 565276788Sdelphij } 566214478Srpaulo 567127668Sbms if (spikey) { 568276788Sdelphij 569127668Sbms char *spistr, *foo; 570276788Sdelphij uint32_t spino; 571276788Sdelphij 572127668Sbms spistr = strsep(&spikey, "@"); 573356341Scy if (spistr == NULL) { 574356341Scy (*ndo->ndo_warning)(ndo, "print_esp: failed to find the @ token"); 575356341Scy return; 576356341Scy } 577276788Sdelphij 578127668Sbms spino = strtoul(spistr, &foo, 0); 579127668Sbms if (spistr == foo || !spikey) { 580146773Ssam (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo); 581127668Sbms return; 582127668Sbms } 583276788Sdelphij 584127668Sbms sa1.spi = spino; 585276788Sdelphij 586313537Sglebius if (strtoaddr6(spikey, &sa1.daddr.in6) == 1) { 587276788Sdelphij sa1.daddr_version = 6; 588313537Sglebius } else if (strtoaddr(spikey, &sa1.daddr.in4) == 1) { 589313537Sglebius sa1.daddr_version = 4; 590313537Sglebius } else { 591313537Sglebius (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey); 592313537Sglebius return; 593313537Sglebius } 59498524Sfenner } 59598524Sfenner 596127668Sbms if (decode) { 597127668Sbms /* skip any blank spaces */ 598127668Sbms while (isspace((unsigned char)*decode)) 599127668Sbms decode++; 600276788Sdelphij 601214478Srpaulo if(!espprint_decode_encalgo(ndo, decode, &sa1)) { 602127668Sbms return; 60398524Sfenner } 60498524Sfenner } 605127668Sbms 606146773Ssam esp_print_addsa(ndo, &sa1, sa_def); 60798524Sfenner} 60898524Sfenner 609276788SdelphijUSES_APPLE_DEPRECATED_API 610214478Srpaulostatic void esp_init(netdissect_options *ndo _U_) 611127668Sbms{ 612313537Sglebius /* 613313537Sglebius * 0.9.6 doesn't appear to define OPENSSL_API_COMPAT, so 614313537Sglebius * we check whether it's undefined or it's less than the 615313537Sglebius * value for 1.1.0. 616313537Sglebius */ 617313537Sglebius#if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L 618214478Srpaulo OpenSSL_add_all_algorithms(); 619313537Sglebius#endif 620214478Srpaulo EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 621214478Srpaulo} 622276788SdelphijUSES_APPLE_RST 623214478Srpaulo 624214478Srpaulovoid esp_print_decodesecret(netdissect_options *ndo) 625214478Srpaulo{ 626127668Sbms char *line; 627127668Sbms char *p; 628214478Srpaulo static int initialized = 0; 629127668Sbms 630214478Srpaulo if (!initialized) { 631214478Srpaulo esp_init(ndo); 632214478Srpaulo initialized = 1; 633214478Srpaulo } 634214478Srpaulo 635146773Ssam p = ndo->ndo_espsecret; 636127668Sbms 637214478Srpaulo while (p && p[0] != '\0') { 638127668Sbms /* pick out the first line or first thing until a comma */ 639214478Srpaulo if ((line = strsep(&p, "\n,")) == NULL) { 640214478Srpaulo line = p; 641214478Srpaulo p = NULL; 642127668Sbms } 643127668Sbms 644214478Srpaulo esp_print_decode_onesecret(ndo, line, "cmdline", 0); 645127668Sbms } 646214478Srpaulo 647214478Srpaulo ndo->ndo_espsecret = NULL; 648127668Sbms} 649127668Sbms 650127668Sbms#endif 651127668Sbms 652276788Sdelphij#ifdef HAVE_LIBCRYPTO 653276788SdelphijUSES_APPLE_DEPRECATED_API 654276788Sdelphij#endif 65556893Sfennerint 656146773Ssamesp_print(netdissect_options *ndo, 657146773Ssam const u_char *bp, const int length, const u_char *bp2 658127668Sbms#ifndef HAVE_LIBCRYPTO 659127668Sbms _U_ 660127668Sbms#endif 661127668Sbms , 662127668Sbms int *nhdr 663127668Sbms#ifndef HAVE_LIBCRYPTO 664127668Sbms _U_ 665127668Sbms#endif 666127668Sbms , 667127668Sbms int *padlen 668127668Sbms#ifndef HAVE_LIBCRYPTO 669127668Sbms _U_ 670127668Sbms#endif 671127668Sbms ) 67256893Sfenner{ 673127668Sbms register const struct newesp *esp; 67456893Sfenner register const u_char *ep; 675127668Sbms#ifdef HAVE_LIBCRYPTO 676313537Sglebius const struct ip *ip; 677127668Sbms struct sa_list *sa = NULL; 678313537Sglebius const struct ip6_hdr *ip6 = NULL; 67956893Sfenner int advance; 68056893Sfenner int len; 681147899Ssam u_char *secret; 68256893Sfenner int ivlen = 0; 683313537Sglebius const u_char *ivoff; 684313537Sglebius const u_char *p; 685313537Sglebius EVP_CIPHER_CTX *ctx; 686356341Scy unsigned int block_size, buffer_size; 687356341Scy u_char *input_buffer, *output_buffer; 688127668Sbms#endif 689127668Sbms 690313537Sglebius esp = (const struct newesp *)bp; 691127668Sbms 692127668Sbms#ifdef HAVE_LIBCRYPTO 69398524Sfenner secret = NULL; 694127668Sbms advance = 0; 695127668Sbms#endif 696127668Sbms 69798524Sfenner#if 0 69898524Sfenner /* keep secret out of a register */ 69998524Sfenner p = (u_char *)&secret; 70098524Sfenner#endif 70198524Sfenner 70275115Sfenner /* 'ep' points to the end of available data. */ 703146773Ssam ep = ndo->ndo_snapend; 70456893Sfenner 705313537Sglebius if ((const u_char *)(esp + 1) >= ep) { 706276788Sdelphij ND_PRINT((ndo, "[|ESP]")); 70756893Sfenner goto fail; 70856893Sfenner } 709276788Sdelphij ND_PRINT((ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi))); 710276788Sdelphij ND_PRINT((ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq))); 711276788Sdelphij ND_PRINT((ndo, ", length %u", length)); 71256893Sfenner 713127668Sbms#ifndef HAVE_LIBCRYPTO 714127668Sbms goto fail; 715127668Sbms#else 716127668Sbms /* initiailize SAs */ 717146773Ssam if (ndo->ndo_sa_list_head == NULL) { 718146773Ssam if (!ndo->ndo_espsecret) 719127668Sbms goto fail; 72056893Sfenner 721146773Ssam esp_print_decodesecret(ndo); 72256893Sfenner } 723127668Sbms 724146773Ssam if (ndo->ndo_sa_list_head == NULL) 72598524Sfenner goto fail; 72656893Sfenner 727313537Sglebius ip = (const struct ip *)bp2; 72875115Sfenner switch (IP_V(ip)) { 72956893Sfenner case 6: 730313537Sglebius ip6 = (const struct ip6_hdr *)bp2; 73156893Sfenner /* we do not attempt to decrypt jumbograms */ 732127668Sbms if (!EXTRACT_16BITS(&ip6->ip6_plen)) 73356893Sfenner goto fail; 73456893Sfenner /* if we can't get nexthdr, we do not need to decrypt it */ 735127668Sbms len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 736127668Sbms 737127668Sbms /* see if we can find the SA, and if so, decode it */ 738146773Ssam for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 739214478Srpaulo if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 740276788Sdelphij sa->daddr_version == 6 && 741276788Sdelphij UNALIGNED_MEMCMP(&sa->daddr.in6, &ip6->ip6_dst, 742127668Sbms sizeof(struct in6_addr)) == 0) { 743127668Sbms break; 744127668Sbms } 745127668Sbms } 74656893Sfenner break; 74756893Sfenner case 4: 74898524Sfenner /* nexthdr & padding are in the last fragment */ 749127668Sbms if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 75098524Sfenner goto fail; 751127668Sbms len = EXTRACT_16BITS(&ip->ip_len); 752127668Sbms 753127668Sbms /* see if we can find the SA, and if so, decode it */ 754146773Ssam for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 755214478Srpaulo if (sa->spi == EXTRACT_32BITS(&esp->esp_spi) && 756276788Sdelphij sa->daddr_version == 4 && 757276788Sdelphij UNALIGNED_MEMCMP(&sa->daddr.in4, &ip->ip_dst, 758276788Sdelphij sizeof(struct in_addr)) == 0) { 759127668Sbms break; 760127668Sbms } 761127668Sbms } 76256893Sfenner break; 76356893Sfenner default: 76456893Sfenner goto fail; 76556893Sfenner } 76656893Sfenner 767127668Sbms /* if we didn't find the specific one, then look for 768127668Sbms * an unspecified one. 769127668Sbms */ 770127668Sbms if (sa == NULL) 771146773Ssam sa = ndo->ndo_sa_default; 772276788Sdelphij 773127668Sbms /* if not found fail */ 774127668Sbms if (sa == NULL) 775127668Sbms goto fail; 776127668Sbms 77756893Sfenner /* if we can't get nexthdr, we do not need to decrypt it */ 77856893Sfenner if (ep - bp2 < len) 77956893Sfenner goto fail; 780127668Sbms if (ep - bp2 > len) { 781127668Sbms /* FCS included at end of frame (NetBSD 1.6 or later) */ 782127668Sbms ep = bp2 + len; 783127668Sbms } 78456893Sfenner 785327234Semaste /* pointer to the IV, if there is one */ 786313537Sglebius ivoff = (const u_char *)(esp + 1) + 0; 787327234Semaste /* length of the IV, if there is one; 0, if there isn't */ 788127668Sbms ivlen = sa->ivlen; 789127668Sbms secret = sa->secret; 790146773Ssam ep = ep - sa->authlen; 79156893Sfenner 792127668Sbms if (sa->evp) { 793313537Sglebius ctx = EVP_CIPHER_CTX_new(); 794313537Sglebius if (ctx != NULL) { 795327234Semaste if (set_cipher_parameters(ctx, sa->evp, secret, NULL, 0) < 0) 796313537Sglebius (*ndo->ndo_warning)(ndo, "espkey init failed"); 79756893Sfenner 798313537Sglebius p = ivoff; 799327234Semaste set_cipher_parameters(ctx, NULL, NULL, p, 0); 800327234Semaste len = ep - (p + ivlen); 801327234Semaste 802327234Semaste /* 803356341Scy * Allocate buffers for the encrypted and decrypted 804356341Scy * data. Both buffers' sizes must be a multiple of 805356341Scy * the cipher block size, and the output buffer must 806356341Scy * be separate from the input buffer. 807327234Semaste */ 808327234Semaste block_size = (unsigned int)EVP_CIPHER_CTX_block_size(ctx); 809356341Scy buffer_size = len + (block_size - len % block_size); 810356341Scy 811356341Scy /* 812356341Scy * Attempt to allocate the input buffer. 813356341Scy */ 814356341Scy input_buffer = (u_char *)malloc(buffer_size); 815356341Scy if (input_buffer == NULL) { 816356341Scy EVP_CIPHER_CTX_free(ctx); 817356341Scy (*ndo->ndo_error)(ndo, "can't allocate memory for encrypted data buffer"); 818356341Scy } 819356341Scy /* 820356341Scy * Copy the input data to the encrypted data buffer, 821356341Scy * and pad it with zeroes. 822356341Scy */ 823356341Scy memcpy(input_buffer, p + ivlen, len); 824356341Scy memset(input_buffer + len, 0, buffer_size - len); 825356341Scy 826356341Scy /* 827356341Scy * Attempt to allocate the output buffer. 828356341Scy */ 829356341Scy output_buffer = (u_char *)malloc(buffer_size); 830327234Semaste if (output_buffer == NULL) { 831356341Scy free(input_buffer); 832327234Semaste EVP_CIPHER_CTX_free(ctx); 833356341Scy (*ndo->ndo_error)(ndo, "can't allocate memory for decryption buffer"); 834327234Semaste } 835327234Semaste 836356341Scy EVP_Cipher(ctx, output_buffer, input_buffer, len); 837356341Scy free(input_buffer); 838313537Sglebius EVP_CIPHER_CTX_free(ctx); 839327234Semaste /* 840327234Semaste * XXX - of course this is wrong, because buf is a 841327234Semaste * const buffer, but changing this would require a 842327234Semaste * more complicated fix. 843327234Semaste */ 844327234Semaste memcpy(__DECONST(u_char *, p + ivlen), output_buffer, len); 845327234Semaste free(output_buffer); 846313537Sglebius advance = ivoff - (const u_char *)esp + ivlen; 847313537Sglebius } else 848313537Sglebius advance = sizeof(struct newesp); 849127668Sbms } else 850127668Sbms advance = sizeof(struct newesp); 85156893Sfenner 85256893Sfenner /* sanity check for pad length */ 85356893Sfenner if (ep - bp < *(ep - 2)) 85456893Sfenner goto fail; 85556893Sfenner 85698524Sfenner if (padlen) 85798524Sfenner *padlen = *(ep - 2) + 2; 85898524Sfenner 85956893Sfenner if (nhdr) 86056893Sfenner *nhdr = *(ep - 1); 86156893Sfenner 862276788Sdelphij ND_PRINT((ndo, ": ")); 86356893Sfenner return advance; 864127668Sbms#endif 86556893Sfenner 86656893Sfennerfail: 867127668Sbms return -1; 86856893Sfenner} 869276788Sdelphij#ifdef HAVE_LIBCRYPTO 870276788SdelphijUSES_APPLE_RST 871276788Sdelphij#endif 872146773Ssam 873146773Ssam/* 874146773Ssam * Local Variables: 875146773Ssam * c-style: whitesmith 876146773Ssam * c-basic-offset: 8 877146773Ssam * End: 878146773Ssam */ 879