linux/arch/s390/crypto/sha_common.c
<<
>>
Prefs
   1/*
   2 * Cryptographic API.
   3 *
   4 * s390 generic implementation of the SHA Secure Hash Algorithms.
   5 *
   6 * Copyright IBM Corp. 2007
   7 * Author(s): Jan Glauber (jang@de.ibm.com)
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms of the GNU General Public License as published by the Free
  11 * Software Foundation; either version 2 of the License, or (at your option)
  12 * any later version.
  13 *
  14 */
  15
  16#include <crypto/internal/hash.h>
  17#include <linux/module.h>
  18#include "sha.h"
  19#include "crypt_s390.h"
  20
  21int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
  22{
  23        struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
  24        unsigned int bsize = crypto_shash_blocksize(desc->tfm);
  25        unsigned int index;
  26        int ret;
  27
  28        /* how much is already in the buffer? */
  29        index = ctx->count & (bsize - 1);
  30        ctx->count += len;
  31
  32        if ((index + len) < bsize)
  33                goto store;
  34
  35        /* process one stored block */
  36        if (index) {
  37                memcpy(ctx->buf + index, data, bsize - index);
  38                ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, bsize);
  39                if (ret != bsize)
  40                        return -EIO;
  41                data += bsize - index;
  42                len -= bsize - index;
  43                index = 0;
  44        }
  45
  46        /* process as many blocks as possible */
  47        if (len >= bsize) {
  48                ret = crypt_s390_kimd(ctx->func, ctx->state, data,
  49                                      len & ~(bsize - 1));
  50                if (ret != (len & ~(bsize - 1)))
  51                        return -EIO;
  52                data += ret;
  53                len -= ret;
  54        }
  55store:
  56        if (len)
  57                memcpy(ctx->buf + index , data, len);
  58
  59        return 0;
  60}
  61EXPORT_SYMBOL_GPL(s390_sha_update);
  62
  63int s390_sha_final(struct shash_desc *desc, u8 *out)
  64{
  65        struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
  66        unsigned int bsize = crypto_shash_blocksize(desc->tfm);
  67        u64 bits;
  68        unsigned int index, end, plen;
  69        int ret;
  70
  71        /* SHA-512 uses 128 bit padding length */
  72        plen = (bsize > SHA256_BLOCK_SIZE) ? 16 : 8;
  73
  74        /* must perform manual padding */
  75        index = ctx->count & (bsize - 1);
  76        end = (index < bsize - plen) ? bsize : (2 * bsize);
  77
  78        /* start pad with 1 */
  79        ctx->buf[index] = 0x80;
  80        index++;
  81
  82        /* pad with zeros */
  83        memset(ctx->buf + index, 0x00, end - index - 8);
  84
  85        /*
  86         * Append message length. Well, SHA-512 wants a 128 bit length value,
  87         * nevertheless we use u64, should be enough for now...
  88         */
  89        bits = ctx->count * 8;
  90        memcpy(ctx->buf + end - 8, &bits, sizeof(bits));
  91
  92        ret = crypt_s390_kimd(ctx->func, ctx->state, ctx->buf, end);
  93        if (ret != end)
  94                return -EIO;
  95
  96        /* copy digest to out */
  97        memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
  98        /* wipe context */
  99        memset(ctx, 0, sizeof *ctx);
 100
 101        return 0;
 102}
 103EXPORT_SYMBOL_GPL(s390_sha_final);
 104
 105MODULE_LICENSE("GPL");
 106MODULE_DESCRIPTION("s390 SHA cipher common functions");
 107