testsha.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /*
  2. * cifra - embedded cryptography library
  3. * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com>
  4. *
  5. * To the extent possible under law, the author(s) have dedicated all
  6. * copyright and related and neighboring rights to this software to the
  7. * public domain worldwide. This software is distributed without any
  8. * warranty.
  9. *
  10. * You should have received a copy of the CC0 Public Domain Dedication
  11. * along with this software. If not, see
  12. * <http://creativecommons.org/publicdomain/zero/1.0/>.
  13. */
  14. #ifndef TESTSHA_H
  15. #define TESTSHA_H
  16. #include "hmac.h"
  17. /* Common functions for testing hash functions.
  18. * You shouldn't use this file. */
  19. static void vector(const cf_chash *hash,
  20. const void *vmsg, size_t nmsg,
  21. const char *expect, size_t nexpect)
  22. {
  23. uint8_t digest[CF_MAXHASH];
  24. const uint8_t *msg = vmsg;
  25. size_t orig_nmsg = nmsg;
  26. cf_chash_ctx ctx;
  27. hash->init(&ctx);
  28. /* Input in carefully chosen chunk sizes to exercise blockwise code. */
  29. if (nmsg)
  30. {
  31. hash->update(&ctx, msg, 1);
  32. nmsg--;
  33. msg++;
  34. }
  35. hash->update(&ctx, msg, nmsg);
  36. hash->digest(&ctx, digest);
  37. TEST_CHECK(nexpect == hash->hashsz);
  38. TEST_CHECK(memcmp(digest, expect, nexpect) == 0);
  39. /* Now try with other arrangements. */
  40. msg = vmsg;
  41. nmsg = orig_nmsg;
  42. hash->init(&ctx);
  43. if (nmsg >= hash->blocksz)
  44. {
  45. hash->update(&ctx, msg, hash->blocksz - 1);
  46. nmsg -= hash->blocksz - 1;
  47. msg += hash->blocksz - 1;
  48. }
  49. hash->update(&ctx, msg, nmsg);
  50. hash->digest(&ctx, digest);
  51. TEST_CHECK(memcmp(digest, expect, nexpect) == 0);
  52. }
  53. /* These are shared between RFC2202 and RFC4231. */
  54. static inline void hmac_test(const cf_chash *hash,
  55. const void *hi_there,
  56. const void *jefe,
  57. const void *aa_dd,
  58. const void *counter_key)
  59. {
  60. uint8_t sig[CF_MAXHASH];
  61. uint8_t key[25], message[50];
  62. /* Key: 0x0b * 20
  63. * Message: "Hi There"
  64. */
  65. memset(key, 0x0b, 20);
  66. memcpy(message, "Hi There", 8);
  67. cf_hmac(key, 20, message, 8, sig, hash);
  68. TEST_CHECK(memcmp(sig, hi_there, hash->hashsz) == 0);
  69. /* Key: "Jefe"
  70. * Message: "what do ya want for nothing?"
  71. */
  72. memcpy(key, "Jefe", 4);
  73. memcpy(message, "what do ya want for nothing?", 28);
  74. cf_hmac(key, 4, message, 28, sig, hash);
  75. TEST_CHECK(memcmp(sig, jefe, hash->hashsz) == 0);
  76. /* Key: 0xaa * 20
  77. * Message: 0xdd * 50
  78. */
  79. memset(key, 0xaa, 20);
  80. memset(message, 0xdd, 50);
  81. cf_hmac(key, 20, message, 50, sig, hash);
  82. TEST_CHECK(memcmp(sig, aa_dd, hash->hashsz) == 0);
  83. /* Key: 0x01..0x19
  84. * Message: 0xcd * 50
  85. */
  86. for (uint8_t i = 1; i < 26; i++)
  87. key[i - 1] = i;
  88. memset(message, 0xcd, 50);
  89. cf_hmac(key, 25, message, 50, sig, hash);
  90. TEST_CHECK(memcmp(sig, counter_key, hash->hashsz) == 0);
  91. }
  92. /* These are specific to RFC4231. */
  93. static inline void hmac_test_sha2(const cf_chash *hash,
  94. const char *long_key,
  95. const char *long_message)
  96. {
  97. uint8_t sig[CF_MAXHASH];
  98. uint8_t key[131], message[152];
  99. /* Key: 0xaa * 131
  100. * Message: "Test Using Larger Than Block-Size Key - Hash Key First"
  101. */
  102. memset(key, 0xaa, 131);
  103. memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54);
  104. cf_hmac(key, 131, message, 54, sig, hash);
  105. TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0);
  106. /* Key: 0xaa * 131
  107. * Message: "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
  108. */
  109. memset(key, 0xaa, 131);
  110. memcpy(message, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.", 152);
  111. cf_hmac(key, 131, message, 152, sig, hash);
  112. TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0);
  113. }
  114. /* This is as hmac_test_sha2, except the sizes are specific to
  115. * a 512-bit block. This is from RFC2202. */
  116. static inline void hmac_test_sha1(const cf_chash *hash,
  117. const char *long_key,
  118. const char *long_message)
  119. {
  120. uint8_t sig[CF_MAXHASH];
  121. uint8_t key[80], message[73];
  122. /* Key: 0xaa * 80
  123. * Message: "Test Using Larger Than Block-Size Key - Hash Key First"
  124. */
  125. memset(key, 0xaa, 80);
  126. memcpy(message, "Test Using Larger Than Block-Size Key - Hash Key First", 54);
  127. cf_hmac(key, 80, message, 54, sig, hash);
  128. TEST_CHECK(memcmp(sig, long_key, hash->hashsz) == 0);
  129. /* Key: 0xaa * 80
  130. * Message: "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
  131. */
  132. memset(key, 0xaa, 80);
  133. memcpy(message, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73);
  134. cf_hmac(key, 80, message, 73, sig, hash);
  135. TEST_CHECK(memcmp(sig, long_message, hash->hashsz) == 0);
  136. }
  137. typedef void (*final_fn)(void *ctx, uint8_t *out);
  138. /* Check incremental interface works, and final function likewise. */
  139. static void vector_abc_final(const cf_chash *hash, const void *vfinal_fn,
  140. const void *expect, size_t nexpect)
  141. {
  142. uint8_t digest[CF_MAXHASH];
  143. final_fn final = vfinal_fn;
  144. cf_chash_ctx ctx;
  145. hash->init(&ctx);
  146. hash->update(&ctx, "a", 1);
  147. hash->digest(&ctx, digest);
  148. hash->update(&ctx, "b", 1);
  149. hash->digest(&ctx, digest);
  150. hash->update(&ctx, "c", 1);
  151. final(&ctx, digest);
  152. TEST_CHECK(hash->hashsz == nexpect);
  153. TEST_CHECK(memcmp(expect, digest, nexpect) == 0);
  154. }
  155. /* Check length-checking vectors work (generated by programs in ../extra_vecs) */
  156. static inline void vector_length(const cf_chash *h,
  157. size_t max,
  158. const void *expect, size_t nexpect)
  159. {
  160. cf_chash_ctx outer, inner;
  161. uint8_t digest[CF_MAXHASH];
  162. h->init(&outer);
  163. for (size_t n = 0; n < max; n++)
  164. {
  165. h->init(&inner);
  166. for (size_t i = 0; i < n; i++)
  167. {
  168. uint8_t byte = (uint8_t) n & 0xff;
  169. h->update(&inner, &byte, 1);
  170. }
  171. h->digest(&inner, digest);
  172. h->update(&outer, digest, h->hashsz);
  173. }
  174. h->digest(&outer, digest);
  175. TEST_CHECK(h->hashsz == nexpect);
  176. TEST_CHECK(memcmp(expect, digest, nexpect) == 0);
  177. }
  178. #endif