void sha1_process(sha1_ctx_t *p, const byte *data, unsigned size) { if (p->pos) { uint n = BLOCK_SIZE - p->pos; if (n > size) n = size; memcpy(p->buf+p->pos, data, n); p->pos += n; data += n; size -= n; if (p->pos == BLOCK_SIZE) { sha1_process_block(p, p->buf); sha1_inc_processed(p, BLOCK_SIZE); p->pos = 0; } } while (size >= BLOCK_SIZE) { sha1_process_block(p, data); sha1_inc_processed(p, BLOCK_SIZE); data += BLOCK_SIZE; size -= BLOCK_SIZE; } memcpy(p->buf, data, size); p->pos = size; }
void sha1_finish(sha1_ctx_t *p) { sha1_inc_processed(p, p->pos); /* size is expected to be in bits */ p->processed[1] <<= 3; p->processed[1] |= (p->processed[0] >> 29) & 7; p->processed[0] <<= 3; p->buf[p->pos++] = 0x80; if (p->pos > 56) { while (p->pos < BLOCK_SIZE) p->buf[p->pos++] = 0x00; sha1_process_block(p, p->buf); p->pos = 0; } while (p->pos < 56) p->buf[p->pos++] = 0x00; /* append size */ p->buf[p->pos++] = p->processed[1] >> 24; p->buf[p->pos++] = p->processed[1] >> 16; p->buf[p->pos++] = p->processed[1] >> 8; p->buf[p->pos++] = p->processed[1]; p->buf[p->pos++] = p->processed[0] >> 24; p->buf[p->pos++] = p->processed[0] >> 16; p->buf[p->pos++] = p->processed[0] >> 8; p->buf[p->pos++] = p->processed[0]; sha1_process_block(p, p->buf); /* put completed sha1 hash into buf */ p->buf[ 0] = (byte)(p->h[0]>>24); p->buf[ 1] = (byte)(p->h[0]>>16); p->buf[ 2] = (byte)(p->h[0]>>8); p->buf[ 3] = (byte)(p->h[0]); p->buf[ 4] = (byte)(p->h[1]>>24); p->buf[ 5] = (byte)(p->h[1]>>16); p->buf[ 6] = (byte)(p->h[1]>>8); p->buf[ 7] = (byte)(p->h[1]); p->buf[ 8] = (byte)(p->h[2]>>24); p->buf[ 9] = (byte)(p->h[2]>>16); p->buf[10] = (byte)(p->h[2]>>8); p->buf[11] = (byte)(p->h[2]); p->buf[12] = (byte)(p->h[3]>>24); p->buf[13] = (byte)(p->h[3]>>16); p->buf[14] = (byte)(p->h[3]>>8); p->buf[15] = (byte)(p->h[3]); p->buf[16] = (byte)(p->h[4]>>24); p->buf[17] = (byte)(p->h[4]>>16); p->buf[18] = (byte)(p->h[4]>>8); p->buf[19] = (byte)(p->h[4]); }
int hmac_sha1 (const void *key, size_t keylen, const void *in, size_t inlen, void *resbuf) { struct sha1_ctx inner; struct sha1_ctx outer; char optkeybuf[20]; char block[64]; char innerhash[20]; /* Reduce the key's size, so that it becomes <= 64 bytes large. */ if (keylen > 64) { struct sha1_ctx keyhash; sha1_init_ctx (&keyhash); sha1_process_bytes (key, keylen, &keyhash); sha1_finish_ctx (&keyhash, optkeybuf); key = optkeybuf; keylen = 20; } /* Compute INNERHASH from KEY and IN. */ sha1_init_ctx (&inner); memset (block, IPAD, sizeof (block)); memxor (block, key, keylen); sha1_process_block (block, 64, &inner); sha1_process_bytes (in, inlen, &inner); sha1_finish_ctx (&inner, innerhash); /* Compute result from KEY and INNERHASH. */ sha1_init_ctx (&outer); memset (block, OPAD, sizeof (block)); memxor (block, key, keylen); sha1_process_block (block, 64, &outer); sha1_process_bytes (innerhash, 20, &outer); sha1_finish_ctx (&outer, resbuf); return 0; }