OpenSSL hasher does not need an internal buffer anymore
[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 if (this->ctx)
107 {
108 EVP_MD_CTX_destroy(this->ctx);
109 }
110 this->ctx = EVP_MD_CTX_create();
111 EVP_DigestInit_ex(this->ctx, this->hasher, NULL);
112 }
113
114 /**
115 * Implementation of hasher_t.get_hash.
116 */
117 static void get_hash(private_openssl_hasher_t *this, chunk_t chunk,
118 u_int8_t *hash)
119 {
120 EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len);
121 if (hash)
122 {
123 EVP_DigestFinal_ex(this->ctx, hash, NULL);
124 reset(this);
125 }
126 }
127
128 /**
129 * Implementation of hasher_t.allocate_hash.
130 */
131 static void allocate_hash(private_openssl_hasher_t *this, chunk_t chunk,
132 chunk_t *hash)
133 {
134 if (hash)
135 {
136 *hash = chunk_alloc(get_hash_size(this));
137 get_hash(this, chunk, hash->ptr);
138 }
139 else
140 {
141 get_hash(this, chunk, NULL);
142 }
143 }
144
145 /**
146 * Implementation of hasher_t.destroy.
147 */
148 static void destroy (private_openssl_hasher_t *this)
149 {
150 if (this->ctx)
151 {
152 EVP_MD_CTX_destroy(this->ctx);
153 }
154 free(this);
155 }
156
157 /*
158 * Described in header
159 */
160 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
161 {
162 private_openssl_hasher_t *this;
163
164 char* name = lookup_algorithm(integrity_algs, algo);
165 if (!name)
166 {
167 /* algo unavailable */
168 return NULL;
169 }
170
171 this = malloc_thing(private_openssl_hasher_t);
172
173 this->hasher = EVP_get_digestbyname(name);
174 if (!this->hasher)
175 {
176 /* OpenSSL does not support the requested algo */
177 free(this);
178 return NULL;
179 }
180
181 this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash;
182 this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash;
183 this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size;
184 this->public.hasher_interface.reset = (void (*) (hasher_t*))reset;
185 this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy;
186
187 this->ctx = NULL;
188
189 /* initialize */
190 reset(this);
191
192 return &this->public;
193 }