openssl: Add helper to determine EVP_MD from hash_algorithm_t
[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 char *name;
97
98 name = enum_to_name(hash_algorithm_short_names, hash);
99 if (!name)
100 {
101 return NULL;
102 }
103 return EVP_get_digestbyname(name);
104 }
105
106 /*
107 * Described in header
108 */
109 openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo)
110 {
111 private_openssl_hasher_t *this;
112
113 INIT(this,
114 .public = {
115 .hasher = {
116 .get_hash = _get_hash,
117 .allocate_hash = _allocate_hash,
118 .get_hash_size = _get_hash_size,
119 .reset = _reset,
120 .destroy = _destroy,
121 },
122 },
123 );
124
125 this->hasher = openssl_get_md(algo);
126 if (!this->hasher)
127 {
128 /* OpenSSL does not support the requested algo */
129 free(this);
130 return NULL;
131 }
132
133 this->ctx = EVP_MD_CTX_create();
134
135 /* initialization */
136 if (!reset(this))
137 {
138 destroy(this);
139 return NULL;
140 }
141
142 return &this->public;
143 }