d81f4b21efd4d40d70ac1f4f511871b5af6f7e4a
[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, void,
106 private_openssl_hasher_t *this, chunk_t chunk, u_int8_t *hash)
107 {
108 EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len);
109 if (hash)
110 {
111 EVP_DigestFinal_ex(this->ctx, hash, NULL);
112 reset(this);
113 }
114 }
115
116 METHOD(hasher_t, allocate_hash, void,
117 private_openssl_hasher_t *this, chunk_t chunk, chunk_t *hash)
118 {
119 if (hash)
120 {
121 *hash = chunk_alloc(get_hash_size(this));
122 get_hash(this, chunk, hash->ptr);
123 }
124 else
125 {
126 get_hash(this, chunk, NULL);
127 }
128 }
129
130 METHOD(hasher_t, destroy, void,
131 private_openssl_hasher_t *this)
132 {
133 EVP_MD_CTX_destroy(this->ctx);
134 free(this);
135 }
136
137 /*
138 * Described in header
139 */
140 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
141 {
142 private_openssl_hasher_t *this;
143
144 char* name = lookup_algorithm(integrity_algs, algo);
145 if (!name)
146 {
147 /* algo unavailable */
148 return NULL;
149 }
150
151 INIT(this,
152 .public = {
153 .hasher = {
154 .get_hash = _get_hash,
155 .allocate_hash = _allocate_hash,
156 .get_hash_size = _get_hash_size,
157 .reset = _reset,
158 .destroy = _destroy,
159 },
160 },
161 );
162
163 this->hasher = EVP_get_digestbyname(name);
164 if (!this->hasher)
165 {
166 /* OpenSSL does not support the requested algo */
167 free(this);
168 return NULL;
169 }
170
171 this->ctx = EVP_MD_CTX_create();
172
173 /* initialization */
174 reset(this);
175
176 return &this->public;
177 }