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