OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [crypto/] [hmac.c] - Blame information for rev 86

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Cryptographic API.
3
 *
4
 * HMAC: Keyed-Hashing for Message Authentication (RFC2104).
5
 *
6
 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
7
 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
8
 *
9
 * The HMAC implementation is derived from USAGI.
10
 * Copyright (c) 2002 Kazunori Miyazawa <miyazawa@linux-ipv6.org> / USAGI
11
 *
12
 * This program is free software; you can redistribute it and/or modify it
13
 * under the terms of the GNU General Public License as published by the Free
14
 * Software Foundation; either version 2 of the License, or (at your option)
15
 * any later version.
16
 *
17
 */
18
 
19
#include <crypto/algapi.h>
20
#include <linux/err.h>
21
#include <linux/init.h>
22
#include <linux/kernel.h>
23
#include <linux/module.h>
24
#include <linux/scatterlist.h>
25
#include <linux/slab.h>
26
#include <linux/string.h>
27
 
28
struct hmac_ctx {
29
        struct crypto_hash *child;
30
};
31
 
32
static inline void *align_ptr(void *p, unsigned int align)
33
{
34
        return (void *)ALIGN((unsigned long)p, align);
35
}
36
 
37
static inline struct hmac_ctx *hmac_ctx(struct crypto_hash *tfm)
38
{
39
        return align_ptr(crypto_hash_ctx_aligned(tfm) +
40
                         crypto_hash_blocksize(tfm) * 2 +
41
                         crypto_hash_digestsize(tfm), sizeof(void *));
42
}
43
 
44
static int hmac_setkey(struct crypto_hash *parent,
45
                       const u8 *inkey, unsigned int keylen)
46
{
47
        int bs = crypto_hash_blocksize(parent);
48
        int ds = crypto_hash_digestsize(parent);
49
        char *ipad = crypto_hash_ctx_aligned(parent);
50
        char *opad = ipad + bs;
51
        char *digest = opad + bs;
52
        struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
53
        struct crypto_hash *tfm = ctx->child;
54
        unsigned int i;
55
 
56
        if (keylen > bs) {
57
                struct hash_desc desc;
58
                struct scatterlist tmp;
59
                int err;
60
 
61
                desc.tfm = tfm;
62
                desc.flags = crypto_hash_get_flags(parent);
63
                desc.flags &= CRYPTO_TFM_REQ_MAY_SLEEP;
64
                sg_init_one(&tmp, inkey, keylen);
65
 
66
                err = crypto_hash_digest(&desc, &tmp, keylen, digest);
67
                if (err)
68
                        return err;
69
 
70
                inkey = digest;
71
                keylen = ds;
72
        }
73
 
74
        memcpy(ipad, inkey, keylen);
75
        memset(ipad + keylen, 0, bs - keylen);
76
        memcpy(opad, ipad, bs);
77
 
78
        for (i = 0; i < bs; i++) {
79
                ipad[i] ^= 0x36;
80
                opad[i] ^= 0x5c;
81
        }
82
 
83
        return 0;
84
}
85
 
86
static int hmac_init(struct hash_desc *pdesc)
87
{
88
        struct crypto_hash *parent = pdesc->tfm;
89
        int bs = crypto_hash_blocksize(parent);
90
        int ds = crypto_hash_digestsize(parent);
91
        char *ipad = crypto_hash_ctx_aligned(parent);
92
        struct hmac_ctx *ctx = align_ptr(ipad + bs * 2 + ds, sizeof(void *));
93
        struct hash_desc desc;
94
        struct scatterlist tmp;
95
        int err;
96
 
97
        desc.tfm = ctx->child;
98
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
99
        sg_init_one(&tmp, ipad, bs);
100
 
101
        err = crypto_hash_init(&desc);
102
        if (unlikely(err))
103
                return err;
104
 
105
        return crypto_hash_update(&desc, &tmp, bs);
106
}
107
 
108
static int hmac_update(struct hash_desc *pdesc,
109
                       struct scatterlist *sg, unsigned int nbytes)
110
{
111
        struct hmac_ctx *ctx = hmac_ctx(pdesc->tfm);
112
        struct hash_desc desc;
113
 
114
        desc.tfm = ctx->child;
115
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
116
 
117
        return crypto_hash_update(&desc, sg, nbytes);
118
}
119
 
120
static int hmac_final(struct hash_desc *pdesc, u8 *out)
121
{
122
        struct crypto_hash *parent = pdesc->tfm;
123
        int bs = crypto_hash_blocksize(parent);
124
        int ds = crypto_hash_digestsize(parent);
125
        char *opad = crypto_hash_ctx_aligned(parent) + bs;
126
        char *digest = opad + bs;
127
        struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
128
        struct hash_desc desc;
129
        struct scatterlist tmp;
130
        int err;
131
 
132
        desc.tfm = ctx->child;
133
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
134
        sg_init_one(&tmp, opad, bs + ds);
135
 
136
        err = crypto_hash_final(&desc, digest);
137
        if (unlikely(err))
138
                return err;
139
 
140
        return crypto_hash_digest(&desc, &tmp, bs + ds, out);
141
}
142
 
