1154941Sjhb/*
2154941Sjhb * Redistribution and use in source and binary forms, with or without
3154941Sjhb * modification, are permitted provided that: (1) source code
4154941Sjhb * distributions retain the above copyright notice and this paragraph
5154941Sjhb * in its entirety, and (2) distributions including binary code include
6154941Sjhb * the above copyright notice and this paragraph in its entirety in
7154941Sjhb * the documentation or other materials provided with the distribution.
8154941Sjhb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9154941Sjhb * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10154941Sjhb * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11154941Sjhb * FOR A PARTICULAR PURPOSE.
12154941Sjhb *
13154941Sjhb * Functions for signature and digest verification.
14154941Sjhb *
15154941Sjhb * Original code by Hannes Gredler (hannes@juniper.net)
16154941Sjhb */
17154941Sjhb
18154941Sjhb#ifndef lint
19154941Sjhbstatic const char rcsid[] _U_ =
20154941Sjhb    "@(#) $Header: /tcpdump/master/tcpdump/signature.c,v 1.2 2008-09-22 20:22:10 guy Exp $ (LBL)";
21154941Sjhb#endif
22154941Sjhb
23154941Sjhb#ifdef HAVE_CONFIG_H
24154941Sjhb#include "config.h"
25154941Sjhb#endif
26154941Sjhb
27154941Sjhb#include <tcpdump-stdinc.h>
28154941Sjhb
29154941Sjhb#include <string.h>
30154941Sjhb
31154941Sjhb#include "interface.h"
32154941Sjhb#include "signature.h"
33154941Sjhb
34171516Sattilio#ifdef HAVE_LIBCRYPTO
35192853Ssson#include <openssl/md5.h>
36154941Sjhb#endif
37154941Sjhb
38163320Sglebiusconst struct tok signature_check_values[] = {
39154941Sjhb    { SIGNATURE_VALID, "valid"},
40154941Sjhb    { SIGNATURE_INVALID, "invalid"},
41154941Sjhb    { CANT_CHECK_SIGNATURE, "unchecked"},
42154941Sjhb    { 0, NULL }
43154941Sjhb};
44154941Sjhb
45154941Sjhb
46154941Sjhb#ifdef HAVE_LIBCRYPTO
47154941Sjhb/*
48154941Sjhb * Compute a HMAC MD5 sum.
49154941Sjhb * Taken from rfc2104, Appendix.
50154941Sjhb */
51154941Sjhbstatic void
52154941Sjhbsignature_compute_hmac_md5(const u_int8_t *text, int text_len, unsigned char *key,
53154941Sjhb                           unsigned int key_len, u_int8_t *digest)
54154941Sjhb{
55154941Sjhb    MD5_CTX context;
56154941Sjhb    unsigned char k_ipad[65];    /* inner padding - key XORd with ipad */
57154941Sjhb    unsigned char k_opad[65];    /* outer padding - key XORd with opad */
58154941Sjhb    unsigned char tk[16];
59154941Sjhb    int i;
60176017Sjeff
61154941Sjhb    /* if key is longer than 64 bytes reset it to key=MD5(key) */
62171052Sattilio    if (key_len > 64) {
63176017Sjeff
64176017Sjeff        MD5_CTX tctx;
65154941Sjhb
66154941Sjhb        MD5_Init(&tctx);
67171052Sattilio        MD5_Update(&tctx, key, key_len);
68154941Sjhb        MD5_Final(tk, &tctx);
69154941Sjhb
70154941Sjhb        key = tk;
71154941Sjhb        key_len = 16;
72154941Sjhb    }
73169394Sjhb
74154941Sjhb    /*
75154941Sjhb     * the HMAC_MD5 transform looks like:
76154941Sjhb     *
77179025Sattilio     * MD5(K XOR opad, MD5(K XOR ipad, text))
78179025Sattilio     *
79154941Sjhb     * where K is an n byte key
80154941Sjhb     * ipad is the byte 0x36 repeated 64 times
81154941Sjhb     * opad is the byte 0x5c repeated 64 times
82154941Sjhb     * and text is the data being protected
83154941Sjhb     */
84154941Sjhb
85154941Sjhb    /* start out by storing key in pads */
86154941Sjhb    memset(k_ipad, 0, sizeof k_ipad);
87154941Sjhb    memset(k_opad, 0, sizeof k_opad);
88154941Sjhb    memcpy(k_ipad, key, key_len);
89154941Sjhb    memcpy(k_opad, key, key_len);
90154941Sjhb
91154941Sjhb    /* XOR key with ipad and opad values */
92154941Sjhb    for (i=0; i<64; i++) {
93154941Sjhb        k_ipad[i] ^= 0x36;
94154941Sjhb        k_opad[i] ^= 0x5c;
95154941Sjhb    }
96171516Sattilio
97154941Sjhb    /*
98167012Skmacy     * perform inner MD5
99171516Sattilio     */
100154941Sjhb    MD5_Init(&context);                   /* init context for 1st pass */
101192853Ssson    MD5_Update(&context, k_ipad, 64);     /* start with inner pad */
102192853Ssson    MD5_Update(&context, text, text_len); /* then text of datagram */
103192853Ssson    MD5_Final(digest, &context);          /* finish up 1st pass */
104154941Sjhb
105154941Sjhb    /*
106154941Sjhb     * perform outer MD5
107154941Sjhb     */
108154941Sjhb    MD5_Init(&context);                   /* init context for 2nd pass */
109154941Sjhb    MD5_Update(&context, k_opad, 64);     /* start with outer pad */
110176017Sjeff    MD5_Update(&context, digest, 16);     /* then results of 1st hash */
111176017Sjeff    MD5_Final(digest, &context);          /* finish up 2nd pass */
112176017Sjeff}
113154941Sjhb#endif
114154941Sjhb
115154941Sjhb#ifdef HAVE_LIBCRYPTO
116154941Sjhb/*
117154941Sjhb * Verify a cryptographic signature of the packet.
118154941Sjhb * Currently only MD5 is supported.
119154941Sjhb */
120154941Sjhbint
121154941Sjhbsignature_verify (const u_char *pptr, u_int plen, u_char *sig_ptr)
122171052Sattilio{
123171052Sattilio    u_int8_t rcvsig[16];
124154941Sjhb    u_int8_t sig[16];
125154941Sjhb    unsigned int i;
126185778Skmacy
127167024Srwatson    /*
128154941Sjhb     * Save the signature before clearing it.
129177843Sattilio     */
130154941Sjhb    memcpy(rcvsig, sig_ptr, sizeof(rcvsig));
131154941Sjhb    memset(sig_ptr, 0, sizeof(rcvsig));
132177843Sattilio
133154941Sjhb    if (!sigsecret) {
134154941Sjhb        return (CANT_CHECK_SIGNATURE);
135154941Sjhb    }
136154941Sjhb
137154941Sjhb    signature_compute_hmac_md5(pptr, plen, (unsigned char *)sigsecret,
138157882Sjhb                               strlen(sigsecret), sig);
139157882Sjhb
140154941Sjhb    if (memcmp(rcvsig, sig, sizeof(sig)) == 0) {
141154941Sjhb        return (SIGNATURE_VALID);
142154941Sjhb
143154941Sjhb    } else {
144154941Sjhb
145154941Sjhb        for (i = 0; i < sizeof(sig); ++i) {
146154941Sjhb            (void)printf("%02x", sig[i]);
147154941Sjhb        }
148154941Sjhb
149154941Sjhb        return (SIGNATURE_INVALID);
150154941Sjhb    }
151154941Sjhb}
152154941Sjhb#endif
153154941Sjhb
154154941Sjhb/*
155154941Sjhb * Local Variables:
156154941Sjhb * c-style: whitesmith
157154941Sjhb * c-basic-offset: 4
158154941Sjhb * End:
159154941Sjhb */
160154941Sjhb