simplified the OpenSSL hasher a bit
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_hasher.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
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 * $Id$
16 */
17
18 #include "openssl_hasher.h"
19
20 #include <openssl/evp.h>
21
22 typedef struct private_openssl_hasher_t private_openssl_hasher_t;
23
24 /**
25 * Private data of openssl_hasher_t
26 */
27 struct private_openssl_hasher_t {
28
29 /**
30 * Public part of this class.
31 */
32 openssl_hasher_t public;
33
34 /**
35 * the hasher to use
36 */
37 const EVP_MD *hasher;
38
39 /**
40 * the current digest context
41 */
42 EVP_MD_CTX *ctx;
43 };
44
45 /**
46 * Mapping from the algorithms defined in IKEv2 to
47 * OpenSSL algorithm names
48 */
49 typedef struct {
50 /**
51 * Identifier specified in IKEv2
52 */
53 int ikev2_id;
54
55 /**
56 * Name of the algorithm, as used in OpenSSL
57 */
58 char *name;
59 } openssl_algorithm_t;
60
61 #define END_OF_LIST -1
62
63 /**
64 * Algorithms for integrity
65 */
66 static openssl_algorithm_t integrity_algs[] = {
67 {HASH_MD2, "md2"},
68 {HASH_MD5, "md5"},
69 {HASH_SHA1, "sha1"},
70 {HASH_SHA256, "sha256"},
71 {HASH_SHA384, "sha384"},
72 {HASH_SHA512, "sha512"},
73 {END_OF_LIST, NULL},
74 };
75
76 /**
77 * Look up an OpenSSL algorithm name
78 */
79 static char* lookup_algorithm(openssl_algorithm_t *openssl_algo,
80 u_int16_t ikev2_algo)
81 {
82 while (openssl_algo->ikev2_id != END_OF_LIST)
83 {
84 if (ikev2_algo == openssl_algo->ikev2_id)
85 {
86 return openssl_algo->name;
87 }
88 openssl_algo++;
89 }
90 return NULL;
91 }
92
93 /**
94 * Implementation of hasher_t.get_hash_size.
95 */
96 static size_t get_hash_size(private_openssl_hasher_t *this)
97 {
98 return this->hasher->md_size;
99 }
100
101 /**
102 * Implementation of hasher_t.reset.
103 */
104 static void reset(private_openssl_hasher_t *this)
105 {
106 EVP_DigestInit_ex(this->ctx, this->hasher, NULL);
107 }
108
109 /**
110 * Implementation of hasher_t.get_hash.
111 */
112 static void get_hash(private_openssl_hasher_t *this, chunk_t chunk,
113 u_int8_t *hash)
114 {
115 EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len);
116 if (hash)
117 {
118 EVP_DigestFinal_ex(this->ctx, hash, NULL);
119 reset(this);
120 }
121 }
122
123 /**
124 * Implementation of hasher_t.allocate_hash.
125 */
126 static void allocate_hash(private_openssl_hasher_t *this, chunk_t chunk,
127 chunk_t *hash)
128 {
129 if (hash)
130 {
131 *hash = chunk_alloc(get_hash_size(this));
132 get_hash(this, chunk, hash->ptr);
133 }
134 else
135 {
136 get_hash(this, chunk, NULL);
137 }
138 }
139
140 /**
141 * Implementation of hasher_t.destroy.
142 */
143 static void destroy (private_openssl_hasher_t *this)
144 {
145 EVP_MD_CTX_destroy(this->ctx);
146 free(this);
147 }
148
149 /*
150 * Described in header
151 */
152 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
153 {
154 private_openssl_hasher_t *this;
155
156 char* name = lookup_algorithm(integrity_algs, algo);
157 if (!name)
158 {
159 /* algo unavailable */
160 return NULL;
161 }
162
163 this = malloc_thing(private_openssl_hasher_t);
164
165 this->hasher = EVP_get_digestbyname(name);
166 if (!this->hasher)
167 {
168 /* OpenSSL does not support the requested algo */
169 free(this);
170 return NULL;
171 }
172
173 this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
174 this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
175 this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size;
176 this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
177 this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
178
179 this->ctx = EVP_MD_CTX_create();
180
181 /* initialization */
182 reset(this);
183
184 return &this->public;
185 }