143
static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
144
                       unsigned int nbytes, u8 *out)
145
{
146
        struct crypto_hash *parent = pdesc->tfm;
147
        int bs = crypto_hash_blocksize(parent);
148
        int ds = crypto_hash_digestsize(parent);
149
        char *ipad = crypto_hash_ctx_aligned(parent);
150
        char *opad = ipad + bs;
151
        char *digest = opad + bs;
152
        struct hmac_ctx *ctx = align_ptr(digest + ds, sizeof(void *));
153
        struct hash_desc desc;
154
        struct scatterlist sg1[2];
155
        struct scatterlist sg2[1];
156
        int err;
157
 
158
        desc.tfm = ctx->child;
159
        desc.flags = pdesc->flags & CRYPTO_TFM_REQ_MAY_SLEEP;
160
 
161
        sg_init_table(sg1, 2);
162
        sg_set_buf(sg1, ipad, bs);
163
        sg_set_page(&sg1[1], (void *) sg, 0, 0);
164
 
165
        sg_init_table(sg2, 1);
166
        sg_set_buf(sg2, opad, bs + ds);
167
 
168
        err = crypto_hash_digest(&desc, sg1, nbytes + bs, digest);
169
        if (unlikely(err))
170
                return err;
171
 
172
        return crypto_hash_digest(&desc, sg2, bs + ds, out);
173
}
174
 
175
static int hmac_init_tfm(struct crypto_tfm *tfm)
176
{
177
        struct crypto_hash *hash;
178
        struct crypto_instance *inst = (void *)tfm->__crt_alg;
179
        struct crypto_spawn *spawn = crypto_instance_ctx(inst);
180
        struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
181
 
182
        hash = crypto_spawn_hash(spawn);
183
        if (IS_ERR(hash))
184
                return PTR_ERR(hash);
185
 
186
        ctx->child = hash;
187
        return 0;
188
}
189
 
190
static void hmac_exit_tfm(struct crypto_tfm *tfm)
191
{
192
        struct hmac_ctx *ctx = hmac_ctx(__crypto_hash_cast(tfm));
193
        crypto_free_hash(ctx->child);
194
}
195
 
196
static void hmac_free(struct crypto_instance *inst)
197
{
198
        crypto_drop_spawn(crypto_instance_ctx(inst));
199
        kfree(inst);
200
}
201
 
202
static struct crypto_instance *hmac_alloc(struct rtattr **tb)
203
{
204
        struct crypto_instance *inst;
205
        struct crypto_alg *alg;
206
        int err;
207
 
208
        err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_HASH);
209
        if (err)
210
                return ERR_PTR(err);
211
 
212
        alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_HASH,
213
                                  CRYPTO_ALG_TYPE_HASH_MASK);
214
        if (IS_ERR(alg))
215
                return ERR_PTR(PTR_ERR(alg));
216
 
217
        inst = crypto_alloc_instance("hmac", alg);
218
        if (IS_ERR(inst))
219
                goto out_put_alg;
220
 
221
        inst->alg.cra_flags = CRYPTO_ALG_TYPE_HASH;
222
        inst->alg.cra_priority = alg->cra_priority;
223
        inst->alg.cra_blocksize = alg->cra_blocksize;
224
        inst->alg.cra_alignmask = alg->cra_alignmask;
225
        inst->alg.cra_type = &crypto_hash_type;
226
 
227
        inst->alg.cra_hash.digestsize =
228
                (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
229
                CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
230
                                       alg->cra_digest.dia_digestsize;
231
 
232
        inst->alg.cra_ctxsize = sizeof(struct hmac_ctx) +
233
                                ALIGN(inst->alg.cra_blocksize * 2 +
234
                                      inst->alg.cra_hash.digestsize,
235
                                      sizeof(void *));
236
 
237
        inst->alg.cra_init = hmac_init_tfm;
238
        inst->alg.cra_exit = hmac_exit_tfm;
239
 
240
        inst->alg.cra_hash.init = hmac_init;
241
        inst->alg.cra_hash.update = hmac_update;
242
        inst->alg.cra_hash.final = hmac_final;
243
        inst->alg.cra_hash.digest = hmac_digest;
244
        inst->alg.cra_hash.setkey = hmac_setkey;
245
 
246
out_put_alg:
247
        crypto_mod_put(alg);
248
        return inst;
249
}
250
 
251
static struct crypto_template hmac_tmpl = {
252
        .name = "hmac",
253
        .alloc = hmac_alloc,
254
        .free = hmac_free,
255
        .module = THIS_MODULE,
256
};
257
 
258
static int __init hmac_module_init(void)
259
{
260
        return crypto_register_template(&hmac_tmpl);
261
}
262
 
263
static void __exit hmac_module_exit(void)
264
{
265
        crypto_unregister_template(&hmac_tmpl);
266
}
267
 
268
module_init(hmac_module_init);
269
module_exit(hmac_module_exit);
270
 
271
MODULE_LICENSE("GPL");
272
MODULE_DESCRIPTION("HMAC hash algorithm");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.