X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/20f164f5e4825a605d97906b9ac6bf4222b9eef4..refs/heads/tcpdump-4.9:/signature.c diff --git a/signature.c b/signature.c index b989baff..204e3456 100644 --- a/signature.c +++ b/signature.c @@ -12,7 +12,7 @@ * * Functions for signature and digest verification. * - * Original code by Hannes Gredler (hannes@juniper.net) + * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H @@ -22,6 +22,7 @@ #include #include +#include #include "netdissect.h" #include "signature.h" @@ -108,39 +109,86 @@ signature_compute_hmac_md5(const uint8_t *text, int text_len, unsigned char *key MD5_Final(digest, &context); /* finish up 2nd pass */ } USES_APPLE_RST -#endif -#ifdef HAVE_LIBCRYPTO /* * Verify a cryptographic signature of the packet. * Currently only MD5 is supported. */ int -signature_verify(netdissect_options *ndo, - 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) { - uint8_t rcvsig[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_TTEST2(*pptr, plen)) { + /* No. */ + return (CANT_CHECK_SIGNATURE); + } - if (!ndo->ndo_sigsecret) { + /* + * Do we have the entire signature to check? + */ + if (!ND_TTEST2(*sig_ptr, sizeof(sig))) { + /* No. */ return (CANT_CHECK_SIGNATURE); } + if (sig_ptr + sizeof(sig) > pptr + plen) { + /* No. */ + return (CANT_CHECK_SIGNATURE); + } + + /* + * 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); + } + + memcpy(packet_copy, pptr, plen); - signature_compute_hmac_md5(pptr, plen, (unsigned char *)ndo->ndo_sigsecret, + /* + * 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); - if (memcmp(rcvsig, sig, sizeof(sig)) == 0) { - return (SIGNATURE_VALID); + /* + * 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) { ND_PRINT((ndo, "%02x", sig[i])); } @@ -148,6 +196,14 @@ signature_verify(netdissect_options *ndo, 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 /*