padding_test.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
  2. /* SPDX-License-Identifier: Unlicense */
  3. #include <tomcrypt_test.h>
  4. #ifdef LTC_PADDING
  5. typedef struct padding_testcase_ padding_testcase;
  6. typedef int (*cmp_padding_testcase)(const padding_testcase*, const unsigned char*, unsigned long);
  7. struct padding_testcase_ {
  8. unsigned long is, should, max, mode;
  9. const char* name;
  10. cmp_padding_testcase cmp;
  11. };
  12. #define EQ(a, b) s_eq((a), (b), #a, #b)
  13. static int s_eq(unsigned long a, unsigned long b, const char* s_a, const char* s_b)
  14. {
  15. if (a == b) return CRYPT_OK;
  16. #if defined(LTC_TEST) && defined(LTC_TEST_DBG)
  17. else fprintf(stderr, "'%s == %s' failed, %lu is not equal to %lu\n", s_a, s_b, a, b);
  18. #else
  19. LTC_UNUSED_PARAM(s_a);
  20. LTC_UNUSED_PARAM(s_b);
  21. #endif
  22. return CRYPT_FAIL_TESTVECTOR;
  23. }
  24. static int s_cmp_pkcs7(const padding_testcase* t, const unsigned char* p, unsigned long len)
  25. {
  26. unsigned long n, diff = len - t->is;
  27. DOX(EQ(len, t->should), t->name);
  28. for (n = len - diff; n < len; ++n) {
  29. DOX(EQ(p[n], diff), t->name);
  30. }
  31. return CRYPT_OK;
  32. }
  33. #ifdef LTC_RNG_GET_BYTES
  34. static int s_cmp_iso_10126(const padding_testcase* t, const unsigned char* p, unsigned long len)
  35. {
  36. LTC_UNUSED_PARAM(p);
  37. if (len < t->should || len > t->max) {
  38. #if defined(LTC_TEST) && defined(LTC_TEST_DBG)
  39. fprintf(stderr, "(%lu < %lu || %lu > %lu) failed, %s\n", len, t->should, len, t->max, t->name);
  40. #endif
  41. return CRYPT_FAIL_TESTVECTOR;
  42. }
  43. DOX(EQ(p[len - 1], len - t->is), t->name);
  44. return CRYPT_OK;
  45. }
  46. #endif
  47. static int s_cmp_x923(const padding_testcase* t, const unsigned char* p, unsigned long len)
  48. {
  49. unsigned long n, diff = len - t->is;
  50. DOX(EQ(len, t->should), t->name);
  51. for (n = len - diff; n < len - 1; ++n) {
  52. DOX(EQ(p[n], 0x0), t->name);
  53. }
  54. DOX(EQ(p[len - 1], diff), t->name);
  55. return CRYPT_OK;
  56. }
  57. static int s_cmp_oaz(const padding_testcase* t, const unsigned char* p, unsigned long len)
  58. {
  59. unsigned long n, diff = len - t->is;
  60. DOX(EQ(len, t->should), t->name);
  61. n = len - diff;
  62. DOX(EQ(p[n], 0x80), t->name);
  63. n++;
  64. for (; n < len; ++n) {
  65. DOX(EQ(p[n], 0x0), t->name);
  66. }
  67. return CRYPT_OK;
  68. }
  69. static int s_cmp_zero(const padding_testcase* t, const unsigned char* p, unsigned long len)
  70. {
  71. unsigned long n, diff = len - t->is;
  72. DOX(EQ(len, t->should), t->name);
  73. for (n = len - diff; n < len; ++n) {
  74. DOX(EQ(p[n], 0x0), t->name);
  75. }
  76. return CRYPT_OK;
  77. }
  78. static int s_cmp_ssh(const padding_testcase* t, const unsigned char* p, unsigned long len)
  79. {
  80. unsigned long n, diff = len - t->is;
  81. unsigned char pad = 0x1;
  82. DOX(EQ(len, t->should), t->name);
  83. for (n = len - diff; n < len; ++n) {
  84. DOX(EQ(p[n], pad), t->name);
  85. pad++;
  86. }
  87. return CRYPT_OK;
  88. }
  89. static int s_padding_testrun(const padding_testcase* t)
  90. {
  91. unsigned long len;
  92. unsigned char buf[1024];
  93. len = sizeof(buf);
  94. XMEMSET(buf, 0xAA, t->is);
  95. DO(padding_pad(buf, t->is, &len, t->mode));
  96. DO(t->cmp(t, buf, len));
  97. DO(padding_depad(buf, &len, t->mode));
  98. DO(EQ(len, t->is));
  99. return CRYPT_OK;
  100. }
  101. int padding_test(void)
  102. {
  103. const padding_testcase cases[] = {
  104. { 0, 16, 0, LTC_PAD_PKCS7 | 16, "0-pkcs7", s_cmp_pkcs7 },
  105. { 1, 16, 0, LTC_PAD_PKCS7 | 16, "1-pkcs7", s_cmp_pkcs7 },
  106. { 15, 16, 0, LTC_PAD_PKCS7 | 16, "15-pkcs7", s_cmp_pkcs7 },
  107. { 16, 32, 0, LTC_PAD_PKCS7 | 16, "16-pkcs7", s_cmp_pkcs7 },
  108. { 255, 256, 0, LTC_PAD_PKCS7 | 16, "255-pkcs7", s_cmp_pkcs7 },
  109. { 256, 272, 0, LTC_PAD_PKCS7 | 16, "256-pkcs7", s_cmp_pkcs7 },
  110. #ifdef LTC_RNG_GET_BYTES
  111. { 0, 16, 256, LTC_PAD_ISO_10126 | 16, "0-rand", s_cmp_iso_10126 },
  112. { 1, 16, 272, LTC_PAD_ISO_10126 | 16, "1-rand", s_cmp_iso_10126 },
  113. { 15, 16, 272, LTC_PAD_ISO_10126 | 16, "15-rand", s_cmp_iso_10126 },
  114. { 16, 32, 288, LTC_PAD_ISO_10126 | 16, "16-rand", s_cmp_iso_10126 },
  115. { 255, 256, 512, LTC_PAD_ISO_10126 | 16, "255-rand", s_cmp_iso_10126 },
  116. { 256, 272, 528, LTC_PAD_ISO_10126 | 16, "256-rand", s_cmp_iso_10126 },
  117. #endif
  118. { 0, 16, 0, LTC_PAD_ANSI_X923 | 16, "0-x923", s_cmp_x923 },
  119. { 1, 16, 0, LTC_PAD_ANSI_X923 | 16, "1-x923", s_cmp_x923 },
  120. { 15, 16, 0, LTC_PAD_ANSI_X923 | 16, "15-x923", s_cmp_x923 },
  121. { 16, 32, 0, LTC_PAD_ANSI_X923 | 16, "16-x923", s_cmp_x923 },
  122. { 255, 256, 0, LTC_PAD_ANSI_X923 | 16, "255-x923", s_cmp_x923 },
  123. { 256, 272, 0, LTC_PAD_ANSI_X923 | 16, "256-x923", s_cmp_x923 },
  124. { 0, 16, 0, LTC_PAD_SSH | 16, "0-ssh", s_cmp_ssh },
  125. { 1, 16, 0, LTC_PAD_SSH | 16, "1-ssh", s_cmp_ssh },
  126. { 15, 16, 0, LTC_PAD_SSH | 16, "15-ssh", s_cmp_ssh },
  127. { 16, 32, 0, LTC_PAD_SSH | 16, "16-ssh", s_cmp_ssh },
  128. { 255, 256, 0, LTC_PAD_SSH | 16, "255-ssh", s_cmp_ssh },
  129. { 256, 272, 0, LTC_PAD_SSH | 16, "256-ssh", s_cmp_ssh },
  130. { 0, 16, 0, LTC_PAD_ONE_AND_ZERO | 16, "0-one-and-zero", s_cmp_oaz },
  131. { 1, 16, 0, LTC_PAD_ONE_AND_ZERO | 16, "1-one-and-zero", s_cmp_oaz },
  132. { 15, 16, 0, LTC_PAD_ONE_AND_ZERO | 16, "15-one-and-zero", s_cmp_oaz },
  133. { 16, 32, 0, LTC_PAD_ONE_AND_ZERO | 16, "16-one-and-zero", s_cmp_oaz },
  134. { 255, 256, 0, LTC_PAD_ONE_AND_ZERO | 16, "255-one-and-zero", s_cmp_oaz },
  135. { 256, 272, 0, LTC_PAD_ONE_AND_ZERO | 16, "256-one-and-zero", s_cmp_oaz },
  136. { 0, 0, 0, LTC_PAD_ZERO | 16, "0-zero", s_cmp_zero },
  137. { 1, 16, 0, LTC_PAD_ZERO | 16, "1-zero", s_cmp_zero },
  138. { 15, 16, 0, LTC_PAD_ZERO | 16, "15-zero", s_cmp_zero },
  139. { 16, 16, 0, LTC_PAD_ZERO | 16, "16-zero", s_cmp_zero },
  140. { 255, 256, 0, LTC_PAD_ZERO | 16, "255-zero", s_cmp_zero },
  141. { 256, 256, 0, LTC_PAD_ZERO | 16, "256-zero", s_cmp_zero },
  142. { 0, 16, 0, LTC_PAD_ZERO_ALWAYS | 16, "0-zero-always", s_cmp_zero },
  143. { 1, 16, 0, LTC_PAD_ZERO_ALWAYS | 16, "1-zero-always", s_cmp_zero },
  144. { 15, 16, 0, LTC_PAD_ZERO_ALWAYS | 16, "15-zero-always", s_cmp_zero },
  145. { 16, 32, 0, LTC_PAD_ZERO_ALWAYS | 16, "16-zero-always", s_cmp_zero },
  146. { 255, 256, 0, LTC_PAD_ZERO_ALWAYS | 16, "255-zero-always", s_cmp_zero },
  147. { 256, 272, 0, LTC_PAD_ZERO_ALWAYS | 16, "256-zero-always", s_cmp_zero },
  148. };
  149. unsigned i;
  150. /* Examples from https://en.wikipedia.org/w/index.php?title=Padding_(cryptography)&oldid=823057951#Byte_padding */
  151. const struct {
  152. unsigned char data[16];
  153. unsigned long len;
  154. unsigned long mode;
  155. } tv[] = {
  156. { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, 0x04, 0x04, 0x04 }, 12, LTC_PAD_PKCS7 | 16 },
  157. { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x00, 0x00, 0x04 }, 12, LTC_PAD_ANSI_X923 | 16 },
  158. #ifdef LTC_RNG_GET_BYTES
  159. { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x81, 0xA6, 0x23, 0x04 }, 12, LTC_PAD_ISO_10126 | 16 },
  160. #endif
  161. { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x80, 0x00, 0x00, 0x00 }, 12, LTC_PAD_ONE_AND_ZERO | 16 },
  162. { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x80 }, 15, LTC_PAD_ONE_AND_ZERO | 16 },
  163. { { 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x00, 0x00, 0x00, 0x00 }, 12, LTC_PAD_ZERO | 16 },
  164. };
  165. /* we need a big buffer like that as LTC_PAD_ISO_10126
  166. * is allowed to add 1-255 bytes of padding
  167. */
  168. unsigned char buf[256 + 16];
  169. unsigned long l;
  170. for (i = 0; i < sizeof(cases)/sizeof(cases[0]); ++i) {
  171. DOX(s_padding_testrun(&cases[i]), cases[i].name);
  172. }
  173. for (i = 0; i < sizeof(tv)/sizeof(tv[0]); ++i) {
  174. XMEMCPY(buf, tv[i].data, sizeof(tv[i].data));
  175. l = sizeof(tv[i].data);
  176. DO(padding_depad(buf, &l, tv[i].mode));
  177. XMEMSET(buf, 0xDD, 16);
  178. l = sizeof(buf);
  179. DO(padding_pad(buf, tv[i].len, &l, tv[i].mode));
  180. #ifdef LTC_RNG_GET_BYTES
  181. if ((tv[i].mode & LTC_PAD_MASK) != LTC_PAD_ISO_10126)
  182. #endif
  183. {
  184. COMPARE_TESTVECTOR(tv[i].data, sizeof(tv[i].data), buf, l, "padding fixed TV", i);
  185. }
  186. }
  187. /* wycheproof failing test - https://github.com/libtom/libtomcrypt/pull/454 */
  188. {
  189. unsigned char data[] = { 0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
  190. unsigned long len = sizeof(data);
  191. SHOULD_FAIL(padding_depad(data, &len, (LTC_PAD_PKCS7 | 16)));
  192. }
  193. return CRYPT_OK;
  194. }
  195. #endif