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_ = 265b0fe478SBruce M Simpson "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.44.2.4 2003/11/19 05:36:40 guy 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 535b0fe478SBruce M Simpson #if defined(__MINGW32__) || defined(__WATCOMC__) 545b0fe478SBruce M Simpson extern char *strsep(char **stringp, const char *delim); /* Missing/strsep.c */ 555b0fe478SBruce M Simpson #endif 565b0fe478SBruce M Simpson 57b0453382SBill Fenner #include "interface.h" 58b0453382SBill Fenner #include "addrtoname.h" 595b0fe478SBruce M Simpson #include "extract.h" 60b0453382SBill Fenner 615b0fe478SBruce M Simpson #ifndef HAVE_SOCKADDR_STORAGE 625b0fe478SBruce M Simpson #ifdef INET6 635b0fe478SBruce M Simpson struct sockaddr_storage { 645b0fe478SBruce M Simpson union { 655b0fe478SBruce M Simpson struct sockaddr_in sin; 665b0fe478SBruce M Simpson struct sockaddr_in6 sin6; 675b0fe478SBruce M Simpson } un; 685b0fe478SBruce M Simpson }; 695b0fe478SBruce M Simpson #else 705b0fe478SBruce M Simpson #define sockaddr_storage sockaddr 715b0fe478SBruce M Simpson #endif 725b0fe478SBruce M Simpson #endif /* HAVE_SOCKADDR_STORAGE */ 73a90e161bSBill Fenner 745b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 755b0fe478SBruce M Simpson struct sa_list { 765b0fe478SBruce M Simpson struct sa_list *next; 775b0fe478SBruce M Simpson struct sockaddr_storage daddr; 785b0fe478SBruce M Simpson u_int32_t spi; 795b0fe478SBruce M Simpson const EVP_CIPHER *evp; 80a90e161bSBill Fenner int ivlen; 81a90e161bSBill Fenner int authlen; 825b0fe478SBruce M Simpson char secret[256]; /* is that big enough for all secrets? */ 835b0fe478SBruce M Simpson int secretlen; 84a90e161bSBill Fenner }; 85a90e161bSBill Fenner 865b0fe478SBruce M Simpson static struct sa_list *sa_list_head = NULL; 875b0fe478SBruce M Simpson static struct sa_list *sa_default = NULL; 885b0fe478SBruce M Simpson 895b0fe478SBruce M Simpson static void esp_print_addsa(struct sa_list *sa, int sa_def) 905b0fe478SBruce M Simpson { 915b0fe478SBruce M Simpson /* copy the "sa" */ 925b0fe478SBruce M Simpson 935b0fe478SBruce M Simpson struct sa_list *nsa; 945b0fe478SBruce M Simpson 955b0fe478SBruce M Simpson nsa = (struct sa_list *)malloc(sizeof(struct sa_list)); 965b0fe478SBruce M Simpson if (nsa == NULL) 975b0fe478SBruce M Simpson error("ran out of memory to allocate sa structure"); 985b0fe478SBruce M Simpson 995b0fe478SBruce M Simpson *nsa = *sa; 1005b0fe478SBruce M Simpson 1015b0fe478SBruce M Simpson if (sa_def) 1025b0fe478SBruce M Simpson sa_default = nsa; 1035b0fe478SBruce M Simpson 1045b0fe478SBruce M Simpson nsa->next = sa_list_head; 1055b0fe478SBruce M Simpson sa_list_head = nsa; 1065b0fe478SBruce M Simpson } 1075b0fe478SBruce M Simpson 108a90e161bSBill Fenner 109a90e161bSBill Fenner static int hexdigit(char hex) 110a90e161bSBill Fenner { 1115b0fe478SBruce M Simpson if (hex >= '0' && hex <= '9') 112a90e161bSBill Fenner return (hex - '0'); 1135b0fe478SBruce M Simpson else if (hex >= 'A' && hex <= 'F') 114a90e161bSBill Fenner return (hex - 'A' + 10); 1155b0fe478SBruce M Simpson else if (hex >= 'a' && hex <= 'f') 116a90e161bSBill Fenner return (hex - 'a' + 10); 1175b0fe478SBruce M Simpson else { 118a90e161bSBill Fenner printf("invalid hex digit %c in espsecret\n", hex); 119a90e161bSBill Fenner return 0; 120a90e161bSBill Fenner } 121a90e161bSBill Fenner } 122a90e161bSBill Fenner 123a90e161bSBill Fenner static int hex2byte(char *hexstring) 124a90e161bSBill Fenner { 125a90e161bSBill Fenner int byte; 126a90e161bSBill Fenner 1275b0fe478SBruce M Simpson byte = (hexdigit(hexstring[0]) << 4) + hexdigit(hexstring[1]); 128a90e161bSBill Fenner return byte; 129a90e161bSBill Fenner } 130a90e161bSBill Fenner 1315b0fe478SBruce M Simpson /* 1325b0fe478SBruce M Simpson * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret 1335b0fe478SBruce M Simpson * 1345b0fe478SBruce M Simpson * special form: file /name 1355b0fe478SBruce M Simpson * causes us to go read from this file instead. 1365b0fe478SBruce M Simpson * 1375b0fe478SBruce M Simpson */ 1385b0fe478SBruce M Simpson static void esp_print_decode_onesecret(char *line) 139a90e161bSBill Fenner { 1405b0fe478SBruce M Simpson struct sa_list sa1; 1415b0fe478SBruce M Simpson int sa_def; 142a90e161bSBill Fenner 1435b0fe478SBruce M Simpson char *spikey; 1445b0fe478SBruce M Simpson char *decode; 1455b0fe478SBruce M Simpson 1465b0fe478SBruce M Simpson spikey = strsep(&line, " \t"); 1475b0fe478SBruce M Simpson sa_def = 0; 1485b0fe478SBruce M Simpson memset(&sa1, 0, sizeof(struct sa_list)); 1495b0fe478SBruce M Simpson 1505b0fe478SBruce M Simpson /* if there is only one token, then it is an algo:key token */ 1515b0fe478SBruce M Simpson if (line == NULL) { 1525b0fe478SBruce M Simpson decode = spikey; 1535b0fe478SBruce M Simpson spikey = NULL; 1545b0fe478SBruce M Simpson /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 1555b0fe478SBruce M Simpson /* sa1.spi = 0; */ 1565b0fe478SBruce M Simpson sa_def = 1; 1575b0fe478SBruce M Simpson } else 1585b0fe478SBruce M Simpson decode = line; 1595b0fe478SBruce M Simpson 1605b0fe478SBruce M Simpson if (spikey && strcasecmp(spikey, "file") == 0) { 1615b0fe478SBruce M Simpson /* open file and read it */ 1625b0fe478SBruce M Simpson FILE *secretfile; 1635b0fe478SBruce M Simpson char fileline[1024]; 1645b0fe478SBruce M Simpson char *nl; 1655b0fe478SBruce M Simpson 1665b0fe478SBruce M Simpson secretfile = fopen(line, FOPEN_READ_TXT); 1675b0fe478SBruce M Simpson if (secretfile == NULL) { 1685b0fe478SBruce M Simpson perror(line); 1695b0fe478SBruce M Simpson exit(3); 1705b0fe478SBruce M Simpson } 1715b0fe478SBruce M Simpson 1725b0fe478SBruce M Simpson while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 1735b0fe478SBruce M Simpson /* remove newline from the line */ 1745b0fe478SBruce M Simpson nl = strchr(fileline, '\n'); 1755b0fe478SBruce M Simpson if (nl) 1765b0fe478SBruce M Simpson *nl = '\0'; 1775b0fe478SBruce M Simpson if (fileline[0] == '#') continue; 1785b0fe478SBruce M Simpson if (fileline[0] == '\0') continue; 1795b0fe478SBruce M Simpson 1805b0fe478SBruce M Simpson esp_print_decode_onesecret(fileline); 1815b0fe478SBruce M Simpson } 1825b0fe478SBruce M Simpson fclose(secretfile); 1835b0fe478SBruce M Simpson 184a90e161bSBill Fenner return; 185a90e161bSBill Fenner } 186a90e161bSBill Fenner 1875b0fe478SBruce M Simpson if (spikey) { 1885b0fe478SBruce M Simpson char *spistr, *foo; 1895b0fe478SBruce M Simpson u_int32_t spino; 1905b0fe478SBruce M Simpson struct sockaddr_in *sin; 1915b0fe478SBruce M Simpson #ifdef INET6 1925b0fe478SBruce M Simpson struct sockaddr_in6 *sin6; 1935b0fe478SBruce M Simpson #endif 1945b0fe478SBruce M Simpson 1955b0fe478SBruce M Simpson spistr = strsep(&spikey, "@"); 1965b0fe478SBruce M Simpson 1975b0fe478SBruce M Simpson spino = strtoul(spistr, &foo, 0); 1985b0fe478SBruce M Simpson if (spistr == foo || !spikey) { 1995b0fe478SBruce M Simpson printf("print_esp: failed to decode spi# %s\n", foo); 200a90e161bSBill Fenner return; 201a90e161bSBill Fenner } 202a90e161bSBill Fenner 2035b0fe478SBruce M Simpson sa1.spi = spino; 2045b0fe478SBruce M Simpson 2055b0fe478SBruce M Simpson sin = (struct sockaddr_in *)&sa1.daddr; 2065b0fe478SBruce M Simpson #ifdef INET6 2075b0fe478SBruce M Simpson sin6 = (struct sockaddr_in6 *)&sa1.daddr; 2085b0fe478SBruce M Simpson if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) { 2095b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN 2105b0fe478SBruce M Simpson sin6->sin6_len = sizeof(struct sockaddr_in6); 2115b0fe478SBruce M Simpson #endif 2125b0fe478SBruce M Simpson sin6->sin6_family = AF_INET6; 2135b0fe478SBruce M Simpson } else 2145b0fe478SBruce M Simpson #endif 2155b0fe478SBruce M Simpson if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) { 2165b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN 2175b0fe478SBruce M Simpson sin->sin_len = sizeof(struct sockaddr_in); 2185b0fe478SBruce M Simpson #endif 2195b0fe478SBruce M Simpson sin->sin_family = AF_INET; 2205b0fe478SBruce M Simpson } else { 2215b0fe478SBruce M Simpson printf("print_esp: can not decode IP# %s\n", spikey); 2225b0fe478SBruce M Simpson return; 2235b0fe478SBruce M Simpson } 2245b0fe478SBruce M Simpson } 2255b0fe478SBruce M Simpson 2265b0fe478SBruce M Simpson if (decode) { 2275b0fe478SBruce M Simpson char *colon, *p; 2285b0fe478SBruce M Simpson char espsecret_key[256]; 2295b0fe478SBruce M Simpson int len; 2305b0fe478SBruce M Simpson size_t i; 2315b0fe478SBruce M Simpson const EVP_CIPHER *evp; 2325b0fe478SBruce M Simpson int ivlen = 8; 2335b0fe478SBruce M Simpson int authlen = 0; 2345b0fe478SBruce M Simpson 2355b0fe478SBruce M Simpson /* skip any blank spaces */ 2365b0fe478SBruce M Simpson while (isspace((unsigned char)*decode)) 2375b0fe478SBruce M Simpson decode++; 2385b0fe478SBruce M Simpson 2395b0fe478SBruce M Simpson colon = strchr(decode, ':'); 240a90e161bSBill Fenner if (colon == NULL) { 2415b0fe478SBruce M Simpson printf("failed to decode espsecret: %s\n", decode); 242a90e161bSBill Fenner return; 243a90e161bSBill Fenner } 2445b0fe478SBruce M Simpson *colon = '\0'; 2455b0fe478SBruce M Simpson 2465b0fe478SBruce M Simpson len = colon - decode; 2475b0fe478SBruce M Simpson if (strlen(decode) > strlen("-hmac96") && 2485b0fe478SBruce M Simpson !strcmp(decode + strlen(decode) - strlen("-hmac96"), 2495b0fe478SBruce M Simpson "-hmac96")) { 2505b0fe478SBruce M Simpson p = strstr(decode, "-hmac96"); 2515b0fe478SBruce M Simpson *p = '\0'; 2525b0fe478SBruce M Simpson authlen = 12; 2535b0fe478SBruce M Simpson } 2545b0fe478SBruce M Simpson if (strlen(decode) > strlen("-cbc") && 2555b0fe478SBruce M Simpson !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 2565b0fe478SBruce M Simpson p = strstr(decode, "-cbc"); 2575b0fe478SBruce M Simpson *p = '\0'; 2585b0fe478SBruce M Simpson } 2595b0fe478SBruce M Simpson evp = EVP_get_cipherbyname(decode); 2605b0fe478SBruce M Simpson if (!evp) { 2615b0fe478SBruce M Simpson printf("failed to find cipher algo %s\n", decode); 2625b0fe478SBruce M Simpson sa1.evp = NULL; 2635b0fe478SBruce M Simpson sa1.authlen = 0; 2645b0fe478SBruce M Simpson sa1.ivlen = 0; 2655b0fe478SBruce M Simpson return; 2665b0fe478SBruce M Simpson } 2675b0fe478SBruce M Simpson 2685b0fe478SBruce M Simpson sa1.evp = evp; 2695b0fe478SBruce M Simpson sa1.authlen = authlen; 2705b0fe478SBruce M Simpson sa1.ivlen = ivlen; 271a90e161bSBill Fenner 272a90e161bSBill Fenner colon++; 273a90e161bSBill Fenner if (colon[0] == '0' && colon[1] == 'x') { 274a90e161bSBill Fenner /* decode some hex! */ 275a90e161bSBill Fenner colon += 2; 276a90e161bSBill Fenner len = strlen(colon) / 2; 2775b0fe478SBruce M Simpson 2785b0fe478SBruce M Simpson if (len > 256) { 2795b0fe478SBruce M Simpson printf("secret is too big: %d\n", len); 2805b0fe478SBruce M Simpson return; 281a90e161bSBill Fenner } 2825b0fe478SBruce M Simpson 283a90e161bSBill Fenner i = 0; 284a90e161bSBill Fenner while (colon[0] != '\0' && colon[1]!='\0') { 285a90e161bSBill Fenner espsecret_key[i] = hex2byte(colon); 286a90e161bSBill Fenner colon += 2; 287a90e161bSBill Fenner i++; 288a90e161bSBill Fenner } 2895b0fe478SBruce M Simpson 2905b0fe478SBruce M Simpson memcpy(sa1.secret, espsecret_key, i); 2915b0fe478SBruce M Simpson sa1.secretlen = i; 292a90e161bSBill Fenner } else { 2935b0fe478SBruce M Simpson i = strlen(colon); 2945b0fe478SBruce M Simpson 2955b0fe478SBruce M Simpson if (i < sizeof(sa1.secret)) { 2965b0fe478SBruce M Simpson memcpy(sa1.secret, colon, i); 2975b0fe478SBruce M Simpson sa1.secretlen = i; 2985b0fe478SBruce M Simpson } else { 2995b0fe478SBruce M Simpson memcpy(sa1.secret, colon, sizeof(sa1.secret)); 3005b0fe478SBruce M Simpson sa1.secretlen = sizeof(sa1.secret); 3015b0fe478SBruce M Simpson } 302a90e161bSBill Fenner } 303a90e161bSBill Fenner } 304a90e161bSBill Fenner 3055b0fe478SBruce M Simpson esp_print_addsa(&sa1, sa_def); 3065b0fe478SBruce M Simpson } 3075b0fe478SBruce M Simpson 3085b0fe478SBruce M Simpson static void esp_print_decodesecret(void) 309b0453382SBill Fenner { 3105b0fe478SBruce M Simpson char *line; 3115b0fe478SBruce M Simpson char *p; 3125b0fe478SBruce M Simpson 3135b0fe478SBruce M Simpson p = espsecret; 3145b0fe478SBruce M Simpson 3155b0fe478SBruce M Simpson while (espsecret && espsecret[0] != '\0') { 3165b0fe478SBruce M Simpson /* pick out the first line or first thing until a comma */ 3175b0fe478SBruce M Simpson if ((line = strsep(&espsecret, "\n,")) == NULL) { 3185b0fe478SBruce M Simpson line = espsecret; 3195b0fe478SBruce M Simpson espsecret = NULL; 3205b0fe478SBruce M Simpson } 3215b0fe478SBruce M Simpson 3225b0fe478SBruce M Simpson esp_print_decode_onesecret(line); 3235b0fe478SBruce M Simpson } 3245b0fe478SBruce M Simpson } 3255b0fe478SBruce M Simpson 3265b0fe478SBruce M Simpson static void esp_init(void) 3275b0fe478SBruce M Simpson { 3285b0fe478SBruce M Simpson 3295b0fe478SBruce M Simpson OpenSSL_add_all_algorithms(); 3305b0fe478SBruce M Simpson EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 3315b0fe478SBruce M Simpson } 3325b0fe478SBruce M Simpson #endif 3335b0fe478SBruce M Simpson 3345b0fe478SBruce M Simpson int 3355b0fe478SBruce M Simpson esp_print(const u_char *bp, const u_char *bp2 3365b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3375b0fe478SBruce M Simpson _U_ 3385b0fe478SBruce M Simpson #endif 3395b0fe478SBruce M Simpson , 3405b0fe478SBruce M Simpson int *nhdr 3415b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3425b0fe478SBruce M Simpson _U_ 3435b0fe478SBruce M Simpson #endif 3445b0fe478SBruce M Simpson , 3455b0fe478SBruce M Simpson int *padlen 3465b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3475b0fe478SBruce M Simpson _U_ 3485b0fe478SBruce M Simpson #endif 3495b0fe478SBruce M Simpson ) 3505b0fe478SBruce M Simpson { 3515b0fe478SBruce M Simpson register const struct newesp *esp; 352b0453382SBill Fenner register const u_char *ep; 3535b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 3545b0fe478SBruce M Simpson struct ip *ip; 3555b0fe478SBruce M Simpson struct sa_list *sa = NULL; 3565b0fe478SBruce M Simpson int espsecret_keylen; 357b0453382SBill Fenner #ifdef INET6 358b0453382SBill Fenner struct ip6_hdr *ip6 = NULL; 359b0453382SBill Fenner #endif 360b0453382SBill Fenner int advance; 361b0453382SBill Fenner int len; 362a90e161bSBill Fenner char *secret; 363b0453382SBill Fenner int ivlen = 0; 364b0453382SBill Fenner u_char *ivoff; 3655b0fe478SBruce M Simpson const u_char *p; 3665b0fe478SBruce M Simpson EVP_CIPHER_CTX ctx; 3675b0fe478SBruce M Simpson int blocksz; 3685b0fe478SBruce M Simpson static int initialized = 0; 3695b0fe478SBruce M Simpson #endif 370b0453382SBill Fenner 3715b0fe478SBruce M Simpson esp = (struct newesp *)bp; 3725b0fe478SBruce M Simpson 3735b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 374a90e161bSBill Fenner secret = NULL; 3755b0fe478SBruce M Simpson advance = 0; 3765b0fe478SBruce M Simpson 3775b0fe478SBruce M Simpson if (!initialized) { 3785b0fe478SBruce M Simpson esp_init(); 3795b0fe478SBruce M Simpson initialized = 1; 3805b0fe478SBruce M Simpson } 3815b0fe478SBruce M Simpson #endif 382a90e161bSBill Fenner 383a90e161bSBill Fenner #if 0 384a90e161bSBill Fenner /* keep secret out of a register */ 385a90e161bSBill Fenner p = (u_char *)&secret; 386a90e161bSBill Fenner #endif 387b0453382SBill Fenner 388685295f4SBill Fenner /* 'ep' points to the end of available data. */ 389b0453382SBill Fenner ep = snapend; 390b0453382SBill Fenner 3915b0fe478SBruce M Simpson if ((u_char *)(esp + 1) >= ep) { 392b0453382SBill Fenner fputs("[|ESP]", stdout); 393b0453382SBill Fenner goto fail; 394b0453382SBill Fenner } 3955b0fe478SBruce M Simpson printf("ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)); 3965b0fe478SBruce M Simpson printf(",seq=0x%x", EXTRACT_32BITS(&esp->esp_seq)); 397b0453382SBill Fenner printf(")"); 398b0453382SBill Fenner 3995b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 4005b0fe478SBruce M Simpson goto fail; 4015b0fe478SBruce M Simpson #else 4025b0fe478SBruce M Simpson /* initiailize SAs */ 4035b0fe478SBruce M Simpson if (sa_list_head == NULL) { 404b0453382SBill Fenner if (!espsecret) 405b0453382SBill Fenner goto fail; 406b0453382SBill Fenner 407a90e161bSBill Fenner esp_print_decodesecret(); 408a90e161bSBill Fenner } 4095b0fe478SBruce M Simpson 4105b0fe478SBruce M Simpson if (sa_list_head == NULL) 411a90e161bSBill Fenner goto fail; 412b0453382SBill Fenner 413b0453382SBill Fenner ip = (struct ip *)bp2; 414685295f4SBill Fenner switch (IP_V(ip)) { 415b0453382SBill Fenner #ifdef INET6 416b0453382SBill Fenner case 6: 417b0453382SBill Fenner ip6 = (struct ip6_hdr *)bp2; 418b0453382SBill Fenner /* we do not attempt to decrypt jumbograms */ 4195b0fe478SBruce M Simpson if (!EXTRACT_16BITS(&ip6->ip6_plen)) 420b0453382SBill Fenner goto fail; 421b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 4225b0fe478SBruce M Simpson len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 4235b0fe478SBruce M Simpson 4245b0fe478SBruce M Simpson /* see if we can find the SA, and if so, decode it */ 4255b0fe478SBruce M Simpson for (sa = sa_list_head; sa != NULL; sa = sa->next) { 4265b0fe478SBruce M Simpson struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr; 4275b0fe478SBruce M Simpson if (sa->spi == ntohl(esp->esp_spi) && 4285b0fe478SBruce M Simpson sin6->sin6_family == AF_INET6 && 4295b0fe478SBruce M Simpson memcmp(&sin6->sin6_addr, &ip6->ip6_dst, 4305b0fe478SBruce M Simpson sizeof(struct in6_addr)) == 0) { 4315b0fe478SBruce M Simpson break; 4325b0fe478SBruce M Simpson } 4335b0fe478SBruce M Simpson } 434b0453382SBill Fenner break; 435b0453382SBill Fenner #endif /*INET6*/ 436b0453382SBill Fenner case 4: 437a90e161bSBill Fenner /* nexthdr & padding are in the last fragment */ 4385b0fe478SBruce M Simpson if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 439a90e161bSBill Fenner goto fail; 4405b0fe478SBruce M Simpson len = EXTRACT_16BITS(&ip->ip_len); 4415b0fe478SBruce M Simpson 4425b0fe478SBruce M Simpson /* see if we can find the SA, and if so, decode it */ 4435b0fe478SBruce M Simpson for (sa = sa_list_head; sa != NULL; sa = sa->next) { 4445b0fe478SBruce M Simpson struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr; 4455b0fe478SBruce M Simpson if (sa->spi == ntohl(esp->esp_spi) && 4465b0fe478SBruce M Simpson sin->sin_family == AF_INET && 4475b0fe478SBruce M Simpson sin->sin_addr.s_addr == ip->ip_dst.s_addr) { 4485b0fe478SBruce M Simpson break; 4495b0fe478SBruce M Simpson } 4505b0fe478SBruce M Simpson } 451b0453382SBill Fenner break; 452b0453382SBill Fenner default: 453b0453382SBill Fenner goto fail; 454b0453382SBill Fenner } 455b0453382SBill Fenner 4565b0fe478SBruce M Simpson /* if we didn't find the specific one, then look for 4575b0fe478SBruce M Simpson * an unspecified one. 4585b0fe478SBruce M Simpson */ 4595b0fe478SBruce M Simpson if (sa == NULL) 4605b0fe478SBruce M Simpson sa = sa_default; 4615b0fe478SBruce M Simpson 4625b0fe478SBruce M Simpson /* if not found fail */ 4635b0fe478SBruce M Simpson if (sa == NULL) 4645b0fe478SBruce M Simpson goto fail; 4655b0fe478SBruce M Simpson 466b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 467b0453382SBill Fenner if (ep - bp2 < len) 468b0453382SBill Fenner goto fail; 4695b0fe478SBruce M Simpson if (ep - bp2 > len) { 4705b0fe478SBruce M Simpson /* FCS included at end of frame (NetBSD 1.6 or later) */ 4715b0fe478SBruce M Simpson ep = bp2 + len; 472b0453382SBill Fenner } 473b0453382SBill Fenner 4745b0fe478SBruce M Simpson ivoff = (u_char *)(esp + 1) + 0; 4755b0fe478SBruce M Simpson ivlen = sa->ivlen; 4765b0fe478SBruce M Simpson secret = sa->secret; 4775b0fe478SBruce M Simpson espsecret_keylen = sa->secretlen; 478b0453382SBill Fenner 4795b0fe478SBruce M Simpson if (sa->evp) { 4805b0fe478SBruce M Simpson memset(&ctx, 0, sizeof(ctx)); 4815b0fe478SBruce M Simpson if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0) 4825b0fe478SBruce M Simpson printf("espkey init failed"); 4835b0fe478SBruce M Simpson 4845b0fe478SBruce M Simpson blocksz = EVP_CIPHER_CTX_block_size(&ctx); 4855b0fe478SBruce M Simpson 4865b0fe478SBruce M Simpson p = ivoff; 4875b0fe478SBruce M Simpson EVP_CipherInit(&ctx, NULL, NULL, p, 0); 4885b0fe478SBruce M Simpson EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); 489b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 4905b0fe478SBruce M Simpson } else 4915b0fe478SBruce M Simpson advance = sizeof(struct newesp); 492b0453382SBill Fenner 4935b0fe478SBruce M Simpson ep = ep - sa->authlen; 494b0453382SBill Fenner /* sanity check for pad length */ 495b0453382SBill Fenner if (ep - bp < *(ep - 2)) 496b0453382SBill Fenner goto fail; 497b0453382SBill Fenner 498a90e161bSBill Fenner if (padlen) 499a90e161bSBill Fenner *padlen = *(ep - 2) + 2; 500a90e161bSBill Fenner 501b0453382SBill Fenner if (nhdr) 502b0453382SBill Fenner *nhdr = *(ep - 1); 503b0453382SBill Fenner 504b0453382SBill Fenner printf(": "); 505b0453382SBill Fenner return advance; 5065b0fe478SBruce M Simpson #endif 507b0453382SBill Fenner 508b0453382SBill Fenner fail: 5095b0fe478SBruce M Simpson return -1; 510b0453382SBill Fenner } 511