Create a gist now

Instantly share code, notes, and snippets.

// 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