1 /* 2 * sm3_base.h - core logic for SM3 implementations 3 * 4 * Copyright (C) 2017 ARM Limited or its affiliates. 5 * Written by Gilad Ben-Yossef <gilad@benyossef.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <crypto/internal/hash.h> 21 #include <crypto/sm3.h> 22 #include <linux/crypto.h> 23 #include <linux/module.h> 24 #include <asm/unaligned.h> 25 26 typedef void (sm3_block_fn)(struct sm3_state *sst, u8 const *src, int blocks); 27 28 static inline int sm3_base_init(struct shash_desc *desc) 29 { 30 struct sm3_state *sctx = shash_desc_ctx(desc); 31 32 sctx->state[0] = SM3_IVA; 33 sctx->state[1] = SM3_IVB; 34 sctx->state[2] = SM3_IVC; 35 sctx->state[3] = SM3_IVD; 36 sctx->state[4] = SM3_IVE; 37 sctx->state[5] = SM3_IVF; 38 sctx->state[6] = SM3_IVG; 39 sctx->state[7] = SM3_IVH; 40 sctx->count = 0; 41 42 return 0; 43 } 44 45 static inline int sm3_base_do_update(struct shash_desc *desc, 46 const u8 *data, 47 unsigned int len, 48 sm3_block_fn *block_fn) 49 { 50 struct sm3_state *sctx = shash_desc_ctx(desc); 51 unsigned int partial = sctx->count % SM3_BLOCK_SIZE; 52 53 sctx->count += len; 54 55 if (unlikely((partial + len) >= SM3_BLOCK_SIZE)) { 56 int blocks; 57 58 if (partial) { 59 int p = SM3_BLOCK_SIZE - partial; 60 61 memcpy(sctx->buffer + partial, data, p); 62 data += p; 63 len -= p; 64 65 block_fn(sctx, sctx->buffer, 1); 66 } 67 68 blocks = len / SM3_BLOCK_SIZE; 69 len %= SM3_BLOCK_SIZE; 70 71 if (blocks) { 72 block_fn(sctx, data, blocks); 73 data += blocks * SM3_BLOCK_SIZE; 74 } 75 partial = 0; 76 } 77 if (len) 78 memcpy(sctx->buffer + partial, data, len); 79 80 return 0; 81 } 82 83 static inline int sm3_base_do_finalize(struct shash_desc *desc, 84 sm3_block_fn *block_fn) 85 { 86 const int bit_offset = SM3_BLOCK_SIZE - sizeof(__be64); 87 struct sm3_state *sctx = shash_desc_ctx(desc); 88 __be64 *bits = (__be64 *)(sctx->buffer + bit_offset); 89 unsigned int partial = sctx->count % SM3_BLOCK_SIZE; 90 91 sctx->buffer[partial++] = 0x80; 92 if (partial > bit_offset) { 93 memset(sctx->buffer + partial, 0x0, SM3_BLOCK_SIZE - partial); 94 partial = 0; 95 96 block_fn(sctx, sctx->buffer, 1); 97 } 98 99 memset(sctx->buffer + partial, 0x0, bit_offset - partial); 100 *bits = cpu_to_be64(sctx->count << 3); 101 block_fn(sctx, sctx->buffer, 1); 102 103 return 0; 104 } 105 106 static inline int sm3_base_finish(struct shash_desc *desc, u8 *out) 107 { 108 struct sm3_state *sctx = shash_desc_ctx(desc); 109 __be32 *digest = (__be32 *)out; 110 int i; 111 112 for (i = 0; i < SM3_DIGEST_SIZE / sizeof(__be32); i++) 113 put_unaligned_be32(sctx->state[i], digest++); 114 115 *sctx = (struct sm3_state){}; 116 return 0; 117 } 118