1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 
4 /*
5    BLAKE2 reference source code package - reference C implementations
6 
7    Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
8    terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
9    your option.  The terms of these licenses can be found at:
10 
11    - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
12    - OpenSSL license   : https://www.openssl.org/source/license.html
13    - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
14 
15    More information about the BLAKE2 hash function can be found at
16    https://blake2.net.
17 */
18 /* see also https://www.ietf.org/rfc/rfc7693.txt */
19 
20 #include "tomcrypt_private.h"
21 
22 #ifdef LTC_BLAKE2S
23 
24 enum blake2s_constant {
25    BLAKE2S_BLOCKBYTES = 64,
26    BLAKE2S_OUTBYTES = 32,
27    BLAKE2S_KEYBYTES = 32,
28    BLAKE2S_SALTBYTES = 8,
29    BLAKE2S_PERSONALBYTES = 8,
30    BLAKE2S_PARAM_SIZE = 32
31 };
32 
33 /* param offsets */
34 enum {
35    O_DIGEST_LENGTH = 0,
36    O_KEY_LENGTH = 1,
37    O_FANOUT = 2,
38    O_DEPTH = 3,
39    O_LEAF_LENGTH = 4,
40    O_NODE_OFFSET = 8,
41    O_XOF_LENGTH = 12,
42    O_NODE_DEPTH = 14,
43    O_INNER_LENGTH = 15,
44    O_SALT = 16,
45    O_PERSONAL = 24
46 };
47 
48 /*
49 struct blake2s_param {
50    unsigned char digest_length;
51    unsigned char key_length;
52    unsigned char fanout;
53    unsigned char depth;
54    ulong32 leaf_length;
55    ulong32 node_offset;
56    ushort16 xof_length;
57    unsigned char node_depth;
58    unsigned char inner_length;
59    unsigned char salt[BLAKE2S_SALTBYTES];
60    unsigned char personal[BLAKE2S_PERSONALBYTES];
61 };
62 */
63 
64 const struct ltc_hash_descriptor blake2s_128_desc =
65 {
66     "blake2s-128",
67     21,
68     16,
69     64,
70     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 4 },
71     11,
72     &blake2s_128_init,
73     &blake2s_process,
74     &blake2s_done,
75     &blake2s_128_test,
76     NULL
77 };
78 
79 const struct ltc_hash_descriptor blake2s_160_desc =
80 {
81     "blake2s-160",
82     22,
83     20,
84     64,
85     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 5 },
86     11,
87     &blake2s_160_init,
88     &blake2s_process,
89     &blake2s_done,
90     &blake2s_160_test,
91     NULL
92 };
93 
94 const struct ltc_hash_descriptor blake2s_224_desc =
95 {
96     "blake2s-224",
97     23,
98     28,
99     64,
100     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 7 },
101     11,
102     &blake2s_224_init,
103     &blake2s_process,
104     &blake2s_done,
105     &blake2s_224_test,
106     NULL
107 };
108 
109 const struct ltc_hash_descriptor blake2s_256_desc =
110 {
111     "blake2s-256",
112     24,
113     32,
114     64,
115     { 1, 3, 6, 1, 4, 1, 1722, 12, 2, 2, 8 },
116     11,
117     &blake2s_256_init,
118     &blake2s_process,
119     &blake2s_done,
120     &blake2s_256_test,
121     NULL
122 };
123 
124 static const ulong32 blake2s_IV[8] = {
125     0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
126     0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
127 };
128 
129 static const unsigned char blake2s_sigma[10][16] = {
130     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
131     { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
132     { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
133     { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
134     { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
135     { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
136     { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
137     { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
138     { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
139     { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
140 };
141 
s_blake2s_set_lastnode(hash_state * md)142 static void s_blake2s_set_lastnode(hash_state *md) { md->blake2s.f[1] = 0xffffffffUL; }
143 
144 /* Some helper functions, not necessarily useful */
s_blake2s_is_lastblock(const hash_state * md)145 static int s_blake2s_is_lastblock(const hash_state *md) { return md->blake2s.f[0] != 0; }
146 
s_blake2s_set_lastblock(hash_state * md)147 static void s_blake2s_set_lastblock(hash_state *md)
148 {
149    if (md->blake2s.last_node) {
150       s_blake2s_set_lastnode(md);
151    }
152    md->blake2s.f[0] = 0xffffffffUL;
153 }
154 
s_blake2s_increment_counter(hash_state * md,const ulong32 inc)155 static void s_blake2s_increment_counter(hash_state *md, const ulong32 inc)
156 {
157    md->blake2s.t[0] += inc;
158    if (md->blake2s.t[0] < inc) md->blake2s.t[1]++;
159 }
160 
s_blake2s_init0(hash_state * md)161 static int s_blake2s_init0(hash_state *md)
162 {
163    int i;
164    XMEMSET(&md->blake2s, 0, sizeof(struct blake2s_state));
165 
166    for (i = 0; i < 8; ++i) {
167       md->blake2s.h[i] = blake2s_IV[i];
168    }
169 
170    return CRYPT_OK;
171 }
172 
173 /* init2 xors IV with input parameter block */
s_blake2s_init_param(hash_state * md,const unsigned char * P)174 static int s_blake2s_init_param(hash_state *md, const unsigned char *P)
175 {
176    unsigned long i;
177 
178    s_blake2s_init0(md);
179 
180    /* IV XOR ParamBlock */
181    for (i = 0; i < 8; ++i) {
182       ulong32 tmp;
183       LOAD32L(tmp, P + i * 4);
184       md->blake2s.h[i] ^= tmp;
185    }
186 
187    md->blake2s.outlen = P[O_DIGEST_LENGTH];
188    return CRYPT_OK;
189 }
190 
191 /**
192    Initialize the hash/MAC state
193 
194       Use this function to init for arbitrary sizes.
195 
196       Give a key and keylen to init for MAC mode.
197 
198    @param md      The hash state you wish to initialize
199    @param outlen  The desired output-length
200    @param key     The key of the MAC
201    @param keylen  The length of the key
202    @return CRYPT_OK if successful
203 */
blake2s_init(hash_state * md,unsigned long outlen,const unsigned char * key,unsigned long keylen)204 int blake2s_init(hash_state *md, unsigned long outlen, const unsigned char *key, unsigned long keylen)
205 {
206    unsigned char P[BLAKE2S_PARAM_SIZE];
207    int err;
208 
209    LTC_ARGCHK(md != NULL);
210 
211    if ((!outlen) || (outlen > BLAKE2S_OUTBYTES)) {
212       return CRYPT_INVALID_ARG;
213    }
214    if ((key && !keylen) || (keylen && !key) || (keylen > BLAKE2S_KEYBYTES)) {
215       return CRYPT_INVALID_ARG;
216    }
217 
218    XMEMSET(P, 0, sizeof(P));
219 
220    P[O_DIGEST_LENGTH] = (unsigned char)outlen;
221    P[O_KEY_LENGTH] = (unsigned char)keylen;
222    P[O_FANOUT] = 1;
223    P[O_DEPTH] = 1;
224 
225    err = s_blake2s_init_param(md, P);
226    if (err != CRYPT_OK) return err;
227 
228    if (key) {
229       unsigned char block[BLAKE2S_BLOCKBYTES];
230 
231       XMEMSET(block, 0, BLAKE2S_BLOCKBYTES);
232       XMEMCPY(block, key, keylen);
233       blake2s_process(md, block, BLAKE2S_BLOCKBYTES);
234 
235 #ifdef LTC_CLEAN_STACK
236       zeromem(block, sizeof(block));
237 #endif
238    }
239    return CRYPT_OK;
240 }
241 
242 /**
243    Initialize the hash state
244    @param md   The hash state you wish to initialize
245    @return CRYPT_OK if successful
246 */
blake2s_128_init(hash_state * md)247 int blake2s_128_init(hash_state *md) { return blake2s_init(md, 16, NULL, 0); }
248 
249 /**
250    Initialize the hash state
251    @param md   The hash state you wish to initialize
252    @return CRYPT_OK if successful
253 */
blake2s_160_init(hash_state * md)254 int blake2s_160_init(hash_state *md) { return blake2s_init(md, 20, NULL, 0); }
255 
256 /**
257    Initialize the hash state
258    @param md   The hash state you wish to initialize
259    @return CRYPT_OK if successful
260 */
blake2s_224_init(hash_state * md)261 int blake2s_224_init(hash_state *md) { return blake2s_init(md, 28, NULL, 0); }
262 
263 /**
264    Initialize the hash state
265    @param md   The hash state you wish to initialize
266    @return CRYPT_OK if successful
267 */
blake2s_256_init(hash_state * md)268 int blake2s_256_init(hash_state *md) { return blake2s_init(md, 32, NULL, 0); }
269 
270 #define G(r, i, a, b, c, d)                                                                                            \
271    do {                                                                                                                \
272       a = a + b + m[blake2s_sigma[r][2 * i + 0]];                                                                      \
273       d = ROR(d ^ a, 16);                                                                                              \
274       c = c + d;                                                                                                       \
275       b = ROR(b ^ c, 12);                                                                                              \
276       a = a + b + m[blake2s_sigma[r][2 * i + 1]];                                                                      \
277       d = ROR(d ^ a, 8);                                                                                               \
278       c = c + d;                                                                                                       \
279       b = ROR(b ^ c, 7);                                                                                               \
280    } while (0)
281 #define ROUND(r)                                                                                                       \
282    do {                                                                                                                \
283       G(r, 0, v[0], v[4], v[8], v[12]);                                                                                \
284       G(r, 1, v[1], v[5], v[9], v[13]);                                                                                \
285       G(r, 2, v[2], v[6], v[10], v[14]);                                                                               \
286       G(r, 3, v[3], v[7], v[11], v[15]);                                                                               \
287       G(r, 4, v[0], v[5], v[10], v[15]);                                                                               \
288       G(r, 5, v[1], v[6], v[11], v[12]);                                                                               \
289       G(r, 6, v[2], v[7], v[8], v[13]);                                                                                \
290       G(r, 7, v[3], v[4], v[9], v[14]);                                                                                \
291    } while (0)
292 
293 #ifdef LTC_CLEAN_STACK
ss_blake2s_compress(hash_state * md,const unsigned char * buf)294 static int ss_blake2s_compress(hash_state *md, const unsigned char *buf)
295 #else
296 static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
297 #endif
298 {
299    unsigned long i;
300    ulong32 m[16];
301    ulong32 v[16];
302 
303    for (i = 0; i < 16; ++i) {
304       LOAD32L(m[i], buf + i * sizeof(m[i]));
305    }
306 
307    for (i = 0; i < 8; ++i) {
308       v[i] = md->blake2s.h[i];
309    }
310 
311    v[8] = blake2s_IV[0];
312    v[9] = blake2s_IV[1];
313    v[10] = blake2s_IV[2];
314    v[11] = blake2s_IV[3];
315    v[12] = md->blake2s.t[0] ^ blake2s_IV[4];
316    v[13] = md->blake2s.t[1] ^ blake2s_IV[5];
317    v[14] = md->blake2s.f[0] ^ blake2s_IV[6];
318    v[15] = md->blake2s.f[1] ^ blake2s_IV[7];
319 
320    ROUND(0);
321    ROUND(1);
322    ROUND(2);
323    ROUND(3);
324    ROUND(4);
325    ROUND(5);
326    ROUND(6);
327    ROUND(7);
328    ROUND(8);
329    ROUND(9);
330 
331    for (i = 0; i < 8; ++i) {
332       md->blake2s.h[i] = md->blake2s.h[i] ^ v[i] ^ v[i + 8];
333    }
334    return CRYPT_OK;
335 }
336 #undef G
337 #undef ROUND
338 
339 #ifdef LTC_CLEAN_STACK
s_blake2s_compress(hash_state * md,const unsigned char * buf)340 static int s_blake2s_compress(hash_state *md, const unsigned char *buf)
341 {
342    int err;
343    err = ss_blake2s_compress(md, buf);
344    burn_stack(sizeof(ulong32) * (32) + sizeof(unsigned long));
345    return err;
346 }
347 #endif
348 
349 /**
350    Process a block of memory through the hash
351    @param md     The hash state
352    @param in     The data to hash
353    @param inlen  The length of the data (octets)
354    @return CRYPT_OK if successful
355 */
blake2s_process(hash_state * md,const unsigned char * in,unsigned long inlen)356 int blake2s_process(hash_state *md, const unsigned char *in, unsigned long inlen)
357 {
358    LTC_ARGCHK(md != NULL);
359    LTC_ARGCHK(in != NULL);
360 
361    if (md->blake2s.curlen > sizeof(md->blake2s.buf)) {
362       return CRYPT_INVALID_ARG;
363    }
364 
365    if (inlen > 0) {
366       unsigned long left = md->blake2s.curlen;
367       unsigned long fill = BLAKE2S_BLOCKBYTES - left;
368       if (inlen > fill) {
369          md->blake2s.curlen = 0;
370          XMEMCPY(md->blake2s.buf + (left % sizeof(md->blake2s.buf)), in, fill); /* Fill buffer */
371          s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
372          s_blake2s_compress(md, md->blake2s.buf); /* Compress */
373          in += fill;
374          inlen -= fill;
375          while (inlen > BLAKE2S_BLOCKBYTES) {
376             s_blake2s_increment_counter(md, BLAKE2S_BLOCKBYTES);
377             s_blake2s_compress(md, in);
378             in += BLAKE2S_BLOCKBYTES;
379             inlen -= BLAKE2S_BLOCKBYTES;
380          }
381       }
382       XMEMCPY(md->blake2s.buf + md->blake2s.curlen, in, inlen);
383       md->blake2s.curlen += inlen;
384    }
385    return CRYPT_OK;
386 }
387 
388 /**
389    Terminate the hash to get the digest
390    @param md  The hash state
391    @param out [out] The destination of the hash (size depending on the length used on init)
392    @return CRYPT_OK if successful
393 */
blake2s_done(hash_state * md,unsigned char * out)394 int blake2s_done(hash_state *md, unsigned char *out)
395 {
396    unsigned char buffer[BLAKE2S_OUTBYTES] = { 0 };
397    unsigned long i;
398 
399    LTC_ARGCHK(md != NULL);
400    LTC_ARGCHK(out != NULL);
401 
402    /* if(md->blake2s.outlen != outlen) return CRYPT_INVALID_ARG; */
403 
404    if (s_blake2s_is_lastblock(md)) {
405       return CRYPT_ERROR;
406    }
407    s_blake2s_increment_counter(md, md->blake2s.curlen);
408    s_blake2s_set_lastblock(md);
409    XMEMSET(md->blake2s.buf + md->blake2s.curlen, 0, BLAKE2S_BLOCKBYTES - md->blake2s.curlen); /* Padding */
410    s_blake2s_compress(md, md->blake2s.buf);
411 
412    for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
413       STORE32L(md->blake2s.h[i], buffer + i * 4);
414    }
415 
416    XMEMCPY(out, buffer, md->blake2s.outlen);
417    zeromem(md, sizeof(hash_state));
418 #ifdef LTC_CLEAN_STACK
419    zeromem(buffer, sizeof(buffer));
420 #endif
421    return CRYPT_OK;
422 }
423 
424 /**
425   Self-test the hash
426   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
427 */
blake2s_256_test(void)428 int blake2s_256_test(void)
429 {
430 #ifndef LTC_TEST
431    return CRYPT_NOP;
432 #else
433    static const struct {
434       const char *msg;
435       unsigned char hash[32];
436   } tests[] = {
437     { "",
438       { 0x69, 0x21, 0x7a, 0x30, 0x79, 0x90, 0x80, 0x94,
439         0xe1, 0x11, 0x21, 0xd0, 0x42, 0x35, 0x4a, 0x7c,
440         0x1f, 0x55, 0xb6, 0x48, 0x2c, 0xa1, 0xa5, 0x1e,
441         0x1b, 0x25, 0x0d, 0xfd, 0x1e, 0xd0, 0xee, 0xf9 } },
442     { "abc",
443       { 0x50, 0x8c, 0x5e, 0x8c, 0x32, 0x7c, 0x14, 0xe2,
444         0xe1, 0xa7, 0x2b, 0xa3, 0x4e, 0xeb, 0x45, 0x2f,
445         0x37, 0x45, 0x8b, 0x20, 0x9e, 0xd6, 0x3a, 0x29,
446         0x4d, 0x99, 0x9b, 0x4c, 0x86, 0x67, 0x59, 0x82 } },
447     { "12345678901234567890123456789012345678901234567890"
448       "12345678901234567890123456789012345678901234567890"
449       "12345678901234567890123456789012345678901234567890"
450       "12345678901234567890123456789012345678901234567890"
451       "12345678901234567890123456789012345678901234567890"
452       "12345678901234567890123456789012345678901234567890",
453       { 0xa3, 0x78, 0x8b, 0x5b, 0x59, 0xee, 0xe4, 0x41,
454         0x95, 0x23, 0x58, 0x00, 0xa4, 0xf9, 0xfa, 0x41,
455         0x86, 0x0c, 0x7b, 0x1c, 0x35, 0xa2, 0x42, 0x70,
456         0x50, 0x80, 0x79, 0x56, 0xe3, 0xbe, 0x31, 0x74 } },
457 
458     { NULL, { 0 } }
459   };
460 
461    int i;
462    unsigned char tmp[32];
463    hash_state md;
464 
465    for (i = 0; tests[i].msg != NULL; i++) {
466       blake2s_256_init(&md);
467       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
468       blake2s_done(&md, tmp);
469       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_256", i)) {
470          return CRYPT_FAIL_TESTVECTOR;
471       }
472 
473    }
474    return CRYPT_OK;
475 #endif
476 }
477 
478 /**
479   Self-test the hash
480   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
481 */
blake2s_224_test(void)482 int blake2s_224_test(void)
483 {
484 #ifndef LTC_TEST
485    return CRYPT_NOP;
486 #else
487    static const struct {
488       const char *msg;
489       unsigned char hash[28];
490   } tests[] = {
491     { "",
492       { 0x1f, 0xa1, 0x29, 0x1e, 0x65, 0x24, 0x8b, 0x37,
493         0xb3, 0x43, 0x34, 0x75, 0xb2, 0xa0, 0xdd, 0x63,
494         0xd5, 0x4a, 0x11, 0xec, 0xc4, 0xe3, 0xe0, 0x34,
495         0xe7, 0xbc, 0x1e, 0xf4 } },
496     { "abc",
497       { 0x0b, 0x03, 0x3f, 0xc2, 0x26, 0xdf, 0x7a, 0xbd,
498         0xe2, 0x9f, 0x67, 0xa0, 0x5d, 0x3d, 0xc6, 0x2c,
499         0xf2, 0x71, 0xef, 0x3d, 0xfe, 0xa4, 0xd3, 0x87,
500         0x40, 0x7f, 0xbd, 0x55 } },
501 
502     { NULL, { 0 } }
503   };
504 
505    int i;
506    unsigned char tmp[28];
507    hash_state md;
508 
509    for (i = 0; tests[i].msg != NULL; i++) {
510       blake2s_224_init(&md);
511       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
512       blake2s_done(&md, tmp);
513       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_224", i)) {
514          return CRYPT_FAIL_TESTVECTOR;
515       }
516 
517    }
518    return CRYPT_OK;
519 #endif
520 }
521 
522 /**
523   Self-test the hash
524   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
525 */
blake2s_160_test(void)526 int blake2s_160_test(void)
527 {
528 #ifndef LTC_TEST
529    return CRYPT_NOP;
530 #else
531    static const struct {
532       const char *msg;
533       unsigned char hash[20];
534   } tests[] = {
535     { "",
536       { 0x35, 0x4c, 0x9c, 0x33, 0xf7, 0x35, 0x96, 0x24,
537         0x18, 0xbd, 0xac, 0xb9, 0x47, 0x98, 0x73, 0x42,
538         0x9c, 0x34, 0x91, 0x6f} },
539     { "abc",
540       { 0x5a, 0xe3, 0xb9, 0x9b, 0xe2, 0x9b, 0x01, 0x83,
541         0x4c, 0x3b, 0x50, 0x85, 0x21, 0xed, 0xe6, 0x04,
542         0x38, 0xf8, 0xde, 0x17 } },
543 
544     { NULL, { 0 } }
545   };
546 
547    int i;
548    unsigned char tmp[20];
549    hash_state md;
550 
551    for (i = 0; tests[i].msg != NULL; i++) {
552       blake2s_160_init(&md);
553       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
554       blake2s_done(&md, tmp);
555       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_160", i)) {
556          return CRYPT_FAIL_TESTVECTOR;
557       }
558 
559    }
560    return CRYPT_OK;
561 #endif
562 }
563 
564 /**
565   Self-test the hash
566   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
567 */
blake2s_128_test(void)568 int blake2s_128_test(void)
569 {
570 #ifndef LTC_TEST
571    return CRYPT_NOP;
572 #else
573    static const struct {
574       const char *msg;
575       unsigned char hash[16];
576   } tests[] = {
577     { "",
578       { 0x64, 0x55, 0x0d, 0x6f, 0xfe, 0x2c, 0x0a, 0x01,
579         0xa1, 0x4a, 0xba, 0x1e, 0xad, 0xe0, 0x20, 0x0c } },
580     { "abc",
581       { 0xaa, 0x49, 0x38, 0x11, 0x9b, 0x1d, 0xc7, 0xb8,
582         0x7c, 0xba, 0xd0, 0xff, 0xd2, 0x00, 0xd0, 0xae } },
583 
584     { NULL, { 0 } }
585   };
586 
587    int i;
588    unsigned char tmp[16];
589    hash_state md;
590 
591    for (i = 0; tests[i].msg != NULL; i++) {
592       blake2s_128_init(&md);
593       blake2s_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
594       blake2s_done(&md, tmp);
595       if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "BLAKE2S_128", i)) {
596          return CRYPT_FAIL_TESTVECTOR;
597       }
598    }
599    return CRYPT_OK;
600 #endif
601 }
602 
603 #endif
604