]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/openssl/openssl_hasher.c
openssl: Add support for SHA-3
[thirdparty/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_hasher.c
1 /*
2 * Copyright (C) 2008-2017 Tobias Brunner
3 * HSR 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 METHOD(hasher_t, get_hash_size, size_t,
44 private_openssl_hasher_t *this)
45 {
46 return EVP_MD_size(this->hasher);
47 }
48
49 METHOD(hasher_t, reset, bool,
50 private_openssl_hasher_t *this)
51 {
52 return EVP_DigestInit_ex(this->ctx, this->hasher, NULL) == 1;
53 }
54
55 METHOD(hasher_t, get_hash, bool,
56 private_openssl_hasher_t *this, chunk_t chunk, uint8_t *hash)
57 {
58 if (EVP_DigestUpdate(this->ctx, chunk.ptr, chunk.len) != 1)
59 {
60 return FALSE;
61 }
62 if (hash)
63 {
64 if (EVP_DigestFinal_ex(this->ctx, hash, NULL) != 1)
65 {
66 return FALSE;
67 }
68 return reset(this);
69 }
70 return TRUE;
71 }
72
73 METHOD(hasher_t, allocate_hash, bool,
74 private_openssl_hasher_t *this, chunk_t chunk, chunk_t *hash)
75 {
76 if (hash)
77 {
78 *hash = chunk_alloc(get_hash_size(this));
79 return get_hash(this, chunk, hash->ptr);
80 }
81 return get_hash(this, chunk, NULL);
82 }
83
84 METHOD(hasher_t, destroy, void,
85 private_openssl_hasher_t *this)
86 {
87 EVP_MD_CTX_destroy(this->ctx);
88 free(this);
89 }
90
91 /*
92 * Described in header
93 */
94 const EVP_MD *openssl_get_md(hash_algorithm_t hash)
95 {
96 const EVP_MD *md;
97 char *name;
98
99 name = strdupnull(enum_to_name(hash_algorithm_short_names, hash));
100 if (!name)
101 {
102 return NULL;
103 }
104 /* for SHA3, we use underscores, while OpenSSL uses dashes */
105 translate(name, "_", "-");
106 md = EVP_get_digestbyname(name);
107 free(name);
108 return md;
109 }
110
111 /*
112 * Described in header
113 */
114 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
115 {
116 private_openssl_hasher_t *this;
117
118 INIT(this,
119 .public = {
120 .hasher = {
121 .get_hash = _get_hash,
122 .allocate_hash = _allocate_hash,
123 .get_hash_size = _get_hash_size,
124 .reset = _reset,
125 .destroy = _destroy,
126 },
127 },
128 );
129
130 this->hasher = openssl_get_md(algo);
131 if (!this->hasher)
132 {
133 /* OpenSSL does not support the requested algo */
134 free(this);
135 return NULL;
136 }
137
138 this->ctx = EVP_MD_CTX_create();
139
140 /* initialization */
141 if (!reset(this))
142 {
143 destroy(this);
144 return NULL;
145 }
146
147 return &this->public;
148 }