Skip to content

Instantly share code, notes, and snippets.

@WolfWings
Last active September 17, 2018 20:52
Show Gist options
  • Save WolfWings/fc79718f7a9c618bfbae3e077d0b3053 to your computer and use it in GitHub Desktop.
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
#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;
}
@WolfWings
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment