1/*
2 * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <string.h>
11#include "internal/sha3.h"
12
13void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
14
15void sha3_reset(KECCAK1600_CTX *ctx)
16{
17 memset(ctx->A, 0, sizeof(ctx->A));
18 ctx->bufsz = 0;
19}
20
21int sha3_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
22{
23 size_t bsz = SHA3_BLOCKSIZE(bitlen);
24
25 if (bsz <= sizeof(ctx->buf)) {
26 sha3_reset(ctx);
27 ctx->block_size = bsz;
28 ctx->md_size = bitlen / 8;
29 ctx->pad = pad;
30 return 1;
31 }
32
33 return 0;
34}
35
36int keccak_kmac_init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bitlen)
37{
38 int ret = sha3_init(ctx, pad, bitlen);
39
40 if (ret)
41 ctx->md_size *= 2;
42 return ret;
43}
44
45int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
46{
47 const unsigned char *inp = _inp;
48 size_t bsz = ctx->block_size;
49 size_t num, rem;
50
51 if (len == 0)
52 return 1;
53
54 if ((num = ctx->bufsz) != 0) { /* process intermediate buffer? */
55 rem = bsz - num;
56
57 if (len < rem) {
58 memcpy(ctx->buf + num, inp, len);
59 ctx->bufsz += len;
60 return 1;
61 }
62 /*
63 * We have enough data to fill or overflow the intermediate
64 * buffer. So we append |rem| bytes and process the block,
65 * leaving the rest for later processing...
66 */
67 memcpy(ctx->buf + num, inp, rem);
68 inp += rem, len -= rem;
69 (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
70 ctx->bufsz = 0;
71 /* ctx->buf is processed, ctx->num is guaranteed to be zero */
72 }
73
74 if (len >= bsz)
75 rem = SHA3_absorb(ctx->A, inp, len, bsz);
76 else
77 rem = len;
78
79 if (rem) {
80 memcpy(ctx->buf, inp + len - rem, rem);
81 ctx->bufsz = rem;
82 }
83
84 return 1;
85}
86
87int sha3_final(unsigned char *md, KECCAK1600_CTX *ctx)
88{
89 size_t bsz = ctx->block_size;
90 size_t num = ctx->bufsz;
91
92 if (ctx->md_size == 0)
93 return 1;
94
95 /*
96 * Pad the data with 10*1. Note that |num| can be |bsz - 1|
97 * in which case both byte operations below are performed on
98 * same byte...
99 */
100 memset(ctx->buf + num, 0, bsz - num);
101 ctx->buf[num] = ctx->pad;
102 ctx->buf[bsz - 1] |= 0x80;
103
104 (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
105
106 SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
107
108 return 1;
109}
110