adding MD4 and DES (ECB) to openssl plugin
[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 {HASH_MD4, "md4"},
74 {END_OF_LIST, NULL},
75 };
76
77 /**
78 * Look up an OpenSSL algorithm name
79 */
80 static char* lookup_algorithm(openssl_algorithm_t *openssl_algo,
81 u_int16_t ikev2_algo)
82 {
83 while (openssl_algo->ikev2_id != END_OF_LIST)
84 {
85 if (ikev2_algo == openssl_algo->ikev2_id)
86 {
87 return openssl_algo->name;
88 }
89 openssl_algo++;
90 }
91 return NULL;
92 }
93
94 /**
95 * Implementation of hasher_t.get_hash_size.
96 */
97 static size_t get_hash_size(private_openssl_hasher_t *this)
98 {
99 return this->hasher->md_size;
100 }
101
102 /**
103 * Implementation of hasher_t.reset.
104 */
105 static void reset(private_openssl_hasher_t *this)
106 {
107 EVP_DigestInit_ex(this->ctx, this->hasher, NULL);
108 }
109
110 /**
111 * Implementation of hasher_t.get_hash.
112 */
113 static void get_hash(private_openssl_hasher_t *this, chunk_t chunk,
114 u_int8_t *hash)
115 {
116 EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len);
117 if (hash)
118 {
119 EVP_DigestFinal_ex(this->ctx, hash, NULL);
120 reset(this);
121 }
122 }
123
124 /**
125 * Implementation of hasher_t.allocate_hash.
126 */
127 static void allocate_hash(private_openssl_hasher_t *this, chunk_t chunk,
128 chunk_t *hash)
129 {
130 if (hash)
131 {
132 *hash = chunk_alloc(get_hash_size(this));
133 get_hash(this, chunk, hash->ptr);
134 }
135 else
136 {
137 get_hash(this, chunk, NULL);
138 }
139 }
140
141 /**
142 * Implementation of hasher_t.destroy.
143 */
144 static void destroy (private_openssl_hasher_t *this)
145 {
146 EVP_MD_CTX_destroy(this->ctx);
147 free(this);
148 }
149
150 /*
151 * Described in header
152 */
153 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
154 {
155 private_openssl_hasher_t *this;
156
157 char* name = lookup_algorithm(integrity_algs, algo);
158 if (!name)
159 {
160 /* algo unavailable */
161 return NULL;
162 }
163
164 this = malloc_thing(private_openssl_hasher_t);
165
166 this->hasher = EVP_get_digestbyname(name);
167 if (!this->hasher)
168 {
169 /* OpenSSL does not support the requested algo */
170 free(this);
171 return NULL;
172 }
173
174 this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
175 this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
176 this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size;
177 this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
178 this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
179
180 this->ctx = EVP_MD_CTX_create();
181
182 /* initialization */
183 reset(this);
184
185 return &this->public;
186 }