Annotation of embedaddon/strongswan/src/libstrongswan/plugins/hmac/hmac.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012 Tobias Brunner
3: * Copyright (C) 2005-2006 Martin Willi
4: * Copyright (C) 2005 Jan Hutter
5: * HSR Hochschule fuer Technik Rapperswil
6: *
7: * This program is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2 of the License, or (at your
10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15: * for more details.
16: */
17:
18: #include "hmac.h"
19:
20: #include <crypto/mac.h>
21: #include <crypto/prfs/mac_prf.h>
22: #include <crypto/signers/mac_signer.h>
23:
24: typedef struct private_mac_t private_mac_t;
25:
26: /**
27: * Private data of a mac_t object.
28: *
29: * The variable names are the same as in the RFC.
30: */
31: struct private_mac_t {
32:
33: /**
34: * Implements mac_t interface
35: */
36: mac_t public;
37:
38: /**
39: * Block size, as in RFC.
40: */
41: uint8_t b;
42:
43: /**
44: * Hash function.
45: */
46: hasher_t *h;
47:
48: /**
49: * Previously xor'ed key using opad.
50: */
51: chunk_t opaded_key;
52:
53: /**
54: * Previously xor'ed key using ipad.
55: */
56: chunk_t ipaded_key;
57: };
58:
59: METHOD(mac_t, get_mac, bool,
60: private_mac_t *this, chunk_t data, uint8_t *out)
61: {
62: /* H(K XOR opad, H(K XOR ipad, text))
63: *
64: * if out is NULL, we append text to the inner hash.
65: * else, we complete the inner and do the outer.
66: *
67: */
68:
69: uint8_t buffer[this->h->get_hash_size(this->h)];
70: chunk_t inner;
71:
72: if (out == NULL)
73: {
74: /* append data to inner */
75: return this->h->get_hash(this->h, data, NULL);
76: }
77:
78: /* append and do outer hash */
79: inner.ptr = buffer;
80: inner.len = this->h->get_hash_size(this->h);
81:
82: /* complete inner, do outer and reinit for next call */
83: return this->h->get_hash(this->h, data, buffer) &&
84: this->h->get_hash(this->h, this->opaded_key, NULL) &&
85: this->h->get_hash(this->h, inner, out) &&
86: this->h->get_hash(this->h, this->ipaded_key, NULL);
87: }
88:
89: METHOD(mac_t, get_mac_size, size_t,
90: private_mac_t *this)
91: {
92: return this->h->get_hash_size(this->h);
93: }
94:
95: METHOD(mac_t, set_key, bool,
96: private_mac_t *this, chunk_t key)
97: {
98: int i;
99: uint8_t buffer[this->b];
100:
101: memset(buffer, 0, this->b);
102:
103: if (key.len > this->b)
104: {
105: /* if key is too long, it will be hashed */
106: if (!this->h->reset(this->h) ||
107: !this->h->get_hash(this->h, key, buffer))
108: {
109: return FALSE;
110: }
111: }
112: else
113: {
114: /* if not, just copy it in our pre-padded k */
115: memcpy(buffer, key.ptr, key.len);
116: }
117:
118: /* apply ipad and opad to key */
119: for (i = 0; i < this->b; i++)
120: {
121: this->ipaded_key.ptr[i] = buffer[i] ^ 0x36;
122: this->opaded_key.ptr[i] = buffer[i] ^ 0x5C;
123: }
124:
125: /* begin hashing of inner pad */
126: return this->h->reset(this->h) &&
127: this->h->get_hash(this->h, this->ipaded_key, NULL);
128: }
129:
130: METHOD(mac_t, destroy, void,
131: private_mac_t *this)
132: {
133: this->h->destroy(this->h);
134: chunk_clear(&this->opaded_key);
135: chunk_clear(&this->ipaded_key);
136: free(this);
137: }
138:
139: /*
140: * Creates an mac_t object
141: */
142: static mac_t *hmac_create(hash_algorithm_t hash_algorithm)
143: {
144: private_mac_t *this;
145:
146: INIT(this,
147: .public = {
148: .get_mac = _get_mac,
149: .get_mac_size = _get_mac_size,
150: .set_key = _set_key,
151: .destroy = _destroy,
152: },
153: );
154:
155: /* set b, according to hasher */
156: switch (hash_algorithm)
157: {
158: case HASH_SHA1:
159: case HASH_MD5:
160: case HASH_SHA256:
161: this->b = 64;
162: break;
163: case HASH_SHA384:
164: case HASH_SHA512:
165: this->b = 128;
166: break;
167: default:
168: free(this);
169: return NULL;
170: }
171:
172: this->h = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
173: if (this->h == NULL)
174: {
175: free(this);
176: return NULL;
177: }
178:
179: /* build ipad and opad */
180: this->opaded_key.ptr = malloc(this->b);
181: this->opaded_key.len = this->b;
182:
183: this->ipaded_key.ptr = malloc(this->b);
184: this->ipaded_key.len = this->b;
185:
186: return &this->public;
187: }
188:
189: /*
190: * Described in header
191: */
192: prf_t *hmac_prf_create(pseudo_random_function_t algo)
193: {
194: mac_t *hmac;
195:
196: hmac = hmac_create(hasher_algorithm_from_prf(algo));
197: if (hmac)
198: {
199: return mac_prf_create(hmac);
200: }
201: return NULL;
202: }
203:
204: /*
205: * Described in header
206: */
207: signer_t *hmac_signer_create(integrity_algorithm_t algo)
208: {
209: mac_t *hmac;
210: size_t trunc;
211:
212: hmac = hmac_create(hasher_algorithm_from_integrity(algo, &trunc));
213: if (hmac)
214: {
215: return mac_signer_create(hmac, trunc);
216: }
217: return NULL;
218: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>