Advertisement
Guest User

Untitled

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