Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BLAKE2[sb] hash #191

Merged
merged 29 commits into from
Apr 20, 2017
Merged

Add BLAKE2[sb] hash #191

merged 29 commits into from
Apr 20, 2017

Conversation

ksherlock
Copy link
Collaborator

Hi,

This adds the blake2s hash (https://blake2.net, https://www.ietf.org/rfc/rfc7693.txt) based on the reference implementation (https://github.com/BLAKE2/BLAKE2/blob/master/ref/blake2s-ref.c)

@karel-m
Copy link
Member

karel-m commented Apr 8, 2017

Looks good, do you plan to add blake2b as well?

@ksherlock
Copy link
Collaborator Author

I have added blake2b as well.

@karel-m
Copy link
Member

karel-m commented Apr 9, 2017

Ad Travis-CI failures e.g. https://travis-ci.org/libtom/libtomcrypt/jobs/220116643

you have to move all declaration at the block beginning like this:

 static inline int blake2s_init0(hash_state *md)
 {
+   int i;
    XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));
 
-   for (int i = 0; i < 8; ++i)
+   for (i = 0; i < 8; ++i)

@ksherlock
Copy link
Collaborator Author

It has been updated.
Thanks,
Kelvin

@karel-m
Copy link
Member

karel-m commented Apr 10, 2017

One more place that needs a fix

src/hashes/blake2s.c: In function ‘blake2s_init0’:
src/hashes/blake2s.c:153:4: error: ‘for’ loop initial declarations are only allowed in C99 mode
src/hashes/blake2s.c:153:4: note: use option -std=c99 or -std=gnu99 to compile your code

{
XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));

