~ubuntu-branches/ubuntu/trusty/linux-linaro-omap/trusty

« back to all changes in this revision

Viewing changes to arch/s390/crypto/ghash_s390.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-57i0gl3v99b3lkfg
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Cryptographic API.
 
3
 *
 
4
 * s390 implementation of the GHASH algorithm for GCM (Galois/Counter Mode).
 
5
 *
 
6
 * Copyright IBM Corp. 2011
 
7
 * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
 
8
 */
 
9
 
 
10
#include <crypto/internal/hash.h>
 
11
#include <linux/module.h>
 
12
 
 
13
#include "crypt_s390.h"
 
14
 
 
15
#define GHASH_BLOCK_SIZE        16
 
16
#define GHASH_DIGEST_SIZE       16
 
17
 
 
18
struct ghash_ctx {
 
19
        u8 icv[16];
 
20
        u8 key[16];
 
21
};
 
22
 
 
23
struct ghash_desc_ctx {
 
24
        u8 buffer[GHASH_BLOCK_SIZE];
 
25
        u32 bytes;
 
26
};
 
27
 
 
28
static int ghash_init(struct shash_desc *desc)
 
29
{
 
30
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 
31
 
 
32
        memset(dctx, 0, sizeof(*dctx));
 
33
 
 
34
        return 0;
 
35
}
 
36
 
 
37
static int ghash_setkey(struct crypto_shash *tfm,
 
38
                        const u8 *key, unsigned int keylen)
 
39
{
 
40
        struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
 
41
 
 
42
        if (keylen != GHASH_BLOCK_SIZE) {
 
43
                crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
 
44
                return -EINVAL;
 
45
        }
 
46
 
 
47
        memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
 
48
        memset(ctx->icv, 0, GHASH_BLOCK_SIZE);
 
49
 
 
50
        return 0;
 
51
}
 
52
 
 
53
static int ghash_update(struct shash_desc *desc,
 
54
                         const u8 *src, unsigned int srclen)
 
55
{
 
56
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 
57
        struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
 
58
        unsigned int n;
 
59
        u8 *buf = dctx->buffer;
 
60
        int ret;
 
61
 
 
62
        if (dctx->bytes) {
 
63
                u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
 
64
 
 
65
                n = min(srclen, dctx->bytes);
 
66
                dctx->bytes -= n;
 
67
                srclen -= n;
 
68
 
 
69
                memcpy(pos, src, n);
 
70
                src += n;
 
71
 
 
72
                if (!dctx->bytes) {
 
73
                        ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf,
 
74
                                              GHASH_BLOCK_SIZE);
 
75
                        BUG_ON(ret != GHASH_BLOCK_SIZE);
 
76
                }
 
77
        }
 
78
 
 
79
        n = srclen & ~(GHASH_BLOCK_SIZE - 1);
 
80
        if (n) {
 
81
                ret = crypt_s390_kimd(KIMD_GHASH, ctx, src, n);
 
82
                BUG_ON(ret != n);
 
83
                src += n;
 
84
                srclen -= n;
 
85
        }
 
86
 
 
87
        if (srclen) {
 
88
                dctx->bytes = GHASH_BLOCK_SIZE - srclen;
 
89
                memcpy(buf, src, srclen);
 
90
        }
 
91
 
 
92
        return 0;
 
93
}
 
94
 
 
95
static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
 
96
{
 
97
        u8 *buf = dctx->buffer;
 
98
        int ret;
 
99
 
 
100
        if (dctx->bytes) {
 
101
                u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
 
102
 
 
103
                memset(pos, 0, dctx->bytes);
 
104
 
 
105
                ret = crypt_s390_kimd(KIMD_GHASH, ctx, buf, GHASH_BLOCK_SIZE);
 
106
                BUG_ON(ret != GHASH_BLOCK_SIZE);
 
107
        }
 
108
 
 
109
        dctx->bytes = 0;
 
110
}
 
111
 
 
112
static int ghash_final(struct shash_desc *desc, u8 *dst)
 
113
{
 
114
        struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 
115
        struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
 
116
 
 
117
        ghash_flush(ctx, dctx);
 
118
        memcpy(dst, ctx->icv, GHASH_BLOCK_SIZE);
 
119
 
 
120
        return 0;
 
121
}
 
122
 
 
123
static struct shash_alg ghash_alg = {
 
124
        .digestsize     = GHASH_DIGEST_SIZE,
 
125
        .init           = ghash_init,
 
126
        .update         = ghash_update,
 
127
        .final          = ghash_final,
 
128
        .setkey         = ghash_setkey,
 
129
        .descsize       = sizeof(struct ghash_desc_ctx),
 
130
        .base           = {
 
131
                .cra_name               = "ghash",
 
132
                .cra_driver_name        = "ghash-s390",
 
133
                .cra_priority           = CRYPT_S390_PRIORITY,
 
134
                .cra_flags              = CRYPTO_ALG_TYPE_SHASH,
 
135
                .cra_blocksize          = GHASH_BLOCK_SIZE,
 
136
                .cra_ctxsize            = sizeof(struct ghash_ctx),
 
137
                .cra_module             = THIS_MODULE,
 
138
                .cra_list               = LIST_HEAD_INIT(ghash_alg.base.cra_list),
 
139
        },
 
140
};
 
141
 
 
142
static int __init ghash_mod_init(void)
 
143
{
 
144
        if (!crypt_s390_func_available(KIMD_GHASH,
 
145
                                       CRYPT_S390_MSA | CRYPT_S390_MSA4))
 
146
                return -EOPNOTSUPP;
 
147
 
 
148
        return crypto_register_shash(&ghash_alg);
 
149
}
 
150
 
 
151
static void __exit ghash_mod_exit(void)
 
152
{
 
153
        crypto_unregister_shash(&ghash_alg);
 
154
}
 
155
 
 
156
module_init(ghash_mod_init);
 
157
module_exit(ghash_mod_exit);
 
158
 
 
159
MODULE_ALIAS("ghash");
 
160
 
 
161
MODULE_LICENSE("GPL");
 
162
MODULE_DESCRIPTION("GHASH Message Digest Algorithm, s390 implementation");