signature.c revision 1.2
11558Srgrimes/*
21558Srgrimes * Redistribution and use in source and binary forms, with or without
31558Srgrimes * modification, are permitted provided that: (1) source code
41558Srgrimes * distributions retain the above copyright notice and this paragraph
51558Srgrimes * in its entirety, and (2) distributions including binary code include
61558Srgrimes * the above copyright notice and this paragraph in its entirety in
71558Srgrimes * the documentation or other materials provided with the distribution.
81558Srgrimes * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
91558Srgrimes * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
101558Srgrimes * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
111558Srgrimes * FOR A PARTICULAR PURPOSE.
121558Srgrimes *
13128085Sbde * Functions for signature and digest verification.
141558Srgrimes *
151558Srgrimes * Original code by Hannes Gredler (hannes@juniper.net)
161558Srgrimes */
171558Srgrimes
181558Srgrimes#include <sys/cdefs.h>
191558Srgrimes#ifndef lint
201558Srgrimes#if 0
211558Srgrimesstatic const char rcsid[] _U_ =
221558Srgrimes    "@(#) Header: /tcpdump/master/tcpdump/signature.c,v 1.2 2008-09-22 20:22:10 guy Exp (LBL)";
231558Srgrimes#else
241558Srgrimes__RCSID("$NetBSD: signature.c,v 1.2 2010/12/05 05:11:31 christos Exp $");
251558Srgrimes#endif
261558Srgrimes#endif
271558Srgrimes
281558Srgrimes#ifdef HAVE_CONFIG_H
291558Srgrimes#include "config.h"
301558Srgrimes#endif
3136997Scharnier
3223672Speter#include <tcpdump-stdinc.h>
3336997Scharnier
3436997Scharnier#include <string.h>
3550476Speter
361558Srgrimes#include "interface.h"
371558Srgrimes#include "signature.h"
381558Srgrimes
391558Srgrimes#ifdef HAVE_LIBCRYPTO
401558Srgrimes#include <openssl/md5.h>
411558Srgrimes#endif
421558Srgrimes
431558Srgrimesconst struct tok signature_check_values[] = {
441558Srgrimes    { SIGNATURE_VALID, "valid"},
451558Srgrimes    { SIGNATURE_INVALID, "invalid"},
4619239Sfenner    { CANT_CHECK_SIGNATURE, "unchecked"},
4719239Sfenner    { 0, NULL }
4836115Sfenner};
491558Srgrimes
501558Srgrimes
511558Srgrimes#ifdef HAVE_LIBCRYPTO
521558Srgrimes/*
531558Srgrimes * Compute a HMAC MD5 sum.
541558Srgrimes * Taken from rfc2104, Appendix.
551558Srgrimes */
56103949Smikestatic void
5759216Simpsignature_compute_hmac_md5(const u_int8_t *text, int text_len, unsigned char *key,
581558Srgrimes                           unsigned int key_len, u_int8_t *digest)
591558Srgrimes{
601558Srgrimes    MD5_CTX context;
611558Srgrimes    unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
621558Srgrimes    unsigned char k_opad[65];    /* outer padding - key XORd with opad */
631558Srgrimes    unsigned char tk[16];
641558Srgrimes    int i;
651558Srgrimes
661558Srgrimes    /* if key is longer than 64 bytes reset it to key=MD5(key) */
671558Srgrimes    if (key_len > 64) {
681558Srgrimes
691558Srgrimes        MD5_CTX tctx;
701558Srgrimes
711558Srgrimes        MD5_Init(&tctx);
7292837Simp        MD5_Update(&tctx, key, key_len);
7392837Simp        MD5_Final(tk, &tctx);
7492837Simp
7592837Simp        key = tk;
7692837Simp        key_len = 16;
7792837Simp    }
7892837Simp
791558Srgrimes    /*
8019300Sfenner     * the HMAC_MD5 transform looks like:
811558Srgrimes     *
821558Srgrimes     * MD5(K XOR opad, MD5(K XOR ipad, text))
831558Srgrimes     *
8492837Simp     * where K is an n byte key
851558Srgrimes     * ipad is the byte 0x36 repeated 64 times
861558Srgrimes     * opad is the byte 0x5c repeated 64 times
8792837Simp     * and text is the data being protected
8892837Simp     */
8992837Simp
901558Srgrimes    /* start out by storing key in pads */
911558Srgrimes    memset(k_ipad, 0, sizeof k_ipad);
921558Srgrimes    memset(k_opad, 0, sizeof k_opad);
931558Srgrimes    memcpy(k_ipad, key, key_len);
941558Srgrimes    memcpy(k_opad, key, key_len);
951558Srgrimes
961558Srgrimes    /* XOR key with ipad and opad values */
971558Srgrimes    for (i=0; i<64; i++) {
9892837Simp        k_ipad[i] ^= 0x36;
991558Srgrimes        k_opad[i] ^= 0x5c;
10019300Sfenner    }
10119300Sfenner
10219300Sfenner    /*
10319300Sfenner     * perform inner MD5
1041558Srgrimes     */
10519300Sfenner    MD5_Init(&context);                   /* init context for 1st pass */
10619300Sfenner    MD5_Update(&context, k_ipad, 64);     /* start with inner pad */
10719300Sfenner    MD5_Update(&context, text, text_len); /* then text of datagram */
10819300Sfenner    MD5_Final(digest, &context);          /* finish up 1st pass */
10919300Sfenner
11019300Sfenner    /*
11119300Sfenner     * perform outer MD5
11219300Sfenner     */
11319300Sfenner    MD5_Init(&context);                   /* init context for 2nd pass */
11419300Sfenner    MD5_Update(&context, k_opad, 64);     /* start with outer pad */
11519300Sfenner    MD5_Update(&context, digest, 16);     /* then results of 1st hash */
11619300Sfenner    MD5_Final(digest, &context);          /* finish up 2nd pass */
11719300Sfenner}
11819300Sfenner#endif
11919300Sfenner
12019300Sfenner#ifdef HAVE_LIBCRYPTO
12119300Sfenner/*
1221558Srgrimes * Verify a cryptographic signature of the packet.
1231558Srgrimes * Currently only MD5 is supported.
1241558Srgrimes */
12592837Simpint
1261558Srgrimessignature_verify (const u_char *pptr, u_int plen, u_char *sig_ptr)
12786473Siedowse{
12886473Siedowse    u_int8_t rcvsig[16];
1291558Srgrimes    u_int8_t sig[16];
1301558Srgrimes    unsigned int i;
1311558Srgrimes
1321558Srgrimes    /*
13319239Sfenner     * Save the signature before clearing it.
13436115Sfenner     */
1351558Srgrimes    memcpy(rcvsig, sig_ptr, sizeof(rcvsig));
1361558Srgrimes    memset(sig_ptr, 0, sizeof(rcvsig));
137114452Smarkm
1381558Srgrimes    if (!sigsecret) {
139114452Smarkm        return (CANT_CHECK_SIGNATURE);
14037635Sjkoshy    }
1411558Srgrimes
1421558Srgrimes    signature_compute_hmac_md5(pptr, plen, (unsigned char *)sigsecret,
1431558Srgrimes                               strlen(sigsecret), sig);
14419300Sfenner
14537635Sjkoshy    if (memcmp(rcvsig, sig, sizeof(sig)) == 0) {
1461558Srgrimes        return (SIGNATURE_VALID);
1471558Srgrimes
14823672Speter    } else {
1491558Srgrimes
1501558Srgrimes        for (i = 0; i < sizeof(sig); ++i) {
1511558Srgrimes            (void)printf("%02x", sig[i]);
15237635Sjkoshy        }
1531558Srgrimes
1541558Srgrimes        return (SIGNATURE_INVALID);
1551558Srgrimes    }
15612377Sjoerg}
15712377Sjoerg#endif
158122669Sjohan
159114452Smarkm/*
160114452Smarkm * Local Variables:
16119300Sfenner * c-style: whitesmith
16219300Sfenner * c-basic-offset: 4
16319239Sfenner * End:
16419300Sfenner */
16519317Sfenner