for (int i = 0; i < 8; ++i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move declaration int i at the block beginning

static int blake2s_init_param(hash_state *md, const struct blake2s_param *P)
{
blake2s_init0(md);
ulong32 *p = (ulong32 *)(P);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

declaration ulong32 *p should go at the block beginning before any code

ulong32 *p = (ulong32 *)(P);

/* IV XOR ParamBlock */
for (size_t i = 0; i < 8; ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move declaration size_t i at the block beginning

LOAD32L(m[i], buf + i * sizeof(m[i]));
}

for (size_t i = 0; i < 8; ++i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the declaration size_t i

ulong32 m[16];
ulong32 v[16];

for (size_t i = 0; i < 16; ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move declaration size_t i at the block beginning

ROUND(8);
ROUND(9);

for (size_t i = 0; i < 8; ++i)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the declaration size_t i

/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i) {
ulong32 tmp;
LOAD32L(tmp, &p[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I propose a change like this:

 static int blake2s_init_param(hash_state *md, const struct blake2s_param *P)
 {
    unsigned long i;
-   ulong32 *p = (ulong32 *)(P);
+   unsigned char *p = (unsigned char *)(P);

    blake2s_init0(md);

    /* IV XOR ParamBlock */
    for (i = 0; i < 8; ++i) {
       ulong32 tmp;
-      LOAD32L(tmp, &p[i]);
+      LOAD32L(tmp, p + i*4);
       md->blake2s.h[i] ^= tmp;
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c.f. my comments to blake2b_init_param()

STORE32L(md->blake2s.h[i], buffer + sizeof(md->blake2s.h[i]) * i);

XMEMCPY(out, buffer, md->blake2s.outlen);
#ifdef LTC_CLEAN_STACK
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

md is not on stack

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

& you forgot to clean buffer

XMEMCPY(out, buffer, md->blake2b.outlen);
#ifdef LTC_CLEAN_STACK
zeromem(buffer, sizeof(buffer));
zeromem(md, sizeof(hash_state));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

md is not on stack

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO zeromem(md, sizeof(hash_state)) should be out of #ifdef LTC_CLEAN_STACK ... #endif

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO zeromem(md, sizeof(hash_state)) should be out of #ifdef LTC_CLEAN_STACK ... #endif

true

Copy link
Member

@sjaeckel sjaeckel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding my comments to the struct blake2[bs]_param I also don't have a good solution yet...

ulong32 h[8];
ulong32 t[2];
ulong32 f[2];
unsigned char buf[2 * 64];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why 2*64 here and 128 for blake2b?

ulong32 t[2];
ulong32 f[2];
unsigned char buf[2 * 64];
ulong32 curlen;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also these types (curlen, outlen, last_node) could be the same type as in blake2b or not? (or in blake2b the same as here, whichever makes most sense, at least it should be consistent)

/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i) {
ulong64 tmp;
LOAD64L(tmp, p + sizeof(md->blake2b.h[i]) * i);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ugh @ the typecast before and then p + sizeof(md->blake2b.h[i]) * i

especially since the blake2b_param struct isn't packed... and I'm not really a fan of packed structs regarding portability...

}

/* init xors IV with input parameter block */
int blake2b_init_param(hash_state *md, const struct blake2b_param *P)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be static

/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i) {
ulong32 tmp;
LOAD32L(tmp, &p[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c.f. my comments to blake2b_init_param()

STORE32L(md->blake2s.h[i], buffer + sizeof(md->blake2s.h[i]) * i);

XMEMCPY(out, buffer, md->blake2s.outlen);
#ifdef LTC_CLEAN_STACK
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

& you forgot to clean buffer

{
int err;
err = _blake2s_compress(md, buf);
burn_stack(sizeof(ulong32) * 32);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you forgot i :)

return CRYPT_OK;
}

int blake2b_init(hash_state *md, unsigned long outlen)
{
struct blake2b_param P;
unsigned char P[BLAKE2B_PARAM_SIZE];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

/* Some helper functions, not necessarily useful */
static int blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format

static void blake2b_set_lastnode(hash_state *md)
{
md->blake2b.f[1] = CONST64(0xffffffffffffffff);
}

/* Some helper functions, not necessarily useful */
static int blake2b_is_lastblock(const hash_state *md) { return md->blake2b.f[0] != 0; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format


XMEMCPY(out, buffer, md->blake2s.outlen);
#ifdef LTC_CLEAN_STACK
zeromem(md, sizeof(hash_state));
zeromem(buffer, sizeof(buffer));
zeromem(md, sizeof(hash_state));
Copy link
Member

@sjaeckel sjaeckel Apr 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we better remove the zero'ing of md for both _done functions? or is the hash descriptor unusable anyways after having called done on it? I just realized that's in line with all the other hash implementations...

@sjaeckel
Copy link
Member

I was thinking about changing blake2[sb]_init as we use it as far as I see only in blake2[sb].c files. We will obviously need to change related parts like:

- int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20); }
+ int blake2b_160_init(hash_state *md) { return blake2b_init(md, 20, NULL, 0); }

But I am not strongly against separate blake2[sb]_init_key functions. Before you start perhaps wait for @sjaeckel's point of view.

sounds fine by me, it doesn't look like a blake2[sb]_init_key is needed as blake2[sb]_init would be yet another wrapper.

The next step would be creating something like src/mac/blake2[sb]mac/blake2[sb]mac.c with:

int blake2smac_init(blake2smac_state *st, unsigned long outlen, const unsigned char *key, unsigned long keylen);
int blake2smac_process(blake2smac_state *st, const unsigned char *in, unsigned long inlen);
int blake2smac_done(blake2smac_state *st, unsigned char *mac, unsigned long *maclen);

And to make it complete we need:

src/mac/blake2[sb]mac/blake2[sb]mac_file.c 
src/mac/blake2[sb]mac/blake2[sb]mac_memory.c 
src/mac/blake2[sb]mac/blake2[sb]mac_memory_multi.c 
src/mac/blake2[sb]mac/blake2[sb]mac_test.c 

also sounds fine by me, I'd just put them in src/mac/blake2/blake2[sb]mac_[file,memory,...].c

please have a look at #184 regarding the structure & API signatures used.

@karel-m
Copy link
Member

karel-m commented Apr 11, 2017

Yes, having both BLAKE2 based MACs in src/mac/blake2/*.c looks better.


const struct ltc_hash_descriptor blake2b_160_desc =
{
"blake2b_160",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please rename the identifiers for all blake2[bs] hash descriptors to blake2[bs]-XXX etc.

@sjaeckel
Copy link
Member

please also add this patch and then we're ready to merge

diff --git a/demos/hashsum.c b/demos/hashsum.c
index 8f94af5..9951a85 100644
--- a/demos/hashsum.c
+++ b/demos/hashsum.c
@@ -105,6 +105,18 @@ void register_algs(void)
 #ifdef LTC_WHIRLPOOL
   register_hash (&whirlpool_desc);
 #endif
+#ifdef LTC_BLAKE2S
+  register_hash (&blake2s_128_desc);
+  register_hash (&blake2s_160_desc);
+  register_hash (&blake2s_224_desc);
+  register_hash (&blake2s_256_desc);
+#endif
+#ifdef LTC_BLAKE2B
+  register_hash (&blake2b_160_desc);
+  register_hash (&blake2b_256_desc);
+  register_hash (&blake2b_384_desc);
+  register_hash (&blake2b_512_desc);
+#endif
 #ifdef LTC_CHC_HASH
   register_hash(&chc_desc);
   if ((err = chc_register(register_cipher(&aes_enc_desc))) != CRYPT_OK) {
diff --git a/src/hashes/blake2b.c b/src/hashes/blake2b.c
index 3e7dd10..55409cc 100644
--- a/src/hashes/blake2b.c
+++ b/src/hashes/blake2b.c
@@ -489,6 +489,16 @@ int blake2b_256_test(void)
         0x31, 0x71, 0xef, 0x3f, 0xee, 0x98, 0x57, 0x9b,
         0x94, 0x96, 0x4e, 0x3b, 0xb1, 0xcb, 0x3e, 0x42,
         0x72, 0x62, 0xc8, 0xc0, 0x68, 0xd5, 0x23, 0x19 } },
+    { "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890",
+      { 0x0f, 0x6e, 0x01, 0x8d, 0x38, 0xd6, 0x3f, 0x08,
+        0x4d, 0x58, 0xe3, 0x0c, 0x90, 0xfb, 0xa2, 0x41,
+        0x5f, 0xca, 0x17, 0xfa, 0x66, 0x26, 0x49, 0xf3,
+        0x8a, 0x30, 0x41, 0x7c, 0x57, 0xcd, 0xa8, 0x14 } },
 
     { NULL, { 0 } }
   };
diff --git a/src/hashes/blake2s.c b/src/hashes/blake2s.c
index 1c4164e..dbb1414 100644
--- a/src/hashes/blake2s.c
+++ b/src/hashes/blake2s.c
@@ -382,6 +382,16 @@ int blake2s_256_test(void)
         0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f,
         0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29,
         0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } },
+    { "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890"
+      "12345678901234567890123456789012345678901234567890",
+      { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41,
+        0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41,
+        0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70,
+        0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } },
 
     { NULL, { 0 } }
   };

@karel-m
Copy link
Member

karel-m commented Apr 18, 2017 via email

@sjaeckel
Copy link
Member

I don't think it should be a personal preference, so I just use the notation that is used in the standards... therefore - and not _
:-)

@karel-m
Copy link
Member

karel-m commented Apr 18, 2017 via email

@sjaeckel
Copy link
Member

And what about zeroing md always (not only #ifdef LTC_CLEAN_STACK) as
mentioned in my comment?

true, I missed that

XMEMCPY(out, buffer, md->blake2b.outlen);
#ifdef LTC_CLEAN_STACK
zeromem(buffer, sizeof(buffer));
zeromem(md, sizeof(hash_state));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO zeromem(md, sizeof(hash_state)) should be out of #ifdef LTC_CLEAN_STACK ... #endif

true

XMEMCPY(out, buffer, md->blake2s.outlen);
#ifdef LTC_CLEAN_STACK
zeromem(buffer, sizeof(buffer));
zeromem(md, sizeof(hash_state));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

@sjaeckel
Copy link
Member

you need something like this

make tv_gen
./tv_gen
mv *_tv.txt notes/
git add notes/
git commit -m "update testvectors"

@karel-m should we add something like the following to helper.pl?

for f in demos/tv_gen.c demos/hashsum.c testprof/x86_prof.c ; do for h in $(rgrep ltc_hash_desc ./src/hashes/ | awk '{print $4}'); do rgrep -q $h $f || echo $h not in $f ; done ; done

...which immediately shows

rmd320_desc not in demos/tv_gen.c
sha512_224_desc not in demos/tv_gen.c
sha512_256_desc not in demos/tv_gen.c
rmd256_desc not in demos/tv_gen.c
sha3_224_desc not in demos/hashsum.c
sha3_256_desc not in demos/hashsum.c
sha3_384_desc not in demos/hashsum.c
sha3_512_desc not in demos/hashsum.c
rmd320_desc not in demos/hashsum.c
sha512_224_desc not in demos/hashsum.c
sha512_256_desc not in demos/hashsum.c
rmd256_desc not in demos/hashsum.c

@sjaeckel
Copy link
Member

I don't know how you created these testvectors, but the ones you pushed fail on my machine as well 😮
What's the architecture&OS you're working on?

@ksherlock
Copy link
Collaborator Author

The hash_sizes in blakes2-160 and blake2s-224 were a little off. hmac_tv.txt should be a little more consistent now.

@karel-m
Copy link
Member

karel-m commented Apr 20, 2017 via email

@sjaeckel sjaeckel merged commit 513fcf3 into libtom:develop Apr 20, 2017
@sjaeckel
Copy link
Member

thx @ksherlock & @karel-m for the good review process

@sjaeckel sjaeckel changed the title blake2s hash Add BLAKE2[sb] hash Apr 20, 2017
@sjaeckel sjaeckel modified the milestone: v1.18.0 Jun 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants