*
* Functions for signature and digest verification.
*
- * Original code by Hannes Gredler (hannes@juniper.net)
+ * Original code by Hannes Gredler (hannes@gredler.at)
*/
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/signature.c,v 1.2 2008-09-22 20:22:10 guy Exp $ (LBL)";
-#endif
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#include <config.h>
-#include <tcpdump-stdinc.h>
+#include "netdissect-stdinc.h"
#include <string.h>
+#include <stdlib.h>
-#include "interface.h"
+#include "netdissect.h"
#include "signature.h"
+#include "diag-control.h"
#ifdef HAVE_LIBCRYPTO
#include <openssl/md5.h>
const struct tok signature_check_values[] = {
{ SIGNATURE_VALID, "valid"},
{ SIGNATURE_INVALID, "invalid"},
+ { CANT_ALLOCATE_COPY, "can't allocate memory"},
{ CANT_CHECK_SIGNATURE, "unchecked"},
{ 0, NULL }
};
* Compute a HMAC MD5 sum.
* Taken from rfc2104, Appendix.
*/
-USES_APPLE_DEPRECATED_API
+DIAG_OFF_DEPRECATION
static void
-signature_compute_hmac_md5(const u_int8_t *text, int text_len, unsigned char *key,
- unsigned int key_len, u_int8_t *digest)
+signature_compute_hmac_md5(const uint8_t *text, int text_len, unsigned char *key,
+ unsigned int key_len, uint8_t *digest)
{
MD5_CTX context;
unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
*/
/* start out by storing key in pads */
- memset(k_ipad, 0, sizeof k_ipad);
- memset(k_opad, 0, sizeof k_opad);
+ memset(k_ipad, 0, sizeof(k_ipad));
+ memset(k_opad, 0, sizeof(k_opad));
memcpy(k_ipad, key, key_len);
memcpy(k_opad, key, key_len);
MD5_Update(&context, digest, 16); /* then results of 1st hash */
MD5_Final(digest, &context); /* finish up 2nd pass */
}
-USES_APPLE_RST
-#endif
+DIAG_ON_DEPRECATION
-#ifdef HAVE_LIBCRYPTO
/*
* Verify a cryptographic signature of the packet.
* Currently only MD5 is supported.
*/
int
-signature_verify (const u_char *pptr, u_int plen, u_char *sig_ptr)
+signature_verify(netdissect_options *ndo, const u_char *pptr, u_int plen,
+ const u_char *sig_ptr, void (*clear_rtn)(void *),
+ const void *clear_arg)
{
- u_int8_t rcvsig[16];
- u_int8_t sig[16];
+ uint8_t *packet_copy, *sig_copy;
+ uint8_t sig[16];
unsigned int i;
+ if (!ndo->ndo_sigsecret) {
+ return (CANT_CHECK_SIGNATURE);
+ }
+
/*
- * Save the signature before clearing it.
+ * Do we have all the packet data to be checked?
*/
- memcpy(rcvsig, sig_ptr, sizeof(rcvsig));
- memset(sig_ptr, 0, sizeof(rcvsig));
+ if (!ND_TTEST_LEN(pptr, plen)) {
+ /* No. */
+ return (CANT_CHECK_SIGNATURE);
+ }
- if (!sigsecret) {
+ /*
+ * Do we have the entire signature to check?
+ */
+ if (!ND_TTEST_LEN(sig_ptr, sizeof(sig))) {
+ /* No. */
+ return (CANT_CHECK_SIGNATURE);
+ }
+ if (sig_ptr + sizeof(sig) > pptr + plen) {
+ /* No. */
return (CANT_CHECK_SIGNATURE);
}
- signature_compute_hmac_md5(pptr, plen, (unsigned char *)sigsecret,
- strlen(sigsecret), sig);
+ /*
+ * Make a copy of the packet, so we don't overwrite the original.
+ */
+ packet_copy = malloc(plen);
+ if (packet_copy == NULL) {
+ return (CANT_ALLOCATE_COPY);
+ }
- if (memcmp(rcvsig, sig, sizeof(sig)) == 0) {
- return (SIGNATURE_VALID);
+ memcpy(packet_copy, pptr, plen);
- } else {
+ /*
+ * Clear the signature in the copy.
+ */
+ sig_copy = packet_copy + (sig_ptr - pptr);
+ memset(sig_copy, 0, sizeof(sig));
+
+ /*
+ * Clear anything else that needs to be cleared in the copy.
+ * Our caller is assumed to have vetted the clear_arg pointer.
+ */
+ (*clear_rtn)((void *)(packet_copy + ((const uint8_t *)clear_arg - pptr)));
+
+ /*
+ * Compute the signature.
+ */
+ signature_compute_hmac_md5(packet_copy, plen,
+ (unsigned char *)ndo->ndo_sigsecret,
+ strlen(ndo->ndo_sigsecret), sig);
+
+ /*
+ * Free the copy.
+ */
+ free(packet_copy);
+ /*
+ * Does the computed signature match the signature in the packet?
+ */
+ if (memcmp(sig_ptr, sig, sizeof(sig)) == 0) {
+ /* Yes. */
+ return (SIGNATURE_VALID);
+ } else {
+ /* No - print the computed signature. */
for (i = 0; i < sizeof(sig); ++i) {
- (void)printf("%02x", sig[i]);
+ ND_PRINT("%02x", sig[i]);
}
return (SIGNATURE_INVALID);
}
}
+#else
+int
+signature_verify(netdissect_options *ndo _U_, const u_char *pptr _U_,
+ u_int plen _U_, const u_char *sig_ptr _U_,
+ void (*clear_rtn)(void *) _U_, const void *clear_arg _U_)
+{
+ return (CANT_CHECK_SIGNATURE);
+}
#endif
-
-/*
- * Local Variables:
- * c-style: whitesmith
- * c-basic-offset: 4
- * End:
- */