Home | History | Annotate | Line # | Download | only in dist
signature.c revision 1.2.12.2
      1 /*
      2  * Redistribution and use in source and binary forms, with or without
      3  * modification, are permitted provided that: (1) source code
      4  * distributions retain the above copyright notice and this paragraph
      5  * in its entirety, and (2) distributions including binary code include
      6  * the above copyright notice and this paragraph in its entirety in
      7  * the documentation or other materials provided with the distribution.
      8  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
      9  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
     10  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     11  * FOR A PARTICULAR PURPOSE.
     12  *
     13  * Functions for signature and digest verification.
     14  *
     15  * Original code by Hannes Gredler (hannes (at) juniper.net)
     16  */
     17 
     18 #include <sys/cdefs.h>
     19 #ifndef lint
     20 #if 0
     21 static const char rcsid[] _U_ =
     22     "@(#) Header: /tcpdump/master/tcpdump/signature.c,v 1.2 2008-09-22 20:22:10 guy Exp  (LBL)";
     23 #else
     24 __RCSID("$NetBSD: signature.c,v 1.2.12.2 2014/08/19 23:52:14 tls Exp $");
     25 #endif
     26 #endif
     27 
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include <tcpdump-stdinc.h>
     33 
     34 #include <string.h>
     35 
     36 #include "interface.h"
     37 #include "signature.h"
     38 
     39 #ifdef HAVE_LIBCRYPTO
     40 #include <openssl/md5.h>
     41 #endif
     42 
     43 const struct tok signature_check_values[] = {
     44     { SIGNATURE_VALID, "valid"},
     45     { SIGNATURE_INVALID, "invalid"},
     46     { CANT_CHECK_SIGNATURE, "unchecked"},
     47     { 0, NULL }
     48 };
     49 
     50 
     51 #ifdef HAVE_LIBCRYPTO
     52 /*
     53  * Compute a HMAC MD5 sum.
     54  * Taken from rfc2104, Appendix.
     55  */
     56 USES_APPLE_DEPRECATED_API
     57 static void
     58 signature_compute_hmac_md5(const u_int8_t *text, int text_len, unsigned char *key,
     59                            unsigned int key_len, u_int8_t *digest)
     60 {
     61     MD5_CTX context;
     62     unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
     63     unsigned char k_opad[65];    /* outer padding - key XORd with opad */
     64     unsigned char tk[16];
     65     int i;
     66 
     67     /* if key is longer than 64 bytes reset it to key=MD5(key) */
     68     if (key_len > 64) {
     69 
     70         MD5_CTX tctx;
     71 
     72         MD5_Init(&tctx);
     73         MD5_Update(&tctx, key, key_len);
     74         MD5_Final(tk, &tctx);
     75 
     76         key = tk;
     77         key_len = 16;
     78     }
     79 
     80     /*
     81      * the HMAC_MD5 transform looks like:
     82      *
     83      * MD5(K XOR opad, MD5(K XOR ipad, text))
     84      *
     85      * where K is an n byte key
     86      * ipad is the byte 0x36 repeated 64 times
     87      * opad is the byte 0x5c repeated 64 times
     88      * and text is the data being protected
     89      */
     90 
     91     /* start out by storing key in pads */
     92     memset(k_ipad, 0, sizeof k_ipad);
     93     memset(k_opad, 0, sizeof k_opad);
     94     memcpy(k_ipad, key, key_len);
     95     memcpy(k_opad, key, key_len);
     96 
     97     /* XOR key with ipad and opad values */
     98     for (i=0; i<64; i++) {
     99         k_ipad[i] ^= 0x36;
    100         k_opad[i] ^= 0x5c;
    101     }
    102 
    103     /*
    104      * perform inner MD5
    105      */
    106     MD5_Init(&context);                   /* init context for 1st pass */
    107     MD5_Update(&context, k_ipad, 64);     /* start with inner pad */
    108     MD5_Update(&context, text, text_len); /* then text of datagram */
    109     MD5_Final(digest, &context);          /* finish up 1st pass */
    110 
    111     /*
    112      * perform outer MD5
    113      */
    114     MD5_Init(&context);                   /* init context for 2nd pass */
    115     MD5_Update(&context, k_opad, 64);     /* start with outer pad */
    116     MD5_Update(&context, digest, 16);     /* then results of 1st hash */
    117     MD5_Final(digest, &context);          /* finish up 2nd pass */
    118 }
    119 USES_APPLE_RST
    120 #endif
    121 
    122 #ifdef HAVE_LIBCRYPTO
    123 /*
    124  * Verify a cryptographic signature of the packet.
    125  * Currently only MD5 is supported.
    126  */
    127 int
    128 signature_verify (const u_char *pptr, u_int plen, u_char *sig_ptr)
    129 {
    130     u_int8_t rcvsig[16];
    131     u_int8_t sig[16];
    132     unsigned int i;
    133 
    134     /*
    135      * Save the signature before clearing it.
    136      */
    137     memcpy(rcvsig, sig_ptr, sizeof(rcvsig));
    138     memset(sig_ptr, 0, sizeof(rcvsig));
    139 
    140     if (!sigsecret) {
    141         return (CANT_CHECK_SIGNATURE);
    142     }
    143 
    144     signature_compute_hmac_md5(pptr, plen, (unsigned char *)sigsecret,
    145                                strlen(sigsecret), sig);
    146 
    147     if (memcmp(rcvsig, sig, sizeof(sig)) == 0) {
    148         return (SIGNATURE_VALID);
    149 
    150     } else {
    151 
    152         for (i = 0; i < sizeof(sig); ++i) {
    153             (void)printf("%02x", sig[i]);
    154         }
    155 
    156         return (SIGNATURE_INVALID);
    157     }
    158 }
    159 #endif
    160 
    161 /*
    162  * Local Variables:
    163  * c-style: whitesmith
    164  * c-basic-offset: 4
    165  * End:
    166  */
    167