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_ = 26f4d0c64aSSam Leffler "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.55.2.1 2005/04/21 06:44:57 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 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; 745b0fe478SBruce M Simpson u_int32_t spi; 755b0fe478SBruce M Simpson const EVP_CIPHER *evp; 76a90e161bSBill Fenner int ivlen; 77a90e161bSBill Fenner int authlen; 78f4d0c64aSSam Leffler u_char secret[256]; /* is that big enough for all secrets? */ 795b0fe478SBruce M Simpson int secretlen; 80a90e161bSBill Fenner }; 81a90e161bSBill Fenner 821de50e9fSSam Leffler static void esp_print_addsa(netdissect_options *ndo, 831de50e9fSSam Leffler struct sa_list *sa, int sa_def) 845b0fe478SBruce M Simpson { 855b0fe478SBruce M Simpson /* copy the "sa" */ 865b0fe478SBruce M Simpson 875b0fe478SBruce M Simpson struct sa_list *nsa; 885b0fe478SBruce M Simpson 895b0fe478SBruce M Simpson nsa = (struct sa_list *)malloc(sizeof(struct sa_list)); 905b0fe478SBruce M Simpson if (nsa == NULL) 911de50e9fSSam Leffler (*ndo->ndo_error)(ndo, "ran out of memory to allocate sa structure"); 925b0fe478SBruce M Simpson 935b0fe478SBruce M Simpson *nsa = *sa; 945b0fe478SBruce M Simpson 955b0fe478SBruce M Simpson if (sa_def) 961de50e9fSSam Leffler ndo->ndo_sa_default = nsa; 975b0fe478SBruce M Simpson 981de50e9fSSam Leffler nsa->next = ndo->ndo_sa_list_head; 991de50e9fSSam Leffler ndo->ndo_sa_list_head = nsa; 1005b0fe478SBruce M Simpson } 1015b0fe478SBruce M Simpson 102a90e161bSBill Fenner 103f4d0c64aSSam Leffler static u_int hexdigit(netdissect_options *ndo, char hex) 104a90e161bSBill Fenner { 1055b0fe478SBruce M Simpson if (hex >= '0' && hex <= '9') 106a90e161bSBill Fenner return (hex - '0'); 1075b0fe478SBruce M Simpson else if (hex >= 'A' && hex <= 'F') 108a90e161bSBill Fenner return (hex - 'A' + 10); 1095b0fe478SBruce M Simpson else if (hex >= 'a' && hex <= 'f') 110a90e161bSBill Fenner return (hex - 'a' + 10); 1115b0fe478SBruce M Simpson else { 1121de50e9fSSam Leffler (*ndo->ndo_error)(ndo, "invalid hex digit %c in espsecret\n", hex); 113a90e161bSBill Fenner return 0; 114a90e161bSBill Fenner } 115a90e161bSBill Fenner } 116a90e161bSBill Fenner 117f4d0c64aSSam Leffler static u_int hex2byte(netdissect_options *ndo, char *hexstring) 118a90e161bSBill Fenner { 119f4d0c64aSSam Leffler u_int byte; 120a90e161bSBill Fenner 1211de50e9fSSam Leffler byte = (hexdigit(ndo, hexstring[0]) << 4) + hexdigit(ndo, hexstring[1]); 122a90e161bSBill Fenner return byte; 123a90e161bSBill Fenner } 124a90e161bSBill Fenner 1255b0fe478SBruce M Simpson /* 1265b0fe478SBruce M Simpson * decode the form: SPINUM@IP <tab> ALGONAME:0xsecret 1275b0fe478SBruce M Simpson * 1285b0fe478SBruce M Simpson * special form: file /name 1295b0fe478SBruce M Simpson * causes us to go read from this file instead. 1305b0fe478SBruce M Simpson * 1315b0fe478SBruce M Simpson */ 1321de50e9fSSam Leffler static void esp_print_decode_onesecret(netdissect_options *ndo, char *line) 133a90e161bSBill Fenner { 1345b0fe478SBruce M Simpson struct sa_list sa1; 1355b0fe478SBruce M Simpson int sa_def; 136a90e161bSBill Fenner 1375b0fe478SBruce M Simpson char *spikey; 1385b0fe478SBruce M Simpson char *decode; 1395b0fe478SBruce M Simpson 1405b0fe478SBruce M Simpson spikey = strsep(&line, " \t"); 1415b0fe478SBruce M Simpson sa_def = 0; 1425b0fe478SBruce M Simpson memset(&sa1, 0, sizeof(struct sa_list)); 1435b0fe478SBruce M Simpson 1445b0fe478SBruce M Simpson /* if there is only one token, then it is an algo:key token */ 1455b0fe478SBruce M Simpson if (line == NULL) { 1465b0fe478SBruce M Simpson decode = spikey; 1475b0fe478SBruce M Simpson spikey = NULL; 1485b0fe478SBruce M Simpson /* memset(&sa1.daddr, 0, sizeof(sa1.daddr)); */ 1495b0fe478SBruce M Simpson /* sa1.spi = 0; */ 1505b0fe478SBruce M Simpson sa_def = 1; 1515b0fe478SBruce M Simpson } else 1525b0fe478SBruce M Simpson decode = line; 1535b0fe478SBruce M Simpson 1545b0fe478SBruce M Simpson if (spikey && strcasecmp(spikey, "file") == 0) { 1555b0fe478SBruce M Simpson /* open file and read it */ 1565b0fe478SBruce M Simpson FILE *secretfile; 1575b0fe478SBruce M Simpson char fileline[1024]; 1585b0fe478SBruce M Simpson char *nl; 1595b0fe478SBruce M Simpson 1605b0fe478SBruce M Simpson secretfile = fopen(line, FOPEN_READ_TXT); 1615b0fe478SBruce M Simpson if (secretfile == NULL) { 1625b0fe478SBruce M Simpson perror(line); 1635b0fe478SBruce M Simpson exit(3); 1645b0fe478SBruce M Simpson } 1655b0fe478SBruce M Simpson 1665b0fe478SBruce M Simpson while (fgets(fileline, sizeof(fileline)-1, secretfile) != NULL) { 1675b0fe478SBruce M Simpson /* remove newline from the line */ 1685b0fe478SBruce M Simpson nl = strchr(fileline, '\n'); 1695b0fe478SBruce M Simpson if (nl) 1705b0fe478SBruce M Simpson *nl = '\0'; 1715b0fe478SBruce M Simpson if (fileline[0] == '#') continue; 1725b0fe478SBruce M Simpson if (fileline[0] == '\0') continue; 1735b0fe478SBruce M Simpson 1741de50e9fSSam Leffler esp_print_decode_onesecret(ndo, fileline); 1755b0fe478SBruce M Simpson } 1765b0fe478SBruce M Simpson fclose(secretfile); 1775b0fe478SBruce M Simpson 178a90e161bSBill Fenner return; 179a90e161bSBill Fenner } 180a90e161bSBill Fenner 1815b0fe478SBruce M Simpson if (spikey) { 1825b0fe478SBruce M Simpson char *spistr, *foo; 1835b0fe478SBruce M Simpson u_int32_t spino; 1845b0fe478SBruce M Simpson struct sockaddr_in *sin; 1855b0fe478SBruce M Simpson #ifdef INET6 1865b0fe478SBruce M Simpson struct sockaddr_in6 *sin6; 1875b0fe478SBruce M Simpson #endif 1885b0fe478SBruce M Simpson 1895b0fe478SBruce M Simpson spistr = strsep(&spikey, "@"); 1905b0fe478SBruce M Simpson 1915b0fe478SBruce M Simpson spino = strtoul(spistr, &foo, 0); 1925b0fe478SBruce M Simpson if (spistr == foo || !spikey) { 1931de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "print_esp: failed to decode spi# %s\n", foo); 194a90e161bSBill Fenner return; 195a90e161bSBill Fenner } 196a90e161bSBill Fenner 1975b0fe478SBruce M Simpson sa1.spi = spino; 1985b0fe478SBruce M Simpson 1995b0fe478SBruce M Simpson sin = (struct sockaddr_in *)&sa1.daddr; 2005b0fe478SBruce M Simpson #ifdef INET6 2015b0fe478SBruce M Simpson sin6 = (struct sockaddr_in6 *)&sa1.daddr; 2025b0fe478SBruce M Simpson if (inet_pton(AF_INET6, spikey, &sin6->sin6_addr) == 1) { 2035b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN 2045b0fe478SBruce M Simpson sin6->sin6_len = sizeof(struct sockaddr_in6); 2055b0fe478SBruce M Simpson #endif 2065b0fe478SBruce M Simpson sin6->sin6_family = AF_INET6; 2075b0fe478SBruce M Simpson } else 2085b0fe478SBruce M Simpson #endif 2095b0fe478SBruce M Simpson if (inet_pton(AF_INET, spikey, &sin->sin_addr) == 1) { 2105b0fe478SBruce M Simpson #ifdef HAVE_SOCKADDR_SA_LEN 2115b0fe478SBruce M Simpson sin->sin_len = sizeof(struct sockaddr_in); 2125b0fe478SBruce M Simpson #endif 2135b0fe478SBruce M Simpson sin->sin_family = AF_INET; 2145b0fe478SBruce M Simpson } else { 2151de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "print_esp: can not decode IP# %s\n", spikey); 2165b0fe478SBruce M Simpson return; 2175b0fe478SBruce M Simpson } 2185b0fe478SBruce M Simpson } 2195b0fe478SBruce M Simpson 2205b0fe478SBruce M Simpson if (decode) { 2215b0fe478SBruce M Simpson char *colon, *p; 222f4d0c64aSSam Leffler u_char espsecret_key[256]; 2235b0fe478SBruce M Simpson int len; 2245b0fe478SBruce M Simpson size_t i; 2255b0fe478SBruce M Simpson const EVP_CIPHER *evp; 2265b0fe478SBruce M Simpson int authlen = 0; 2275b0fe478SBruce M Simpson 2285b0fe478SBruce M Simpson /* skip any blank spaces */ 2295b0fe478SBruce M Simpson while (isspace((unsigned char)*decode)) 2305b0fe478SBruce M Simpson decode++; 2315b0fe478SBruce M Simpson 2325b0fe478SBruce M Simpson colon = strchr(decode, ':'); 233a90e161bSBill Fenner if (colon == NULL) { 2341de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "failed to decode espsecret: %s\n", decode); 235a90e161bSBill Fenner return; 236a90e161bSBill Fenner } 2375b0fe478SBruce M Simpson *colon = '\0'; 2385b0fe478SBruce M Simpson 2395b0fe478SBruce M Simpson len = colon - decode; 2405b0fe478SBruce M Simpson if (strlen(decode) > strlen("-hmac96") && 2415b0fe478SBruce M Simpson !strcmp(decode + strlen(decode) - strlen("-hmac96"), 2425b0fe478SBruce M Simpson "-hmac96")) { 2435b0fe478SBruce M Simpson p = strstr(decode, "-hmac96"); 2445b0fe478SBruce M Simpson *p = '\0'; 2455b0fe478SBruce M Simpson authlen = 12; 2465b0fe478SBruce M Simpson } 2475b0fe478SBruce M Simpson if (strlen(decode) > strlen("-cbc") && 2485b0fe478SBruce M Simpson !strcmp(decode + strlen(decode) - strlen("-cbc"), "-cbc")) { 2495b0fe478SBruce M Simpson p = strstr(decode, "-cbc"); 2505b0fe478SBruce M Simpson *p = '\0'; 2515b0fe478SBruce M Simpson } 2525b0fe478SBruce M Simpson evp = EVP_get_cipherbyname(decode); 2535b0fe478SBruce M Simpson if (!evp) { 2541de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "failed to find cipher algo %s\n", decode); 2555b0fe478SBruce M Simpson sa1.evp = NULL; 2565b0fe478SBruce M Simpson sa1.authlen = 0; 2575b0fe478SBruce M Simpson sa1.ivlen = 0; 2585b0fe478SBruce M Simpson return; 2595b0fe478SBruce M Simpson } 2605b0fe478SBruce M Simpson 2615b0fe478SBruce M Simpson sa1.evp = evp; 2625b0fe478SBruce M Simpson sa1.authlen = authlen; 2631de50e9fSSam Leffler sa1.ivlen = EVP_CIPHER_iv_length(evp); 264a90e161bSBill Fenner 265a90e161bSBill Fenner colon++; 266a90e161bSBill Fenner if (colon[0] == '0' && colon[1] == 'x') { 267a90e161bSBill Fenner /* decode some hex! */ 268a90e161bSBill Fenner colon += 2; 269a90e161bSBill Fenner len = strlen(colon) / 2; 2705b0fe478SBruce M Simpson 2715b0fe478SBruce M Simpson if (len > 256) { 2721de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "secret is too big: %d\n", len); 2735b0fe478SBruce M Simpson return; 274a90e161bSBill Fenner } 2755b0fe478SBruce M Simpson 276a90e161bSBill Fenner i = 0; 277a90e161bSBill Fenner while (colon[0] != '\0' && colon[1]!='\0') { 2781de50e9fSSam Leffler espsecret_key[i] = hex2byte(ndo, colon); 279a90e161bSBill Fenner colon += 2; 280a90e161bSBill Fenner i++; 281a90e161bSBill Fenner } 2825b0fe478SBruce M Simpson 2835b0fe478SBruce M Simpson memcpy(sa1.secret, espsecret_key, i); 2845b0fe478SBruce M Simpson sa1.secretlen = i; 285a90e161bSBill Fenner } else { 2865b0fe478SBruce M Simpson i = strlen(colon); 2875b0fe478SBruce M Simpson 2885b0fe478SBruce M Simpson if (i < sizeof(sa1.secret)) { 2895b0fe478SBruce M Simpson memcpy(sa1.secret, colon, i); 2905b0fe478SBruce M Simpson sa1.secretlen = i; 2915b0fe478SBruce M Simpson } else { 2925b0fe478SBruce M Simpson memcpy(sa1.secret, colon, sizeof(sa1.secret)); 2935b0fe478SBruce M Simpson sa1.secretlen = sizeof(sa1.secret); 2945b0fe478SBruce M Simpson } 295a90e161bSBill Fenner } 296a90e161bSBill Fenner } 297a90e161bSBill Fenner 2981de50e9fSSam Leffler esp_print_addsa(ndo, &sa1, sa_def); 2995b0fe478SBruce M Simpson } 3005b0fe478SBruce M Simpson 3011de50e9fSSam Leffler static void esp_print_decodesecret(netdissect_options *ndo) 302b0453382SBill Fenner { 3035b0fe478SBruce M Simpson char *line; 3045b0fe478SBruce M Simpson char *p; 3055b0fe478SBruce M Simpson 3061de50e9fSSam Leffler p = ndo->ndo_espsecret; 3075b0fe478SBruce M Simpson 3081de50e9fSSam Leffler while (ndo->ndo_espsecret && ndo->ndo_espsecret[0] != '\0') { 3095b0fe478SBruce M Simpson /* pick out the first line or first thing until a comma */ 3101de50e9fSSam Leffler if ((line = strsep(&ndo->ndo_espsecret, "\n,")) == NULL) { 3111de50e9fSSam Leffler line = ndo->ndo_espsecret; 3121de50e9fSSam Leffler ndo->ndo_espsecret = NULL; 3135b0fe478SBruce M Simpson } 3145b0fe478SBruce M Simpson 3151de50e9fSSam Leffler esp_print_decode_onesecret(ndo, line); 3165b0fe478SBruce M Simpson } 3175b0fe478SBruce M Simpson } 3185b0fe478SBruce M Simpson 3191de50e9fSSam Leffler static void esp_init(netdissect_options *ndo _U_) 3205b0fe478SBruce M Simpson { 3215b0fe478SBruce M Simpson 3225b0fe478SBruce M Simpson OpenSSL_add_all_algorithms(); 3235b0fe478SBruce M Simpson EVP_add_cipher_alias(SN_des_ede3_cbc, "3des"); 3245b0fe478SBruce M Simpson } 3255b0fe478SBruce M Simpson #endif 3265b0fe478SBruce M Simpson 3275b0fe478SBruce M Simpson int 3281de50e9fSSam Leffler esp_print(netdissect_options *ndo, 3291de50e9fSSam Leffler const u_char *bp, const int length, const u_char *bp2 3305b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3315b0fe478SBruce M Simpson _U_ 3325b0fe478SBruce M Simpson #endif 3335b0fe478SBruce M Simpson , 3345b0fe478SBruce M Simpson int *nhdr 3355b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3365b0fe478SBruce M Simpson _U_ 3375b0fe478SBruce M Simpson #endif 3385b0fe478SBruce M Simpson , 3395b0fe478SBruce M Simpson int *padlen 3405b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3415b0fe478SBruce M Simpson _U_ 3425b0fe478SBruce M Simpson #endif 3435b0fe478SBruce M Simpson ) 3445b0fe478SBruce M Simpson { 3455b0fe478SBruce M Simpson register const struct newesp *esp; 346b0453382SBill Fenner register const u_char *ep; 3475b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 3485b0fe478SBruce M Simpson struct ip *ip; 3495b0fe478SBruce M Simpson struct sa_list *sa = NULL; 3505b0fe478SBruce M Simpson int espsecret_keylen; 351b0453382SBill Fenner #ifdef INET6 352b0453382SBill Fenner struct ip6_hdr *ip6 = NULL; 353b0453382SBill Fenner #endif 354b0453382SBill Fenner int advance; 355b0453382SBill Fenner int len; 356f4d0c64aSSam Leffler u_char *secret; 357b0453382SBill Fenner int ivlen = 0; 358b0453382SBill Fenner u_char *ivoff; 3591de50e9fSSam Leffler u_char *p; 3605b0fe478SBruce M Simpson EVP_CIPHER_CTX ctx; 3615b0fe478SBruce M Simpson int blocksz; 3625b0fe478SBruce M Simpson static int initialized = 0; 3635b0fe478SBruce M Simpson #endif 364b0453382SBill Fenner 3655b0fe478SBruce M Simpson esp = (struct newesp *)bp; 3665b0fe478SBruce M Simpson 3675b0fe478SBruce M Simpson #ifdef HAVE_LIBCRYPTO 368a90e161bSBill Fenner secret = NULL; 3695b0fe478SBruce M Simpson advance = 0; 3705b0fe478SBruce M Simpson 3715b0fe478SBruce M Simpson if (!initialized) { 3721de50e9fSSam Leffler esp_init(ndo); 3735b0fe478SBruce M Simpson initialized = 1; 3745b0fe478SBruce M Simpson } 3755b0fe478SBruce M Simpson #endif 376a90e161bSBill Fenner 377a90e161bSBill Fenner #if 0 378a90e161bSBill Fenner /* keep secret out of a register */ 379a90e161bSBill Fenner p = (u_char *)&secret; 380a90e161bSBill Fenner #endif 381b0453382SBill Fenner 382685295f4SBill Fenner /* 'ep' points to the end of available data. */ 3831de50e9fSSam Leffler ep = ndo->ndo_snapend; 384b0453382SBill Fenner 3855b0fe478SBruce M Simpson if ((u_char *)(esp + 1) >= ep) { 386b0453382SBill Fenner fputs("[|ESP]", stdout); 387b0453382SBill Fenner goto fail; 388b0453382SBill Fenner } 3891de50e9fSSam Leffler (*ndo->ndo_printf)(ndo, "ESP(spi=0x%08x", EXTRACT_32BITS(&esp->esp_spi)); 3901de50e9fSSam Leffler (*ndo->ndo_printf)(ndo, ",seq=0x%x)", EXTRACT_32BITS(&esp->esp_seq)); 3911de50e9fSSam Leffler (*ndo->ndo_printf)(ndo, ", length %u", length); 392b0453382SBill Fenner 3935b0fe478SBruce M Simpson #ifndef HAVE_LIBCRYPTO 3945b0fe478SBruce M Simpson goto fail; 3955b0fe478SBruce M Simpson #else 3965b0fe478SBruce M Simpson /* initiailize SAs */ 3971de50e9fSSam Leffler if (ndo->ndo_sa_list_head == NULL) { 3981de50e9fSSam Leffler if (!ndo->ndo_espsecret) 399b0453382SBill Fenner goto fail; 400b0453382SBill Fenner 4011de50e9fSSam Leffler esp_print_decodesecret(ndo); 402a90e161bSBill Fenner } 4035b0fe478SBruce M Simpson 4041de50e9fSSam Leffler if (ndo->ndo_sa_list_head == NULL) 405a90e161bSBill Fenner goto fail; 406b0453382SBill Fenner 407b0453382SBill Fenner ip = (struct ip *)bp2; 408685295f4SBill Fenner switch (IP_V(ip)) { 409b0453382SBill Fenner #ifdef INET6 410b0453382SBill Fenner case 6: 411b0453382SBill Fenner ip6 = (struct ip6_hdr *)bp2; 412b0453382SBill Fenner /* we do not attempt to decrypt jumbograms */ 4135b0fe478SBruce M Simpson if (!EXTRACT_16BITS(&ip6->ip6_plen)) 414b0453382SBill Fenner goto fail; 415b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 4165b0fe478SBruce M Simpson len = sizeof(struct ip6_hdr) + EXTRACT_16BITS(&ip6->ip6_plen); 4175b0fe478SBruce M Simpson 4185b0fe478SBruce M Simpson /* see if we can find the SA, and if so, decode it */ 4191de50e9fSSam Leffler for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 4205b0fe478SBruce M Simpson struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa->daddr; 4215b0fe478SBruce M Simpson if (sa->spi == ntohl(esp->esp_spi) && 4225b0fe478SBruce M Simpson sin6->sin6_family == AF_INET6 && 4235b0fe478SBruce M Simpson memcmp(&sin6->sin6_addr, &ip6->ip6_dst, 4245b0fe478SBruce M Simpson sizeof(struct in6_addr)) == 0) { 4255b0fe478SBruce M Simpson break; 4265b0fe478SBruce M Simpson } 4275b0fe478SBruce M Simpson } 428b0453382SBill Fenner break; 429b0453382SBill Fenner #endif /*INET6*/ 430b0453382SBill Fenner case 4: 431a90e161bSBill Fenner /* nexthdr & padding are in the last fragment */ 4325b0fe478SBruce M Simpson if (EXTRACT_16BITS(&ip->ip_off) & IP_MF) 433a90e161bSBill Fenner goto fail; 4345b0fe478SBruce M Simpson len = EXTRACT_16BITS(&ip->ip_len); 4355b0fe478SBruce M Simpson 4365b0fe478SBruce M Simpson /* see if we can find the SA, and if so, decode it */ 4371de50e9fSSam Leffler for (sa = ndo->ndo_sa_list_head; sa != NULL; sa = sa->next) { 4385b0fe478SBruce M Simpson struct sockaddr_in *sin = (struct sockaddr_in *)&sa->daddr; 4395b0fe478SBruce M Simpson if (sa->spi == ntohl(esp->esp_spi) && 4405b0fe478SBruce M Simpson sin->sin_family == AF_INET && 4415b0fe478SBruce M Simpson sin->sin_addr.s_addr == ip->ip_dst.s_addr) { 4425b0fe478SBruce M Simpson break; 4435b0fe478SBruce M Simpson } 4445b0fe478SBruce M Simpson } 445b0453382SBill Fenner break; 446b0453382SBill Fenner default: 447b0453382SBill Fenner goto fail; 448b0453382SBill Fenner } 449b0453382SBill Fenner 4505b0fe478SBruce M Simpson /* if we didn't find the specific one, then look for 4515b0fe478SBruce M Simpson * an unspecified one. 4525b0fe478SBruce M Simpson */ 4535b0fe478SBruce M Simpson if (sa == NULL) 4541de50e9fSSam Leffler sa = ndo->ndo_sa_default; 4555b0fe478SBruce M Simpson 4565b0fe478SBruce M Simpson /* if not found fail */ 4575b0fe478SBruce M Simpson if (sa == NULL) 4585b0fe478SBruce M Simpson goto fail; 4595b0fe478SBruce M Simpson 460b0453382SBill Fenner /* if we can't get nexthdr, we do not need to decrypt it */ 461b0453382SBill Fenner if (ep - bp2 < len) 462b0453382SBill Fenner goto fail; 4635b0fe478SBruce M Simpson if (ep - bp2 > len) { 4645b0fe478SBruce M Simpson /* FCS included at end of frame (NetBSD 1.6 or later) */ 4655b0fe478SBruce M Simpson ep = bp2 + len; 466b0453382SBill Fenner } 467b0453382SBill Fenner 4685b0fe478SBruce M Simpson ivoff = (u_char *)(esp + 1) + 0; 4695b0fe478SBruce M Simpson ivlen = sa->ivlen; 4705b0fe478SBruce M Simpson secret = sa->secret; 4715b0fe478SBruce M Simpson espsecret_keylen = sa->secretlen; 4721de50e9fSSam Leffler ep = ep - sa->authlen; 473b0453382SBill Fenner 4745b0fe478SBruce M Simpson if (sa->evp) { 4755b0fe478SBruce M Simpson memset(&ctx, 0, sizeof(ctx)); 4765b0fe478SBruce M Simpson if (EVP_CipherInit(&ctx, sa->evp, secret, NULL, 0) < 0) 4771de50e9fSSam Leffler (*ndo->ndo_warning)(ndo, "espkey init failed"); 4785b0fe478SBruce M Simpson 4795b0fe478SBruce M Simpson blocksz = EVP_CIPHER_CTX_block_size(&ctx); 4805b0fe478SBruce M Simpson 4815b0fe478SBruce M Simpson p = ivoff; 4825b0fe478SBruce M Simpson EVP_CipherInit(&ctx, NULL, NULL, p, 0); 4835b0fe478SBruce M Simpson EVP_Cipher(&ctx, p + ivlen, p + ivlen, ep - (p + ivlen)); 484b0453382SBill Fenner advance = ivoff - (u_char *)esp + ivlen; 4855b0fe478SBruce M Simpson } else 4865b0fe478SBruce M Simpson advance = sizeof(struct newesp); 487b0453382SBill Fenner 488b0453382SBill Fenner /* sanity check for pad length */ 489b0453382SBill Fenner if (ep - bp < *(ep - 2)) 490b0453382SBill Fenner goto fail; 491b0453382SBill Fenner 492a90e161bSBill Fenner if (padlen) 493a90e161bSBill Fenner *padlen = *(ep - 2) + 2; 494a90e161bSBill Fenner 495b0453382SBill Fenner if (nhdr) 496b0453382SBill Fenner *nhdr = *(ep - 1); 497b0453382SBill Fenner 4981de50e9fSSam Leffler (ndo->ndo_printf)(ndo, ": "); 499b0453382SBill Fenner return advance; 5005b0fe478SBruce M Simpson #endif 501b0453382SBill Fenner 502b0453382SBill Fenner fail: 5035b0fe478SBruce M Simpson return -1; 504b0453382SBill Fenner } 5051de50e9fSSam Leffler 5061de50e9fSSam Leffler /* 5071de50e9fSSam Leffler * Local Variables: 5081de50e9fSSam Leffler * c-style: whitesmith 5091de50e9fSSam Leffler * c-basic-offset: 8 5101de50e9fSSam Leffler * End: 5111de50e9fSSam Leffler */ 512