]> git.ipfire.org Git - thirdparty/strongswan.git/blame - programs/charon/lib/crypto/hmac.c
- import of strongswan-2.7.0
[thirdparty/strongswan.git] / programs / charon / lib / crypto / hmac.c
CommitLineData
781fadcc
MW
1/**
2 * @file hmac.c
3 *
7a09fcea 4 * @brief Implementation of hmac_t.
781fadcc
MW
5 */
6
7/*
8 * Copyright (C) 2005 Jan Hutter, Martin Willi
9 * Hochschule fuer Technik Rapperswil
10 *
11 * This program is free software; you can redistribute it and/or modify it
7a09fcea 12 * under the terms of the GNU General hmac License as published by the
781fadcc
MW
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
7a09fcea 18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General hmac License
781fadcc
MW
19 * for more details.
20 */
21
5113680f 22#include <string.h>
781fadcc
MW
23
24#include "hmac.h"
25
7a09fcea 26
5796aa16
MW
27typedef struct private_hmac_t private_hmac_t;
28
781fadcc 29/**
1e7d52a6
JH
30 * Private data of a hmac_t object.
31 *
32 * The variable names are the same as in the RFC.
781fadcc 33 */
5796aa16 34struct private_hmac_t {
781fadcc 35 /**
1e7d52a6 36 * Public hmac_t interface.
781fadcc 37 */
7a09fcea 38 hmac_t hmac;
781fadcc 39
781fadcc 40 /**
1e7d52a6 41 * Block size, as in RFC.
781fadcc
MW
42 */
43 u_int8_t b;
44
45 /**
1e7d52a6 46 * Hash function.
781fadcc
MW
47 */
48 hasher_t *h;
49
50 /**
1e7d52a6 51 * Previously xor'ed key using opad.
781fadcc
MW
52 */
53 chunk_t opaded_key;
1e7d52a6 54
781fadcc 55 /**
1e7d52a6 56 * Previously xor'ed key using ipad.
781fadcc
MW
57 */
58 chunk_t ipaded_key;
59};
60
61/**
7a09fcea 62 * Implementation of hmac_t.get_mac.
781fadcc 63 */
d048df5c 64static void get_mac(private_hmac_t *this, chunk_t data, u_int8_t *out)
781fadcc 65{
1318dd4e
MW
66 /* H(K XOR opad, H(K XOR ipad, text))
67 *
68 * if out is NULL, we append text to the inner hash.
69 * else, we complete the inner and do the outer.
70 *
71 */
72
52923c9a 73 u_int8_t buffer[this->h->get_hash_size(this->h)];
781fadcc 74 chunk_t inner;
781fadcc 75
1318dd4e
MW
76 if (out == NULL)
77 {
78 /* append data to inner */
79 this->h->get_hash(this->h, data, NULL);
80 }
81 else
82 {
83 /* append and do outer hash */
84 inner.ptr = buffer;
52923c9a 85 inner.len = this->h->get_hash_size(this->h);
1318dd4e
MW
86
87 /* complete inner */
88 this->h->get_hash(this->h, data, buffer);
89
90 /* do outer */
91 this->h->get_hash(this->h, this->opaded_key, NULL);
92 this->h->get_hash(this->h, inner, out);
93
94 /* reinit for next call */
95 this->h->get_hash(this->h, this->ipaded_key, NULL);
96 }
781fadcc
MW
97}
98
99/**
7a09fcea 100 * Implementation of hmac_t.allocate_mac.
781fadcc 101 */
d048df5c 102static void allocate_mac(private_hmac_t *this, chunk_t data, chunk_t *out)
781fadcc
MW
103{
104 /* allocate space and use get_mac */
1318dd4e 105 if (out == NULL)
781fadcc 106 {
1318dd4e 107 /* append mode */
7a09fcea 108 this->hmac.get_mac(&(this->hmac), data, NULL);
1318dd4e
MW
109 }
110 else
111 {
52923c9a 112 out->len = this->h->get_hash_size(this->h);
5113680f 113 out->ptr = malloc(out->len);
7a09fcea 114 this->hmac.get_mac(&(this->hmac), data, out->ptr);
781fadcc 115 }
781fadcc
MW
116}
117
118/**
7a09fcea 119 * Implementation of hmac_t.get_block_size.
781fadcc
MW
120 */
121static size_t get_block_size(private_hmac_t *this)
122{
52923c9a 123 return this->h->get_hash_size(this->h);
781fadcc
MW
124}
125
a217b51d 126/**
7a09fcea 127 * Implementation of hmac_t.set_key.
a217b51d 128 */
d048df5c 129static void set_key(private_hmac_t *this, chunk_t key)
a217b51d
MW
130{
131 int i;
132 u_int8_t buffer[this->b];
133
134 memset(buffer, 0, this->b);
135
136 if (key.len > this->b)
137 {
138 /* if key is too long, it will be hashed */
139 this->h->get_hash(this->h, key, buffer);
140 }
141 else
142 {
143 /* if not, just copy it in our pre-padded k */
144 memcpy(buffer, key.ptr, key.len);
145 }
146
147 /* apply ipad and opad to key */
148 for (i = 0; i < this->b; i++)
149 {
150 this->ipaded_key.ptr[i] = buffer[i] ^ 0x36;
151 this->opaded_key.ptr[i] = buffer[i] ^ 0x5C;
152 }
153
62adf1e0 154 /* begin hashing of inner pad */
1318dd4e
MW
155 this->h->reset(this->h);
156 this->h->get_hash(this->h, this->ipaded_key, NULL);
a217b51d
MW
157}
158
781fadcc 159/**
7a09fcea 160 * Implementation of hmac_t.destroy.
781fadcc 161 */
d048df5c 162static void destroy(private_hmac_t *this)
781fadcc
MW
163{
164 this->h->destroy(this->h);
5113680f
MW
165 free(this->opaded_key.ptr);
166 free(this->ipaded_key.ptr);
167 free(this);
781fadcc
MW
168}
169
170/*
171 * Described in header
172 */
a217b51d 173hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
781fadcc
MW
174{
175 private_hmac_t *this;
781fadcc 176
5113680f 177 this = malloc_thing(private_hmac_t);
d048df5c 178
7a09fcea 179 /* set hmac_t methods */
d048df5c
MW
180 this->hmac.get_mac = (void (*)(hmac_t *,chunk_t,u_int8_t*))get_mac;
181 this->hmac.allocate_mac = (void (*)(hmac_t *,chunk_t,chunk_t*))allocate_mac;
7a09fcea 182 this->hmac.get_block_size = (size_t (*)(hmac_t *))get_block_size;
d048df5c
MW
183 this->hmac.set_key = (void (*)(hmac_t *,chunk_t))set_key;
184 this->hmac.destroy = (void (*)(hmac_t *))destroy;
781fadcc
MW
185
186 /* set b, according to hasher */
187 switch (hash_algorithm)
188 {
189 case HASH_SHA1:
1484eedb 190 case HASH_MD5:
781fadcc
MW
191 this->b = 64;
192 break;
193 default:
5113680f 194 free(this);
781fadcc
MW
195 return NULL;
196 }
197
198 /* build the hasher */
199 this->h = hasher_create(hash_algorithm);
781fadcc
MW
200
201 /* build ipad and opad */
5113680f 202 this->opaded_key.ptr = malloc(this->b);
781fadcc 203 this->opaded_key.len = this->b;
d048df5c 204
5113680f 205 this->ipaded_key.ptr = malloc(this->b);
781fadcc 206 this->ipaded_key.len = this->b;
a217b51d 207
7a09fcea 208 return &(this->hmac);
781fadcc 209}