Last active
September 17, 2018 20:52
-
-
Save WolfWings/fc79718f7a9c618bfbae3e077d0b3053 to your computer and use it in GitHub Desktop.
Little-endian (x86) PBKDF2 (SHA1) which relies on the AF_ALG user-space interface to the Linux Kernel Cryptography system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <linux/if_alg.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <byteswap.h> | |
static struct sockaddr_alg sa = { | |
.salg_family = AF_ALG | |
, .salg_type = "hash" | |
, .salg_name = "hmac(sha1)" | |
}; | |
#define BLOCKSIZE 20 | |
void pbkdf2( | |
const char *password, const int password_len, | |
const char *salt, const int salt_len, | |
const int iter, | |
unsigned char *key_buffer, const int key_length | |
) { | |
unsigned char last[BLOCKSIZE], xorb[BLOCKSIZE]; | |
unsigned char count_buffer[4]; | |
int block_count = (key_length + BLOCKSIZE - 1) / BLOCKSIZE; | |
int block_rem = ((key_length + BLOCKSIZE - 1) % 20) + 1; | |
int block, cur_iter, i, control, hmac, block_bswap; | |
control = socket(AF_ALG, SOCK_SEQPACKET, 0); | |
bind(control, (struct sockaddr *)&sa, sizeof(sa)); | |
setsockopt(control, SOL_ALG, ALG_SET_KEY, password, password_len); | |
for (block = 1; block <= block_count; block++) { | |
block_bswap = bswap_32(block); | |
hmac = accept(control, NULL, 0); | |
sendto(hmac, salt, salt_len, MSG_MORE, NULL, 0); | |
sendto(hmac, &block_bswap, 4, 0, NULL, 0); | |
recvfrom(hmac, last, BLOCKSIZE, 0, NULL, NULL); | |
close(hmac); | |
memcpy(xorb, last, BLOCKSIZE); | |
for (cur_iter = 1; cur_iter < iter; cur_iter++) { | |
hmac = accept(control, NULL, 0); | |
sendto(hmac, last, BLOCKSIZE, 0, NULL, 0); | |
recvfrom(hmac, last, BLOCKSIZE, 0, NULL, NULL); | |
close(hmac); | |
for (i = 0; i < BLOCKSIZE; i++) { | |
xorb[i] ^= last[i]; | |
} | |
} | |
memcpy(key_buffer + (block * BLOCKSIZE) - BLOCKSIZE, xorb, (block < block_count) ? BLOCKSIZE : block_rem); | |
} | |
close(control); | |
return; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As a note, this code fragment is specifically avoiding any libc calls with the exception of memcpy which generally optimizes out to an inline macro regardless, and is targeting x86 explicitly thus the explicit byte-swap to big-endian which the PBKDF2 standard requires.
Including the sockaddr data structure this compiles down to <600 bytes total program space taken.