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.5 1999/12/15 08:10:18 fenner 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 <net/route.h> 40 #include <net/if.h> 41 42 #include <netinet/in.h> 43 #include <netinet/if_ether.h> 44 #include <netinet/in_systm.h> 45 #include <netinet/ip.h> 46 #include <netinet/ip_icmp.h> 47 #include <netinet/ip_var.h> 48 #include <netinet/udp.h> 49 #include <netinet/udp_var.h> 50 #include <netinet/tcp.h> 51 52 #ifdef CRYPTO 53 #include <des.h> 54 #include <blowfish.h> 55 #ifdef HAVE_RC5_H 56 #include <rc5.h> 57 #endif 58 #ifdef HAVE_CAST_H 59 #include <cast.h> 60 #endif 61 #endif 62 63 #include <stdio.h> 64 65 #ifdef INET6 66 #include <netinet/ip6.h> 67 #endif 68 69 /* there's no standard definition so we are on our own */ 70 struct esp { 71 u_int32_t esp_spi; /* ESP */ 72 /*variable size, 32bit bound*/ /* Initialization Vector */ 73 /*variable size*/ /* Payload data */ 74 /*variable size*/ /* padding */ 75 /*8bit*/ /* pad size */ 76 /*8bit*/ /* next header */ 77 /*8bit*/ /* next header */ 78 /*variable size, 32bit bound*/ /* Authentication data (new IPsec) */ 79 }; 80 81 struct newesp { 82 u_int32_t esp_spi; /* ESP */ 83 u_int32_t esp_seq; /* Sequence number */ 84 /*variable size*/ /* (IV and) Payload data */ 85 /*variable size*/ /* padding */ 86 /*8bit*/ /* pad size */ 87 /*8bit*/ /* next header */ 88 /*8bit*/ /* next header */ 89 /*variable size, 32bit bound*/ /* Authentication data */ 90 }; 91 92 #include "interface.h" 93 #include "addrtoname.h" 94 95 int 96 esp_print(register const u_char *bp, register const u_char *bp2, int *nhdr) 97 { 98 register const struct esp *esp; 99 register const u_char *ep; 100 u_int32_t spi; 101 enum { NONE, DESCBC, BLOWFISH, RC5, CAST128, DES3CBC } algo = NONE; 102 struct ip *ip = NULL; 103 #ifdef INET6 104 struct ip6_hdr *ip6 = NULL; 105 #endif 106 int advance; 107 int len; 108 char *secret = NULL; 109 int ivlen = 0; 110 u_char *ivoff; 111 112 esp = (struct esp *)bp; 113 spi = (u_int32_t)ntohl(esp->esp_spi); 114 115 /* 'ep' points to the end of avaible data. */ 116 ep = snapend; 117 118 if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) { 119 fputs("[|ESP]", stdout); 120 goto fail; 121 } 122 printf("ESP(spi=%u", spi); 123 printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1))); 124 printf(")"); 125 126 /* if we don't have decryption key, we can't decrypt this packet. */ 127 if (!espsecret) 128 goto fail; 129 130 if (strncmp(espsecret, "des-cbc:", 8) == 0 131 && strlen(espsecret + 8) == 8) { 132 algo = DESCBC; 133 ivlen = 8; 134 secret = espsecret + 8; 135 } else if (strncmp(espsecret, "blowfish-cbc:", 13) == 0) { 136 algo = BLOWFISH; 137 ivlen = 8; 138 secret = espsecret + 13; 139 } else if (strncmp(espsecret, "rc5-cbc:", 8) == 0) { 140 algo = RC5; 141 ivlen = 8; 142 secret = espsecret + 8; 143 } else if (strncmp(espsecret, "cast128-cbc:", 12) == 0) { 144 algo = CAST128; 145 ivlen = 8; 146 secret = espsecret + 12; 147 } else if (strncmp(espsecret, "3des-cbc:", 9) == 0 148 && strlen(espsecret + 9) == 24) { 149 algo = DES3CBC; 150 ivlen = 8; 151 secret = espsecret + 9; 152 } else if (strncmp(espsecret, "none:", 5) == 0) { 153 algo = NONE; 154 ivlen = 0; 155 secret = espsecret + 5; 156 } else if (strlen(espsecret) == 8) { 157 algo = DESCBC; 158 ivlen = 8; 159 secret = espsecret; 160 } else { 161 algo = NONE; 162 ivlen = 0; 163 secret = espsecret; 164 } 165 166 ip = (struct ip *)bp2; 167 switch (ip->ip_v) { 168 #ifdef INET6 169 case 6: 170 ip6 = (struct ip6_hdr *)bp2; 171 ip = NULL; 172 /* we do not attempt to decrypt jumbograms */ 173 if (!ntohs(ip6->ip6_plen)) 174 goto fail; 175 /* if we can't get nexthdr, we do not need to decrypt it */ 176 len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen); 177 break; 178 #endif /*INET6*/ 179 case 4: 180 #ifdef INET6 181 ip6 = NULL; 182 #endif 183 len = ntohs(ip->ip_len); 184 break; 185 default: 186 goto fail; 187 } 188 189 /* if we can't get nexthdr, we do not need to decrypt it */ 190 if (ep - bp2 < len) 191 goto fail; 192 193 if (Rflag) 194 ivoff = (u_char *)(esp + 1) + sizeof(u_int32_t); 195 else 196 ivoff = (u_char *)(esp + 1); 197 198 switch (algo) { 199 case DESCBC: 200 #ifdef CRYPTO 201 { 202 u_char iv[8]; 203 des_key_schedule schedule; 204 u_char *p; 205 206 switch (ivlen) { 207 case 4: 208 memcpy(iv, ivoff, 4); 209 memcpy(&iv[4], ivoff, 4); 210 p = &iv[4]; 211 *p++ ^= 0xff; 212 *p++ ^= 0xff; 213 *p++ ^= 0xff; 214 *p++ ^= 0xff; 215 break; 216 case 8: 217 memcpy(iv, ivoff, 8); 218 break; 219 default: 220 goto fail; 221 } 222 223 des_check_key = 0; 224 des_set_key((void *)secret, schedule); 225 226 p = ivoff + ivlen; 227 des_cbc_encrypt((void *)p, (void *)p, 228 (long)(ep - p), schedule, (void *)iv, 229 DES_DECRYPT); 230 advance = ivoff - (u_char *)esp + ivlen; 231 break; 232 } 233 #else 234 goto fail; 235 #endif /*CRYPTO*/ 236 237 case BLOWFISH: 238 #ifdef CRYPTO 239 { 240 BF_KEY schedule; 241 u_char *p; 242 243 BF_set_key(&schedule, strlen(secret), secret); 244 245 p = ivoff + ivlen; 246 BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 247 BF_DECRYPT); 248 advance = ivoff - (u_char *)esp + ivlen; 249 break; 250 } 251 #else 252 goto fail; 253 #endif /*CRYPTO*/ 254 255 case RC5: 256 #if defined(CRYPTO) && defined(HAVE_RC5_H) 257 { 258 RC5_32_KEY schedule; 259 u_char *p; 260 261 RC5_32_set_key(&schedule, strlen(secret), secret, 262 RC5_16_ROUNDS); 263 264 p = ivoff + ivlen; 265 RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 266 RC5_DECRYPT); 267 advance = ivoff - (u_char *)esp + ivlen; 268 break; 269 } 270 #else 271 goto fail; 272 #endif /*CRYPTO*/ 273 274 case CAST128: 275 #if defined(CRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128) 276 { 277 CAST_KEY schedule; 278 u_char *p; 279 280 CAST_set_key(&schedule, strlen(secret), secret); 281 282 p = ivoff + ivlen; 283 CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff, 284 CAST_DECRYPT); 285 advance = ivoff - (u_char *)esp + ivlen; 286 break; 287 } 288 #else 289 goto fail; 290 #endif /*CRYPTO*/ 291 292 case DES3CBC: 293 #if defined(CRYPTO) 294 { 295 des_key_schedule s1, s2, s3; 296 u_char *p; 297 298 des_check_key = 0; 299 des_set_key((void *)secret, s1); 300 des_set_key((void *)(secret + 8), s2); 301 des_set_key((void *)(secret + 16), s3); 302 303 p = ivoff + ivlen; 304 des_ede3_cbc_encrypt((void *)p, (void *)p, 305 (long)(ep - p), s1, s2, s3, (void *)ivoff, DES_DECRYPT); 306 advance = ivoff - (u_char *)esp + ivlen; 307 break; 308 } 309 #else 310 goto fail; 311 #endif /*CRYPTO*/ 312 313 case NONE: 314 default: 315 if (Rflag) 316 advance = sizeof(struct esp) + sizeof(u_int32_t); 317 else 318 advance = sizeof(struct esp); 319 break; 320 } 321 322 /* sanity check for pad length */ 323 if (ep - bp < *(ep - 2)) 324 goto fail; 325 326 if (nhdr) 327 *nhdr = *(ep - 1); 328 329 printf(": "); 330 return advance; 331 332 fail: 333 if (nhdr) 334 *nhdr = -1; 335 return 65536; 336 } 337