signature.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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@gredler.at)
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include "config.h"
  19. #endif
  20. #include <netdissect-stdinc.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include "netdissect.h"
  24. #include "signature.h"
  25. #ifdef HAVE_LIBCRYPTO
  26. #include <openssl/md5.h>
  27. #endif
  28. const struct tok signature_check_values[] = {
  29. { SIGNATURE_VALID, "valid"},
  30. { SIGNATURE_INVALID, "invalid"},
  31. { CANT_ALLOCATE_COPY, "can't allocate memory"},
  32. { CANT_CHECK_SIGNATURE, "unchecked"},
  33. { 0, NULL }
  34. };
  35. #ifdef HAVE_LIBCRYPTO
  36. /*
  37. * Compute a HMAC MD5 sum.
  38. * Taken from rfc2104, Appendix.
  39. */
  40. USES_APPLE_DEPRECATED_API
  41. static void
  42. signature_compute_hmac_md5(const uint8_t *text, int text_len, unsigned char *key,
  43. unsigned int key_len, uint8_t *digest)
  44. {
  45. MD5_CTX context;
  46. unsigned char k_ipad[65]; /* inner padding - key XORd with ipad */
  47. unsigned char k_opad[65]; /* outer padding - key XORd with opad */
  48. unsigned char tk[16];
  49. int i;
  50. /* if key is longer than 64 bytes reset it to key=MD5(key) */
  51. if (key_len > 64) {
  52. MD5_CTX tctx;
  53. MD5_Init(&tctx);
  54. MD5_Update(&tctx, key, key_len);
  55. MD5_Final(tk, &tctx);
  56. key = tk;
  57. key_len = 16;
  58. }
  59. /*
  60. * the HMAC_MD5 transform looks like:
  61. *
  62. * MD5(K XOR opad, MD5(K XOR ipad, text))
  63. *
  64. * where K is an n byte key
  65. * ipad is the byte 0x36 repeated 64 times
  66. * opad is the byte 0x5c repeated 64 times
  67. * and text is the data being protected
  68. */
  69. /* start out by storing key in pads */
  70. memset(k_ipad, 0, sizeof k_ipad);
  71. memset(k_opad, 0, sizeof k_opad);
  72. memcpy(k_ipad, key, key_len);
  73. memcpy(k_opad, key, key_len);
  74. /* XOR key with ipad and opad values */
  75. for (i=0; i<64; i++) {
  76. k_ipad[i] ^= 0x36;
  77. k_opad[i] ^= 0x5c;
  78. }
  79. /*
  80. * perform inner MD5
  81. */
  82. MD5_Init(&context); /* init context for 1st pass */
  83. MD5_Update(&context, k_ipad, 64); /* start with inner pad */
  84. MD5_Update(&context, text, text_len); /* then text of datagram */
  85. MD5_Final(digest, &context); /* finish up 1st pass */
  86. /*
  87. * perform outer MD5
  88. */
  89. MD5_Init(&context); /* init context for 2nd pass */
  90. MD5_Update(&context, k_opad, 64); /* start with outer pad */
  91. MD5_Update(&context, digest, 16); /* then results of 1st hash */
  92. MD5_Final(digest, &context); /* finish up 2nd pass */
  93. }
  94. USES_APPLE_RST
  95. /*
  96. * Verify a cryptographic signature of the packet.
  97. * Currently only MD5 is supported.
  98. */
  99. int
  100. signature_verify(netdissect_options *ndo, const u_char *pptr, u_int plen,
  101. const u_char *sig_ptr, void (*clear_rtn)(void *),
  102. const void *clear_arg)
  103. {
  104. uint8_t *packet_copy, *sig_copy;
  105. uint8_t sig[16];
  106. unsigned int i;
  107. if (!ndo->ndo_sigsecret) {
  108. return (CANT_CHECK_SIGNATURE);
  109. }
  110. /*
  111. * Do we have all the packet data to be checked?
  112. */
  113. if (!ND_TTEST2(pptr, plen)) {
  114. /* No. */
  115. return (CANT_CHECK_SIGNATURE);
  116. }
  117. /*
  118. * Do we have the entire signature to check?
  119. */
  120. if (!ND_TTEST2(sig_ptr, sizeof(sig))) {
  121. /* No. */
  122. return (CANT_CHECK_SIGNATURE);
  123. }
  124. if (sig_ptr + sizeof(sig) > pptr + plen) {
  125. /* No. */
  126. return (CANT_CHECK_SIGNATURE);
  127. }
  128. /*
  129. * Make a copy of the packet, so we don't overwrite the original.
  130. */
  131. packet_copy = malloc(plen);
  132. if (packet_copy == NULL) {
  133. return (CANT_ALLOCATE_COPY);
  134. }
  135. memcpy(packet_copy, pptr, plen);
  136. /*
  137. * Clear the signature in the copy.
  138. */
  139. sig_copy = packet_copy + (sig_ptr - pptr);
  140. memset(sig_copy, 0, sizeof(sig));
  141. /*
  142. * Clear anything else that needs to be cleared in the copy.
  143. * Our caller is assumed to have vetted the clear_arg pointer.
  144. */
  145. (*clear_rtn)((void *)(packet_copy + ((const uint8_t *)clear_arg - pptr)));
  146. /*
  147. * Compute the signature.
  148. */
  149. signature_compute_hmac_md5(packet_copy, plen,
  150. (unsigned char *)ndo->ndo_sigsecret,
  151. strlen(ndo->ndo_sigsecret), sig);
  152. /*
  153. * Free the copy.
  154. */
  155. free(packet_copy);
  156. /*
  157. * Does the computed signature match the signature in the packet?
  158. */
  159. if (memcmp(sig_ptr, sig, sizeof(sig)) == 0) {
  160. /* Yes. */
  161. return (SIGNATURE_VALID);
  162. } else {
  163. /* No - print the computed signature. */
  164. for (i = 0; i < sizeof(sig); ++i) {
  165. ND_PRINT((ndo, "%02x", sig[i]));
  166. }
  167. return (SIGNATURE_INVALID);
  168. }
  169. }
  170. #else
  171. int
  172. signature_verify(netdissect_options *ndo _U_, const u_char *pptr _U_,
  173. u_int plen _U_, const u_char *sig_ptr _U_,
  174. void (*clear_rtn)(void *) _U_, const void *clear_arg _U_)
  175. {
  176. return (CANT_CHECK_SIGNATURE);
  177. }
  178. #endif
  179. /*
  180. * Local Variables:
  181. * c-style: whitesmith
  182. * c-basic-offset: 4
  183. * End:
  184. */