Annotation of embedaddon/strongswan/src/libstrongswan/plugins/af_alg/af_alg_prf.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2010 Martin Willi
3: * Copyright (C) 2010 revosec AG
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "af_alg_prf.h"
17: #include "af_alg_ops.h"
18:
19: typedef struct private_af_alg_prf_t private_af_alg_prf_t;
20:
21: /**
22: * Private data of a af_alg_prf_t object.
23: */
24: struct private_af_alg_prf_t {
25:
26: /**
27: * Public af_alg_prf_t interface.
28: */
29: af_alg_prf_t public;
30:
31: /**
32: * AF_ALG operations
33: */
34: af_alg_ops_t *ops;
35:
36: /**
37: * Size of the PRF output
38: */
39: size_t block_size;
40:
41: /**
42: * Default key size
43: */
44: size_t key_size;
45:
46: /**
47: * Using an XCBC algorithm?
48: */
49: bool xcbc;
50: };
51:
52: /**
53: * Algorithm database
54: */
55: static struct {
56: pseudo_random_function_t id;
57: char *name;
58: size_t block_size;
59: bool xcbc;
60: } algs[AF_ALG_PRF] = {
61: {PRF_HMAC_SHA1, "hmac(sha1)", 20, FALSE, },
62: {PRF_HMAC_SHA2_256, "hmac(sha256)", 32, FALSE, },
63: {PRF_HMAC_MD5, "hmac(md5)", 16, FALSE, },
64: {PRF_HMAC_SHA2_384, "hmac(sha384)", 48, FALSE, },
65: {PRF_HMAC_SHA2_512, "hmac(sha512)", 64, FALSE, },
66: {PRF_AES128_XCBC, "xcbc(aes)", 16, TRUE, },
67: {PRF_CAMELLIA128_XCBC, "xcbc(camellia)", 16, TRUE, },
68: };
69:
70: /**
71: * See header.
72: */
73: void af_alg_prf_probe(plugin_feature_t *features, int *pos)
74: {
75: af_alg_ops_t *ops;
76: int i;
77:
78: for (i = 0; i < countof(algs); i++)
79: {
80: ops = af_alg_ops_create("hash", algs[i].name);
81: if (ops)
82: {
83: ops->destroy(ops);
84: features[(*pos)++] = PLUGIN_PROVIDE(PRF, algs[i].id);
85: }
86: }
87: }
88:
89: /**
90: * Get the kernel algorithm string and block size for our identifier
91: */
92: static size_t lookup_alg(pseudo_random_function_t algo, char **name, bool *xcbc)
93: {
94: int i;
95:
96: for (i = 0; i < countof(algs); i++)
97: {
98: if (algs[i].id == algo)
99: {
100: *name = algs[i].name;
101: *xcbc = algs[i].xcbc;
102: return algs[i].block_size;
103: }
104: }
105: return 0;
106: }
107:
108: METHOD(prf_t, get_bytes, bool,
109: private_af_alg_prf_t *this, chunk_t seed, uint8_t *buffer)
110: {
111: return this->ops->hash(this->ops, seed, buffer, this->block_size);
112: }
113:
114: METHOD(prf_t, allocate_bytes, bool,
115: private_af_alg_prf_t *this, chunk_t seed, chunk_t *chunk)
116: {
117: if (chunk)
118: {
119: *chunk = chunk_alloc(this->block_size);
120: return get_bytes(this, seed, chunk->ptr);
121: }
122: return get_bytes(this, seed, NULL);
123: }
124:
125: METHOD(prf_t, get_block_size, size_t,
126: private_af_alg_prf_t *this)
127: {
128: return this->block_size;
129: }
130:
131: METHOD(prf_t, get_key_size, size_t,
132: private_af_alg_prf_t *this)
133: {
134: return this->block_size;
135: }
136:
137: METHOD(prf_t, set_key, bool,
138: private_af_alg_prf_t *this, chunk_t key)
139: {
140: char buf[this->block_size];
141:
142: this->ops->reset(this->ops);
143: if (this->xcbc)
144: {
145: /* The kernel currently does not support variable length XCBC keys,
146: * do RFC4434 key padding/reduction manually. */
147: if (key.len < this->block_size)
148: {
149: memset(buf, 0, this->block_size);
150: memcpy(buf, key.ptr, key.len);
151: key = chunk_from_thing(buf);
152: }
153: else if (key.len > this->block_size)
154: {
155: memset(buf, 0, this->block_size);
156: if (!this->ops->set_key(this->ops, chunk_from_thing(buf)) ||
157: !this->ops->hash(this->ops, key, buf, this->block_size))
158: {
159: return FALSE;
160: }
161: key = chunk_from_thing(buf);
162: }
163: }
164: return this->ops->set_key(this->ops, key);
165: }
166:
167: METHOD(prf_t, destroy, void,
168: private_af_alg_prf_t *this)
169: {
170: this->ops->destroy(this->ops);
171: free(this);
172: }
173:
174: /*
175: * Described in header.
176: */
177: af_alg_prf_t *af_alg_prf_create(pseudo_random_function_t algo)
178: {
179: private_af_alg_prf_t *this;
180: size_t block_size;
181: bool xcbc;
182: char *name;
183:
184: block_size = lookup_alg(algo, &name, &xcbc);
185: if (!block_size)
186: { /* not supported by kernel */
187: return NULL;
188: }
189:
190: INIT(this,
191: .public = {
192: .prf = {
193: .get_bytes = _get_bytes,
194: .allocate_bytes = _allocate_bytes,
195: .get_block_size = _get_block_size,
196: .get_key_size = _get_key_size,
197: .set_key = _set_key,
198: .destroy = _destroy,
199: },
200: },
201: .ops = af_alg_ops_create("hash", name),
202: .block_size = block_size,
203: .xcbc = xcbc,
204: );
205: if (!this->ops)
206: {
207: free(this);
208: return NULL;
209: }
210: return &this->public;
211: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>