1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Cryptographic API. 4 * 5 * s390 generic implementation of the SHA Secure Hash Algorithms. 6 * 7 * Copyright IBM Corp. 2007 8 * Author(s): Jan Glauber (jang@de.ibm.com) 9 */ 10 11 #include <crypto/internal/hash.h> 12 #include <linux/module.h> 13 #include <asm/cpacf.h> 14 #include "sha.h" 15 16 int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len) 17 { 18 struct s390_sha_ctx *ctx = shash_desc_ctx(desc); 19 unsigned int bsize = crypto_shash_blocksize(desc->tfm); 20 unsigned int index, n; 21 int fc; 22 23 /* how much is already in the buffer? */ 24 index = ctx->count % bsize; 25 ctx->count += len; 26 27 if ((index + len) < bsize) 28 goto store; 29 30 fc = ctx->func; 31 if (ctx->first_message_part) 32 fc |= test_facility(86) ? CPACF_KIMD_NIP : 0; 33 34 /* process one stored block */ 35 if (index) { 36 memcpy(ctx->buf + index, data, bsize - index); 37 cpacf_kimd(fc, ctx->state, ctx->buf, bsize); 38 ctx->first_message_part = 0; 39 fc &= ~CPACF_KIMD_NIP; 40 data += bsize - index; 41 len -= bsize - index; 42 index = 0; 43 } 44 45 /* process as many blocks as possible */ 46 if (len >= bsize) { 47 n = (len / bsize) * bsize; 48 cpacf_kimd(fc, ctx->state, data, n); 49 ctx->first_message_part = 0; 50 data += n; 51 len -= n; 52 } 53 store: 54 if (len) 55 memcpy(ctx->buf + index , data, len); 56 57 return 0; 58 } 59 EXPORT_SYMBOL_GPL(s390_sha_update); 60 61 static int s390_crypto_shash_parmsize(int func) 62 { 63 switch (func) { 64 case CPACF_KLMD_SHA_1: 65 return 20; 66 case CPACF_KLMD_SHA_256: 67 return 32; 68 case CPACF_KLMD_SHA_512: 69 return 64; 70 case CPACF_KLMD_SHA3_224: 71 case CPACF_KLMD_SHA3_256: 72 case CPACF_KLMD_SHA3_384: 73 case CPACF_KLMD_SHA3_512: 74 return 200; 75 default: 76 return -EINVAL; 77 } 78 } 79 80 int s390_sha_final(struct shash_desc *desc, u8 *out) 81 { 82 struct s390_sha_ctx *ctx = shash_desc_ctx(desc); 83 unsigned int bsize = crypto_shash_blocksize(desc->tfm); 84 u64 bits; 85 unsigned int n; 86 int mbl_offset, fc; 87 88 n = ctx->count % bsize; 89 bits = ctx->count * 8; 90 mbl_offset = s390_crypto_shash_parmsize(ctx->func); 91 if (mbl_offset < 0) 92 return -EINVAL; 93 94 mbl_offset = mbl_offset / sizeof(u32); 95 96 /* set total msg bit length (mbl) in CPACF parmblock */ 97 switch (ctx->func) { 98 case CPACF_KLMD_SHA_1: 99 case CPACF_KLMD_SHA_256: 100 memcpy(ctx->state + mbl_offset, &bits, sizeof(bits)); 101 break; 102 case CPACF_KLMD_SHA_512: 103 /* 104 * the SHA512 parmblock has a 128-bit mbl field, clear 105 * high-order u64 field, copy bits to low-order u64 field 106 */ 107 memset(ctx->state + mbl_offset, 0x00, sizeof(bits)); 108 mbl_offset += sizeof(u64) / sizeof(u32); 109 memcpy(ctx->state + mbl_offset, &bits, sizeof(bits)); 110 break; 111 case CPACF_KLMD_SHA3_224: 112 case CPACF_KLMD_SHA3_256: 113 case CPACF_KLMD_SHA3_384: 114 case CPACF_KLMD_SHA3_512: 115 break; 116 default: 117 return -EINVAL; 118 } 119 120 fc = ctx->func; 121 fc |= test_facility(86) ? CPACF_KLMD_DUFOP : 0; 122 if (ctx->first_message_part) 123 fc |= CPACF_KLMD_NIP; 124 cpacf_klmd(fc, ctx->state, ctx->buf, n); 125 126 /* copy digest to out */ 127 memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm)); 128 /* wipe context */ 129 memset(ctx, 0, sizeof *ctx); 130 131 return 0; 132 } 133 EXPORT_SYMBOL_GPL(s390_sha_final); 134 135 MODULE_LICENSE("GPL"); 136 MODULE_DESCRIPTION("s390 SHA cipher common functions"); 137