#include "../../lib/md2_impls/md2_3.h" #include "../../lib/md2_impls/md2_common.h" struct thread_args { size_t len; const uint8_t* buf; }; void process_nothread_hash(size_t len, const uint8_t buf[len], uint8_t messageDigestBuf[48]) { for (size_t i = 0; i < (len + 16) / 16 - 1; i++) { FIRST_LOOP_START_MARK for (int j = 0; j < 16; j++) { messageDigestBuf[16 + j] = buf[i * 16 + j]; messageDigestBuf[32 + j] = (messageDigestBuf[16 + j] ^ messageDigestBuf[j]); } FIRST_LOOP_END_MARK u_int8_t t = 0; SECOND_LOOP_START_MARK for (int j = 0; j < 18; j++) { for (int k = 0; k < 48; k++) { t = messageDigestBuf[k] = messageDigestBuf[k] ^ MD2_PI_SUBST[t]; } t = (t + j) % 256; } SECOND_LOOP_END_MARK } } void* process_hash(void* threadArgs) { struct thread_args* args = (struct thread_args*)threadArgs; uint8_t* messageDigestBuf = calloc(48, sizeof(uint8_t)); if (messageDigestBuf == NULL) { return NULL; } process_nothread_hash(args->len, args->buf, messageDigestBuf); pthread_exit(messageDigestBuf); } void* process_checksum(void* threasdArgs) { struct thread_args* args = (struct thread_args*)threasdArgs; uint8_t* checksum = calloc(16, sizeof(uint8_t)); if (checksum == NULL) { return NULL; } uint8_t l = 0; CHECKSUM_START_MARK for (size_t i = 0; i < args->len / 16; i++) { for (int j = 0; j < 16; j++) { u_int8_t c = args->buf[i * 16 + j]; // reference is wrong. It says: Set C[j] to S[c xor L]. But it should be: l = checksum[j] ^= MD2_PI_SUBST[c ^ l]; } } CHECKSUM_END_MARK pthread_exit(checksum); } void md2_hash_3(size_t len, const uint8_t buf[len], uint8_t out[16]) { int paddingNeeded = 16 - (len % 16); uint8_t originalPadding = paddingNeeded; len += paddingNeeded; uint8_t* newBuf = calloc(len + 16, sizeof(uint8_t)); if (newBuf == NULL) { return; } memcpy(newBuf, buf, len - paddingNeeded); while (paddingNeeded > 0) { newBuf[len - paddingNeeded] = originalPadding; paddingNeeded--; } pthread_t thread_1, thread_2; struct thread_args thread_args = {len, newBuf}; if (pthread_create(&thread_1, NULL, process_hash, (void*)&thread_args) != 0) { printf("Error creating thread 1\n"); if (errno == 0) errno = EAGAIN; return; } if (pthread_create(&thread_2, NULL, process_checksum, (void*)&thread_args) != 0) { printf("Error creating thread 2\n"); if (errno == 0) errno = EAGAIN; return; } u_int8_t* messageDigestBuf; u_int8_t* checksum; if (pthread_join(thread_1, (void**)&messageDigestBuf) != 0) { printf("Error joining thread 1\n"); if (errno == 0) errno = EINVAL; return; } if (pthread_join(thread_2, (void**)&checksum) != 0) { printf("Error joining thread 2\n"); if (errno == 0) errno = EINVAL; return; } process_nothread_hash(16, checksum, messageDigestBuf); END_MARK memcpy(out, messageDigestBuf, 16); free(messageDigestBuf); free(checksum); free(newBuf); }