Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * utility fn for MD5 style padding as follows:
- * ret = strtopb([in] in, [in] src_len, [out ptr] out_size
- *
- * in: src is source buf, src_len is len in bits
- * out: out_size is filled with size of padded buffer, return value is a pointer
- * to beginning of padded buffer.
- *
- * cross platform & leakless per valgrind:
- *
- * == HEAP SUMMARY:
- * == in use at exit: 0 bytes in 0 blocks
- * == total heap usage: 2 allocs, 2 frees, 525 bytes allocated
- * ==
- * == All heap blocks were freed -- no leaks are possible
- *
- * TODO: add [in] block_size, require congruent mod { 2**n }
- *
- * James Skarzinskas <james@jskarzin.org>
- */
- #include <stdio.h> /* stderr, stdout */
- #include <stdlib.h> /* malloc(), free(), EXIT_SUCCESS */
- #include <string.h> /* memset(), strlen() */
- #include <inttypes.h> /* uint64_t */
- #include <assert.h> /* assert() */
- #define _LINUX /* uncomment on windows */
- #define _TEST_H /* include entry point main to do sanity tests */
- /* if on Linux, macro stdint's _byteswap_uint64 -> __builtin_bswap64 */
- #ifdef _LINUX
- #define _byteswap_uint64(X) __builtin_bswap64((X))
- #endif // _LINUX
- /* given an input, return a buffer of 512-bit blocks tailed by input bit
- * size as a big endian uint64:
- *
- * 1. set n to next multiple of m congrent mod 448 (why? 512 - 64 bits)
- * 2. allocate buffer of size n, prepending input data
- * 3. append bit '1' and then zero until n
- * 4. set last 8 bytes to big endian 64-bit length
- *
- * next multiple: (x + n) & ~(n-1) <-- modulo of 2^n := AND, could also & 0x200
- * returns padded buffer or NULL on failure.
- */
- char*
- strtopb(const char *src, size_t src_len, size_t *out_size) {
- /* sanity check inputs */
- assert(src_len > 0);
- assert(src != NULL);
- unsigned int ml = src_len * 8; /* msg length in bits */
- /* number of bits required to store in 512-bit chunks */
- unsigned int nb = ((ml + sizeof(uint64_t)) + 512) & ~511;
- unsigned int rb = nb - sizeof(uint64_t);
- uint64_t u64_be_len = _byteswap_uint64(ml); /* cross platform endianness swap */
- char *buf = (char *)malloc(nb); /* allocate the padded message block */
- memset(buf, 0, nb); /* zero the buffer */
- memcpy(buf, (char *)src, ml); /* prepend the source */
- /* cheat: append a big endian 1 */
- *(buf + ml) = 0x80; /* 0b1000000*/
- if (NULL != out_size) { /* avoid exception if no out_size */
- *out_size = nb; /* set output size */
- }
- /* copy the big endian length to last 64 bits */
- memcpy((unsigned char *)buf + rb, (unsigned char *)&u64_be_len, sizeof(uint64_t));
- return buf;
- }
- #ifdef _TEST_H
- int main()
- {
- /* test case variables */
- const char* input_string = "Hello there!";
- size_t out, len = strlen(input_string);
- uint64_t result_len;
- char* output_string;
- int nb, i;
- /* sanity on control data */
- assert(input_string == "Hello there!");
- assert(len == 12);
- char* result = strtopb(input_string, len, &out);
- assert(out == 512);
- memcpy((unsigned char *)&result_len, &result[504], sizeof(uint64_t));
- result_len = _byteswap_uint64(result_len);
- assert(result_len / 8 == 12);
- /* test assumes 32-bit integers */
- nb = sizeof(unsigned char) * ~~(result_len / 8);
- output_string = (char *)malloc(nb + 1);
- for (i = 0; i <= result_len / 8; i++) {
- output_string[i] = (unsigned char)result[i];
- }
- /* test we haven't mangled our data */
- assert((0 == memcmp(input_string, output_string, nb)));
- /* dispose resources & exit */
- free(output_string);
- free(result);
- fprintf(stdout, "Done successfully.\r\n");
- return EXIT_SUCCESS;
- }
- #endif // _TEST_H
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement