Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2017
532
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.53 KB | None | 0 0
  1. /*
  2. * utility fn for MD5 style padding as follows:
  3. *
  4. * ret = strtobpb([in] in, [in] src_len, [out ptr] out_size
  5. *
  6. * in: src is source buf, src_len is len in bits
  7. * out: out_size is filled with size of padded buffer, return value is a pointer
  8. * to beginning of padded buffer.
  9. *
  10. * cross platform & leakless per valgrind:
  11. *
  12. * == HEAP SUMMARY:
  13. * == in use at exit: 0 bytes in 0 blocks
  14. * == total heap usage: 2 allocs, 2 frees, 525 bytes allocated
  15. * ==
  16. * == All heap blocks were freed -- no leaks are possible
  17. *
  18. * TODO: add [in] block_size, require congruent mod { 2**n }
  19. *
  20. * James Skarzinskas <james@jskarzin.org>
  21. */
  22. #include <stdio.h> /* stderr, stdout */
  23. #include <stdlib.h> /* malloc(), free(), EXIT_SUCCESS */
  24. #include <string.h> /* memset(), strlen() */
  25. #include <inttypes.h> /* uint64_t */
  26. #include <assert.h> /* assert() */
  27.  
  28. #define _LINUX /* uncomment on windows */
  29. #define _TEST_H /* include entry point main to do sanity tests */
  30.  
  31. /* if on Linux, macro stdint's _byteswap_uint64 -> __builtin_bswap64 */
  32. #ifdef _LINUX
  33. #define _byteswap_uint64(X) __builtin_bswap64((X))
  34. #endif // _LINUX
  35.  
  36. /* given an input, return a buffer of 512-bit blocks tailed by input bit
  37. * size as a big endian uint64:
  38. *
  39. * 1. set n to next multiple of m congrent mod 448 (why? 512 - 64 bits)
  40. * 2. allocate buffer of size n, prepending input data
  41. * 3. append bit '1' and then zero until n
  42. * 4. set last 8 bytes to big endian 64-bit length
  43. *
  44. * next multiple: (x + n) & ~(n-1) <-- modulo of 2^n := AND, could also & 0x200
  45. * returns padded buffer or NULL on failure.
  46. */
  47. char*
  48. strtopb(const char *src, size_t src_len, size_t *out_size) {
  49. /* sanity check inputs */
  50. assert(src_len > 0);
  51. assert(src != NULL);
  52.  
  53. unsigned int ml = src_len * 8; /* msg length in bits */
  54. /* number of bits required to store in 512-bit chunks */
  55. unsigned int nb = ((ml + sizeof(uint64_t)) + 512) & ~511;
  56. unsigned int rb = nb - sizeof(uint64_t);
  57. uint64_t u64_be_len = _byteswap_uint64(ml); /* cross platform endianness swap */
  58.  
  59. char *buf = (char *)malloc(nb); /* allocate the padded message block */
  60. memset(buf, 0, nb); /* zero the buffer */
  61. memcpy(buf, (char *)src, ml); /* prepend the source */
  62. /* cheat: append a big endian 1 */
  63. *(buf + ml) = 0x80; /* 0b1000000*/
  64. if (NULL != out_size) { /* avoid exception if no out_size */
  65. *out_size = nb; /* set output size */
  66. }
  67. /* copy the big endian length to last 64 bits */
  68. memcpy((unsigned char *)buf + rb, (unsigned char *)&u64_be_len, sizeof(uint64_t));
  69. return buf;
  70. }
  71.  
  72. #ifdef _TEST_H
  73. int main()
  74. {
  75. /* test case variables */
  76. const char* input_string = "Hello there!";
  77. size_t out, len = strlen(input_string);
  78. uint64_t result_len;
  79. char* output_string;
  80. int nb, i;
  81.  
  82. /* sanity on control data */
  83. assert(input_string == "Hello there!");
  84. assert(len == 12);
  85. char* result = strtopb(input_string, len, &out);
  86. assert(out == 512);
  87.  
  88. memcpy((unsigned char *)&result_len, &result[504], sizeof(uint64_t));
  89. result_len = _byteswap_uint64(result_len);
  90. assert(result_len / 8 == 12);
  91.  
  92. /* test assumes 32-bit integers */
  93. nb = sizeof(unsigned char) * ~~(result_len / 8);
  94. output_string = (char *)malloc(nb + 1);
  95.  
  96. for (i = 0; i <= result_len / 8; i++) {
  97. output_string[i] = (unsigned char)result[i];
  98. }
  99.  
  100. /* test we haven't mangled our data */
  101. assert((0 == memcmp(input_string, output_string, nb)));
  102.  
  103. /* dispose resources & exit */
  104. free(output_string);
  105. free(result);
  106.  
  107. fprintf(stdout, "Done successfully.\r\n");
  108. return EXIT_SUCCESS;
  109. }
  110. #endif // _TEST_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement