1 /* $NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #ifndef lint 25 static const char rcsid[] = 26 "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.17 2000/12/12 09:58:41 itojun Exp $ (LBL)"; 27 #endif 28 29 #ifdef HAVE_CONFIG_H 30 #include "config.h" 31 #endif 32 33 #include <string.h> 34 #include <sys/param.h> 35 #include <sys/time.h> 36 #include <sys/types.h> 37 #include <sys/socket.h> 38 39 #include <netinet/in.h> 40 41 #ifdef HAVE_LIBCRYPTO 42 #include <des.h> 43 #include <blowfish.h> 44 #ifdef HAVE_RC5_H 45 #include <rc5.h> 46 #endif 47 #ifdef HAVE_CAST_H 48 #include <cast.h> 49 #endif 50 #endif 51 52 #include <stdio.h> 53 54 #include "ip.h" 55 #include "esp.h" 56 #ifdef INET6 57 #include "ip6.h" 58 #endif 59 60 #include "interface.h" 61 #include "addrtoname.h" 62 63 int 64 esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) 65 { 66 register const struct esp *esp; 67 register const u_char *ep; 68 u_int32_t spi; 69 enum { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC } algo = NONE; 70 struct ip *ip = NULL; 71 #ifdef INET6 72 struct ip6_hdr *ip6 = NULL; 73 #endif 74 int advance; 75 int len; 76 char *secret = NULL; 77 int ivlen = 0; 78 u_char *ivoff; 79 80 esp = (struct esp *)bp; 81 spi = (u_int32_t)ntohl(esp->esp_spi); 82 83 /* 'ep' points to the end of available data. */ 84 ep = snapend; 85 86 if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) { 87 fputs("[|ESP]", stdout); 88 goto fail; 89 } 90 printf("ESP(spi=0x%08x", spi); 91 printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1))); 92 printf(")"); 93 94 /* if we don't have decryption key, we can't decrypt this packet. */ 95 if (!espsecret) 96 goto fail; 97 98 if (strncmp(espsecret, "des-cbc:", 8) == 0 99 && strlen(espsecret + 8) == 8) { 100 algo = DESCBC; 101 ivlen = 8; 102 secret = espsecret + 8; 103 } else if (strncmp(espsecret, "blowfish-cbc:", 13) == 0) { 104 algo = BLOWFISH; 105 ivlen = 8; 106 secret = espsecret + 13; 107 } else if (strncmp(espsecret, "rc5-cbc:", 8) == 0) { 108 algo = RC5; 109 ivlen = 8; 110 secret = espsecret + 8; 111 } else if (strncmp(espsecret, "cast128-cbc:", 12) == 0) { 112 algo = CAST128; 113 ivlen = 8; 114 secret = espsecret + 12; 115 } else if (strncmp(espsecret, "3des-cbc:", 9) == 0 116 && strlen(espsecret + 9) == 24) { 117 algo = DES3CBC; 118 ivlen = 8; 119 secret = espsecret + 9; 120 } else if (strncmp(espsecret, "none:", 5) == 0) { 121 algo = NONE; 122 ivlen = 0; 123 secret = espsecret + 5; 124 } else if (strlen(espsecret) == 8) { 125 algo = DESCBC; 126 ivlen = 8; 127 secret = espsecret; 128 } else { 129 algo = NONE; 130 ivlen = 0; 131 secret = espsecret; 132 } 133 134 ip = (struct ip *)bp2; 135 switch (IP_V(ip)) { 136 #ifdef INET6 137 case 6: 138 ip6 = (struct ip6_hdr *)bp2; 139 ip = NULL; 140 /* we do not attempt to decrypt jumbograms */ 141 if (!ntohs(ip6->ip6_plen)) 142 goto fail; 143 /* if we can't get nexthdr, we do not need to decrypt it */ 144 len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); 145 break; 146 #endif /*INET6*/ 147 case 4: 148 #ifdef INET6 149 ip6 = NULL; 150 #endif 151 len = ntohs(ip->ip_len); 152 break; 153 default: 154 goto fail; 155 } 156 157 /* if we can't get nexthdr, we do not need to decrypt it */ 158 if (ep - bp2 < len) 159 goto fail; 160 161 if (Rflag) 162 ivoff = (u_char *)(esp + 1) + sizeof(u_int32_t); 163 else 164 ivoff = (u_char *)(esp + 1); 165 166 switch (algo) { 167 case DESCBC: 168 #ifdef HAVE_LIBCRYPTO 169 { 170 u_char iv[8]; 171 des_key_schedule schedule; 172 u_char *p; 173 174 switch (ivlen) { 175 case 4: 176 memcpy(iv, ivoff, 4); 177 memcpy(&iv[4], ivoff, 4); 178 p = &iv[4]; 179 *p++ ^= 0xff; 180 *p++ ^= 0xff; 181 *p++ ^= 0xff; 182 *p++ ^= 0xff; 183 break; 184 case 8: 185 memcpy(iv, ivoff, 8); 186 break; 187 default: 188 goto fail; 189 } 190 191 des_check_key = 0; 192 des_set_key((void *)secret, schedule); 193 194 p = ivoff + ivlen; 195 des_cbc_encrypt((void *)p, (void *)p, 196 (long)(ep - p), schedule, (void *)iv, 197 DES_DECRYPT); 198 advance = ivoff - (u_char *)esp + ivlen; 199 break; 200 } 201 #else 202 goto fail; 203 #endif /*HAVE_LIBCRYPTO*/ 204 205 case BLOWFISH: 206 #ifdef HAVE_LIBCRYPTO 207 { 208 BF_KEY schedule; 209 u_char *p; 210 211 BF_set_key(&schedule, strlen(secret), secret); 212 213 p = ivoff + ivlen; 214 BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 215 BF_DECRYPT); 216 advance = ivoff - (u_char *)esp + ivlen; 217 break; 218 } 219 #else 220 goto fail; 221 #endif /*HAVE_LIBCRYPTO*/ 222 223 case RC5: 224 #if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H) 225 { 226 RC5_32_KEY schedule; 227 u_char *p; 228 229 RC5_32_set_key(&schedule, strlen(secret), secret, 230 RC5_16_ROUNDS); 231 232 p = ivoff + ivlen; 233 RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 234 RC5_DECRYPT); 235 advance = ivoff - (u_char *)esp + ivlen; 236 break; 237 } 238 #else 239 goto fail; 240 #endif /*HAVE_LIBCRYPTO*/ 241 242 case CAST128: 243 #if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) 244 { 245 CAST_KEY schedule; 246 u_char *p; 247 248 CAST_set_key(&schedule, strlen(secret), secret); 249 250 p = ivoff + ivlen; 251 CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 252 CAST_DECRYPT); 253 advance = ivoff - (u_char *)esp + ivlen; 254 break; 255 } 256 #else 257 goto fail; 258 #endif /*HAVE_LIBCRYPTO*/ 259 260 case DES3CBC: 261 #if defined(HAVE_LIBCRYPTO) 262 { 263 des_key_schedule s1, s2, s3; 264 u_char *p; 265 266 des_check_key = 0; 267 des_set_key((void *)secret, s1); 268 des_set_key((void *)(secret + 8), s2); 269 des_set_key((void *)(secret + 16), s3); 270 271 p = ivoff + ivlen; 272 des_ede3_cbc_encrypt((void *)p, (void *)p, 273 (long)(ep - p), s1, s2, s3, (void *)ivoff, DES_DECRYPT); 274 advance = ivoff - (u_char *)esp + ivlen; 275 break; 276 } 277 #else 278 goto fail; 279 #endif /*HAVE_LIBCRYPTO*/ 280 281 case NONE: 282 default: 283 if (Rflag) 284 advance = sizeof(struct esp) + sizeof(u_int32_t); 285 else 286 advance = sizeof(struct esp); 287 break; 288 } 289 290 /* sanity check for pad length */ 291 if (ep - bp < *(ep - 2)) 292 goto fail; 293 294 if (nhdr) 295 *nhdr = *(ep - 1); 296 297 printf(": "); 298 return advance; 299 300 fail: 301 if (nhdr) 302 *nhdr = -1; 303 return 65536; 304 } 305