2626 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2727 * SUCH DAMAGE.
2828 *
29- * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.26 2005/10/15 02:49:06 momjian Exp $
29+ * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.27 2006/02/18 20:48:51 neilc Exp $
3030 */
3131
3232#include "postgres.h"
4747#define MAX_IV (128/8)
4848
4949/*
50- * Does OpenSSL support AES?
50+ * Compatibility with OpenSSL 0.9.6
51+ *
52+ * It needs AES and newer DES and digest API.
5153 */
5254#if OPENSSL_VERSION_NUMBER >=0x00907000L
5355
54- /* Yes, it does. */
56+ /*
57+ * Nothing needed for OpenSSL 0.9.7+
58+ */
59+
5560#include <openssl/aes.h>
61+
5662#else /* old OPENSSL */
5763
5864/*
59- *No, it does not. So use included rijndael code to emulate it .
65+ *Emulate OpenSSL AES .
6066 */
67+
6168#include "rijndael.c"
6269
6370#define AES_ENCRYPT 1
9097memcpy(iv, (src) + (len) - 16, 16); \
9198} \
9299} while (0)
93- #endif /* old OPENSSL */
94100
95101/*
96- *Compatibility with older OpenSSL API for DES.
102+ *Emulate DES_* API
97103 */
98- #if OPENSSL_VERSION_NUMBER < 0x00907000L
104+
99105#define DES_key_schedule des_key_schedule
100106#define DES_cblock des_cblock
101107#define DES_set_key (k ,ks ) \
110116#define DES_ede3_cbc_encrypt (i ,o ,l ,k1 ,k2 ,k3 ,iv ,e ) \
111117des_ede3_cbc_encrypt((i), (o), \
112118(l), *(k1), *(k2), *(k3), (iv), (e))
113- #endif
119+
120+ /*
121+ * Emulate newer digest API.
122+ */
123+
124+ static void EVP_MD_CTX_init (EVP_MD_CTX * ctx )
125+ {
126+ memset (ctx ,0 ,sizeof (* ctx ));
127+ }
128+
129+ static int EVP_MD_CTX_cleanup (EVP_MD_CTX * ctx )
130+ {
131+ memset (ctx ,0 ,sizeof (* ctx ));
132+ return 1 ;
133+ }
134+
135+ static int EVP_DigestInit_ex (EVP_MD_CTX * ctx ,const EVP_MD * md ,void * engine )
136+ {
137+ EVP_DigestInit (ctx ,md );
138+ return 1 ;
139+ }
140+
141+ static int EVP_DigestFinal_ex (EVP_MD_CTX * ctx ,unsignedchar * res ,unsignedint * len )
142+ {
143+ EVP_DigestFinal (ctx ,res ,len );
144+ return 1 ;
145+ }
146+
147+ #endif /* old OpenSSL */
114148
115149/*
116150 * Hashes
117151 */
152+
153+ typedef struct OSSLDigest {
154+ const EVP_MD * algo ;
155+ EVP_MD_CTX ctx ;
156+ }OSSLDigest ;
157+
118158static unsigned
119159digest_result_size (PX_MD * h )
120160{
121- return EVP_MD_CTX_size ((EVP_MD_CTX * )h -> p .ptr );
161+ OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
162+ return EVP_MD_CTX_size (& digest -> ctx );
122163}
123164
124165static unsigned
125166digest_block_size (PX_MD * h )
126167{
127- return EVP_MD_CTX_block_size ((EVP_MD_CTX * )h -> p .ptr );
168+ OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
169+ return EVP_MD_CTX_block_size (& digest -> ctx );
128170}
129171
130172static void
131173digest_reset (PX_MD * h )
132174{
133- EVP_MD_CTX * ctx = (EVP_MD_CTX * )h -> p .ptr ;
134- const EVP_MD * md ;
175+ OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
135176
136- md = EVP_MD_CTX_md (ctx );
137-
138- EVP_DigestInit (ctx ,md );
177+ EVP_DigestInit_ex (& digest -> ctx ,digest -> algo ,NULL );
139178}
140179
141180static void
142181digest_update (PX_MD * h ,const uint8 * data ,unsigned dlen )
143182{
144- EVP_MD_CTX * ctx = (EVP_MD_CTX * )h -> p .ptr ;
183+ OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
145184
146- EVP_DigestUpdate (ctx ,data ,dlen );
185+ EVP_DigestUpdate (& digest -> ctx ,data ,dlen );
147186}
148187
149188static void
150189digest_finish (PX_MD * h ,uint8 * dst )
151190{
152- EVP_MD_CTX * ctx = (EVP_MD_CTX * )h -> p .ptr ;
153- const EVP_MD * md = EVP_MD_CTX_md (ctx );
154-
155- EVP_DigestFinal (ctx ,dst ,NULL );
191+ OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
156192
157- /*
158- * Some builds of 0.9.7x clear all of ctx in EVP_DigestFinal. Fix it by
159- * reinitializing ctx.
160- */
161- EVP_DigestInit (ctx ,md );
193+ EVP_DigestFinal_ex (& digest -> ctx ,dst ,NULL );
162194}
163195
164196static void
165197digest_free (PX_MD * h )
166198{
167- EVP_MD_CTX * ctx = (EVP_MD_CTX * )h -> p .ptr ;
199+ OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
200+
201+ EVP_MD_CTX_cleanup (& digest -> ctx );
168202
169- px_free (ctx );
203+ px_free (digest );
170204px_free (h );
171205}
172206
178212px_find_digest (const char * name ,PX_MD * * res )
179213{
180214const EVP_MD * md ;
181- EVP_MD_CTX * ctx ;
182215PX_MD * h ;
216+ OSSLDigest * digest ;
183217
184218if (!px_openssl_initialized )
185219{
@@ -191,8 +225,12 @@ px_find_digest(const char *name, PX_MD ** res)
191225if (md == NULL )
192226return PXE_NO_HASH ;
193227
194- ctx = px_alloc (sizeof (* ctx ));
195- EVP_DigestInit (ctx ,md );
228+ digest = px_alloc (sizeof (* digest ));
229+ digest -> algo = md ;
230+
231+ EVP_MD_CTX_init (& digest -> ctx );
232+ if (EVP_DigestInit_ex (& digest -> ctx ,digest -> algo ,NULL )== 0 )
233+ return -1 ;
196234
197235h = px_alloc (sizeof (* h ));
198236h -> result_size = digest_result_size ;
@@ -201,7 +239,7 @@ px_find_digest(const char *name, PX_MD ** res)
201239h -> update = digest_update ;
202240h -> finish = digest_finish ;
203241h -> free = digest_free ;
204- h -> p .ptr = (void * )ctx ;
242+ h -> p .ptr = (void * )digest ;
205243
206244* res = h ;
207245return 0 ;