Created
August 23, 2016 19:57
-
-
Save quend/7e7277b158d360abf656ab17b6215add to your computer and use it in GitHub Desktop.
This file contains 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
// clang -L/usr/local/opt/openssl/lib -I/usr/local/opt/openssl/include -lssl -lcrypto -O0 -g aesni_cbc_hmac_sha1_cipher.c && ./a.out | |
#include <stdio.h> | |
#include <string.h> | |
#include <openssl/evp.h> | |
#include <openssl/objects.h> | |
#include <openssl/aes.h> | |
#include <openssl/sha.h> | |
#include <openssl/rand.h> | |
#define NO_PAYLOAD_LENGTH ((size_t)-1) | |
void sha1_block_data_order(void *c, const void *p, size_t len); | |
static int aesni_cbc_hmac_sha1_cipher(unsigned char *out, size_t len) | |
{ | |
SHA_CTX md; | |
SHA1_Init(&md); | |
SHA_CTX md_head; | |
SHA1_Init(&md_head); | |
SHA_CTX md_tail; | |
SHA1_Init(&md_tail); | |
unsigned int l; | |
// size_t plen = key->payload_length, iv = 0, /* explicit IV in TLS 1.1 and | |
// * later */ | |
size_t sha_off = 0; | |
size_t aes_off = 0, blocks; | |
sha_off = SHA_CBLOCK - md.num; | |
// key->payload_length = NO_PAYLOAD_LENGTH; | |
if (len % AES_BLOCK_SIZE) | |
return 0; | |
union { | |
unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)]; | |
unsigned char c[32 + SHA_DIGEST_LENGTH]; | |
} mac, *pmac; | |
/* arrange cache line alignment */ | |
pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32)); | |
size_t inp_len, mask, j, i; | |
unsigned int res, maxpad, pad, bitlen; | |
int ret = 1; | |
union { | |
unsigned int u[SHA_LBLOCK]; | |
unsigned char c[SHA_CBLOCK]; | |
} *data = (void *)md.data; | |
/* figure out payload length */ | |
pad = out[len - 1]; | |
maxpad = len - (SHA_DIGEST_LENGTH + 1); | |
maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); | |
maxpad &= 255; | |
printf("maxpad, pad: %d %d\n", maxpad, pad); | |
inp_len = len - (SHA_DIGEST_LENGTH + pad + 1); | |
mask = (0 - ((inp_len - len) >> (sizeof(inp_len) * 8 - 1))); | |
inp_len &= mask; | |
ret &= (int)mask; | |
printf("ret (inp_len): %d\n", ret); | |
// key->aux.tls_aad[plen - 2] = inp_len >> 8; | |
// key->aux.tls_aad[plen - 1] = inp_len; | |
/* calculate HMAC */ | |
md = md_head; | |
// SHA1_Update(&md, key->aux.tls_aad, plen); | |
len -= SHA_DIGEST_LENGTH; /* amend mac */ | |
if (len >= (256 + SHA_CBLOCK)) { | |
j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK); | |
j += SHA_CBLOCK - md.num; | |
SHA1_Update(&md, out, j); | |
out += j; | |
len -= j; | |
inp_len -= j; | |
} | |
/* but pretend as if we hashed padded payload */ | |
bitlen = md.Nl + (inp_len << 3); /* at most 18 bits */ | |
# ifdef BSWAP4 | |
bitlen = BSWAP4(bitlen); | |
# else | |
mac.c[0] = 0; | |
mac.c[1] = (unsigned char)(bitlen >> 16); | |
mac.c[2] = (unsigned char)(bitlen >> 8); | |
mac.c[3] = (unsigned char)bitlen; | |
bitlen = mac.u[0]; | |
# endif | |
pmac->u[0] = 0; | |
pmac->u[1] = 0; | |
pmac->u[2] = 0; | |
pmac->u[3] = 0; | |
pmac->u[4] = 0; | |
for (res = md.num, j = 0; j < len; j++) { | |
size_t c = out[j]; | |
mask = (j - inp_len) >> (sizeof(j) * 8 - 8); | |
c &= mask; | |
c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); | |
data->c[res++] = (unsigned char)c; | |
if (res != SHA_CBLOCK) | |
continue; | |
/* j is not incremented yet */ | |
mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); | |
data->u[SHA_LBLOCK - 1] |= bitlen & mask; | |
sha1_block_data_order(&md, data, 1); | |
mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); | |
pmac->u[0] |= md.h0 & mask; | |
pmac->u[1] |= md.h1 & mask; | |
pmac->u[2] |= md.h2 & mask; | |
pmac->u[3] |= md.h3 & mask; | |
pmac->u[4] |= md.h4 & mask; | |
res = 0; | |
} | |
for (i = res; i < SHA_CBLOCK; i++, j++) | |
data->c[i] = 0; | |
if (res > SHA_CBLOCK - 8) { | |
mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); | |
data->u[SHA_LBLOCK - 1] |= bitlen & mask; | |
sha1_block_data_order(&md, data, 1); | |
mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); | |
pmac->u[0] |= md.h0 & mask; | |
pmac->u[1] |= md.h1 & mask; | |
pmac->u[2] |= md.h2 & mask; | |
pmac->u[3] |= md.h3 & mask; | |
pmac->u[4] |= md.h4 & mask; | |
memset(data, 0, SHA_CBLOCK); | |
j += 64; | |
} | |
data->u[SHA_LBLOCK - 1] = bitlen; | |
sha1_block_data_order(&md, data, 1); | |
mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); | |
pmac->u[0] |= md.h0 & mask; | |
pmac->u[1] |= md.h1 & mask; | |
pmac->u[2] |= md.h2 & mask; | |
pmac->u[3] |= md.h3 & mask; | |
pmac->u[4] |= md.h4 & mask; | |
# ifdef BSWAP4 | |
pmac->u[0] = BSWAP4(pmac->u[0]); | |
pmac->u[1] = BSWAP4(pmac->u[1]); | |
pmac->u[2] = BSWAP4(pmac->u[2]); | |
pmac->u[3] = BSWAP4(pmac->u[3]); | |
pmac->u[4] = BSWAP4(pmac->u[4]); | |
# else | |
for (i = 0; i < 5; i++) { | |
res = pmac->u[i]; | |
pmac->c[4 * i + 0] = (unsigned char)(res >> 24); | |
pmac->c[4 * i + 1] = (unsigned char)(res >> 16); | |
pmac->c[4 * i + 2] = (unsigned char)(res >> 8); | |
pmac->c[4 * i + 3] = (unsigned char)res; | |
} | |
# endif | |
len += SHA_DIGEST_LENGTH; | |
md = md_tail; | |
SHA1_Update(&md, pmac->c, SHA_DIGEST_LENGTH); | |
SHA1_Final(pmac->c, &md); | |
/* verify HMAC */ | |
out += inp_len; | |
len -= inp_len; | |
{ | |
unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH; | |
size_t off = out - p; | |
printf("off: %lx\n", off); | |
unsigned int c, cmask; | |
maxpad += SHA_DIGEST_LENGTH; | |
for (res = 0, i = 0, j = 0; j < maxpad; j++) { | |
c = p[j]; | |
cmask = | |
((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) * | |
8 - 1); | |
printf("%ld: %x\n", j, ~cmask); | |
res |= (c ^ pad) & ~cmask; /* ... and padding */ | |
cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); | |
printf("%ld: %x\n", j, cmask); | |
res |= (c ^ pmac->c[i]) & cmask; | |
i += 1 & cmask; | |
} | |
maxpad -= SHA_DIGEST_LENGTH; | |
res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); | |
printf("ret (pre-res): %d\n", ret); | |
ret &= (int)~res; | |
} | |
printf("ret: %d\n", ret); | |
return ret; | |
} | |
int main() { | |
int len = 32; | |
unsigned char * out = malloc(len); | |
int maxpad = len - SHA_DIGEST_LENGTH - 1; | |
unsigned char pad = maxpad + SHA_DIGEST_LENGTH; | |
memset(out, pad, len); | |
aesni_cbc_hmac_sha1_cipher(out, len); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment