67b49c186161244d7c76aa0ea7bce1b2c118e37a
[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
16 #include "openssl_hasher.h"
17
18 #include <openssl/evp.h>
19
20 typedef struct private_openssl_hasher_t private_openssl_hasher_t;
21
22 /**
23 * Private data of openssl_hasher_t
24 */
25 struct private_openssl_hasher_t {
26
27 /**
28 * Public part of this class.
29 */
30 openssl_hasher_t public;
31
32 /**
33 * the hasher to use
34 */
35 const EVP_MD *hasher;
36
37 /**
38 * the current digest context
39 */
40 EVP_MD_CTX *ctx;
41 };
42
43 /**
44 * Mapping from the algorithms defined in IKEv2 to
45 * OpenSSL algorithm names
46 */
47 typedef struct {
48 /**
49 * Identifier specified in IKEv2
50 */
51 int ikev2_id;
52
53 /**
54 * Name of the algorithm, as used in OpenSSL
55 */
56 char *name;
57 } openssl_algorithm_t;
58
59 #define END_OF_LIST -1
60
61 /**
62 * Algorithms for integrity
63 */
64 static openssl_algorithm_t integrity_algs[] = {
65 {HASH_MD2, "md2"},
66 {HASH_MD5, "md5"},
67 {HASH_SHA1, "sha1"},
68 {HASH_SHA224, "sha224"},
69 {HASH_SHA256, "sha256"},
70 {HASH_SHA384, "sha384"},
71 {HASH_SHA512, "sha512"},
72 {HASH_MD4, "md4"},
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 METHOD(hasher_t, get_hash_size, size_t,
94 private_openssl_hasher_t *this)
95 {
96 return this->hasher->md_size;
97 }
98
99 METHOD(hasher_t, reset, void,
100 private_openssl_hasher_t *this)
101 {
102 EVP_DigestInit_ex(this->ctx, this->hasher, NULL);
103 }
104
105 METHOD(hasher_t, get_hash, bool,
106 private_openssl_hasher_t *this, chunk_t chunk, u_int8_t *hash)
107 {
108 if (EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len) != 1)
109 {
110 return FALSE;
111 }
112 if (hash)
113 {
114 if (EVP_DigestFinal_ex(this->ctx, hash, NULL) != 1)
115 {
116 return FALSE;
117 }
118 reset(this);
119 }
120 return TRUE;
121 }
122
123 METHOD(hasher_t, allocate_hash, bool,
124 private_openssl_hasher_t *this, chunk_t chunk, chunk_t *hash)
125 {
126 if (hash)
127 {
128 *hash = chunk_alloc(get_hash_size(this));
129 return get_hash(this, chunk, hash->ptr);
130 }
131 return get_hash(this, chunk, NULL);
132 }
133
134 METHOD(hasher_t, destroy, void,
135 private_openssl_hasher_t *this)
136 {
137 EVP_MD_CTX_destroy(this->ctx);
138 free(this);
139 }
140
141 /*
142 * Described in header
143 */
144 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
145 {
146 private_openssl_hasher_t *this;
147
148 char* name = lookup_algorithm(integrity_algs, algo);
149 if (!name)
150 {
151 /* algo unavailable */
152 return NULL;
153 }
154
155 INIT(this,
156 .public = {
157 .hasher = {
158 .get_hash = _get_hash,
159 .allocate_hash = _allocate_hash,
160 .get_hash_size = _get_hash_size,
161 .reset = _reset,
162 .destroy = _destroy,
163 },
164 },
165 );
166
167 this->hasher = EVP_get_digestbyname(name);
168 if (!this->hasher)
169 {
170 /* OpenSSL does not support the requested algo */
171 free(this);
172 return NULL;
173 }
174
175 this->ctx = EVP_MD_CTX_create();
176
177 /* initialization */
178 reset(this);
179
180 return &this->public;
181 }