-#include <assert.h>
+#include <stdio.h>
#include <stdint.h>
#include <string.h>
+#include "sha2.h"
uint64_t sha256_h_init[8] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
0x5fcb6fab3ad6faec, 0x6c44198c4a475817
};
-#define SHA2_MAX_BLOCK_LENGTH 128
-
static inline int min(int a,int b) { return a<b?a:b; }
static inline uint32_t rot32(uint32_t v, int amt) {
#define FLAG_HALFWORD 1 /* Curse you, 512-224 */
#define FLAG_HMAC 2
-struct sha2_variety_t {
- uint64_t *iv;
- int bits,words_out;
- int v_flags;
-};
-
-struct sha2_ctx_t {
- int variety_idx;
- struct sha2_variety_t *variety;
- uint64_t h64[8];
- uint8_t pending[SHA2_MAX_BLOCK_LENGTH];
- int pending_len;
- uint64_t length;
- int flags;
- uint8_t k_prime[SHA2_MAX_BLOCK_LENGTH]; /* For HMAC */
-};
-
-#define SHA2_VARIETY_224 0
-#define SHA2_VARIETY_256 1
-#define SHA2_VARIETY_384 2
-#define SHA2_VARIETY_512 3
-#define SHA2_VARIETY_512_256 4
-#define SHA2_VARIETY_512_224 5
-#define SHA2_VARIETY_END 6
-
struct sha2_variety_t sha2_variety_def[SHA2_VARIETY_END] = {
{sha224_h_init,32,7,0}, /* SHA224 */
{sha256_h_init,32,8,0}, /* SHA256 */
}
static int sha2_finish_main(struct sha2_ctx_t *ctx, uint8_t *out, int maxlen) {
- int i,space_bytes,half_here,space_needed,len_bytes,len_offset,
- block_size,bits,len;
+ int i, half_here, space_needed, len_len, block_size,bits,len;
signed int pad_length;
- uint8_t terminal[128],*len_pos;
+ uint8_t terminal[SHA2_MAX_BLOCK_LENGTH*2],*len_pos;
bits = ctx->variety->bits;
block_size = 2*bits;
- len_bytes = bits/4; /* 32 => 8; 64 => 16 */
- space_bytes = block_size - ctx->pending_len;
- space_needed = 1 + len_bytes;
- pad_length = space_bytes - space_needed;
- if(pad_length<0) {
+ len_len = bits/4; /* Length of length field: 32bit => 8by; 64bit => 16by */
+ space_needed = 1 + len_len; /* Need room for 0x80 and the length field */
+ pad_length = block_size - ctx->pending_len - space_needed;
+ if(pad_length<0) { /* Oops, add a block */
pad_length += block_size;
}
- memset(terminal,0,128);
+ memset(terminal,0,SHA2_MAX_BLOCK_LENGTH*2);
terminal[0] = 0x80;
- len_offset = 1 + pad_length;
- len_pos = terminal+len_offset;
- be_unpack(ctx->length*8,&len_pos,len_bytes,len_bytes,NULL);
+ len_pos = terminal + pad_length + 1; /* gets clobbered by be_unpack */
+ be_unpack(ctx->length*8,&len_pos,len_len,len_len,NULL);
sha2_more(ctx,terminal,space_needed + pad_length);
len = 0;
for(i=0;i<ctx->variety->words_out;i++) {
sha2_finish(&ctx,out,SHA2_MAX_BLOCK_LENGTH);
} else {
memcpy(out,key,key_len);
- memset(out+key_len,0,block_size-key_len);
}
}
printf("ok test-trunc\n");
}
+#define MAX_LEN 1000
+static void test_lengths() { /* Only useful with valgrind */
+ struct sha2_ctx_t ctx;
+ uint8_t text[MAX_LEN],out[SHA2_MAX_DIGEST_SIZE];
+ int len;
+
+ memset(text,42,MAX_LEN);
+ for(len=0;len<1000;len++) {
+ sha2_init(&ctx,SHA2_VARIETY_512);
+ sha2_more(&ctx,text,len);
+ sha2_finish(&ctx,out,SHA2_MAX_DIGEST_SIZE);
+ }
+}
+
+
int main() {
char *dog = "The quick brown fox jumps over the lazy dog";
char *k = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+ printf("Run me under valgrind too!\n");
compare("empty-512",SHA2_VARIETY_512,"","cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",NULL);
compare("empty-384",SHA2_VARIETY_384,"","38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",NULL);
compare("empty-256",SHA2_VARIETY_256,"","e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",NULL);
compare("dog-224",SHA2_VARIETY_224,dog,"730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525",NULL);
compare("hmac-512",SHA2_VARIETY_512,dog,"2a31d580d74d604de3dce055477d0a5633411adeafa044e10a2c6cfee6e38df49ed336cb53e3e7fa6bbbf3f107a3067296560be3deb09afcaff9cb98d2169433",k);
compare("hmac-224",SHA2_VARIETY_224,dog,"610d38da56e06cf7d15bdf1ad83e250ae77ada28b5648036bba614ee",k);
+ test_lengths();
test_trunc();
return 0;
}