Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit55d0532

Browse files
committed
SSL support for ephemeral DH keys.
As the comment headers in be-secure.c discusses, EPH preservesconfidentiality even if the static private key (which is usuallykept unencrypted) is compromised.Because of the value of this, common default values are hard-codedto protect the confidentiality of the data even if an attackersuccessfully deletes or modifies the external file.Bear Giles
1 parent1957042 commit55d0532

File tree

2 files changed

+476
-5
lines changed

2 files changed

+476
-5
lines changed

‎src/backend/libpq/be-secure.c

Lines changed: 257 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,34 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.1 2002/06/14 04:23:17 momjian Exp $
15-
*
14+
* $Header: /cvsroot/pgsql/src/backend/libpq/be-secure.c,v 1.2 2002/06/14 04:31:49 momjian Exp $
15+
*
16+
* Since the server static private key ($DataDir/server.key)
17+
* will normally be stored unencrypted so that the database
18+
* backend can restart automatically, it is important that
19+
* we select an algorithm that continues to provide confidentiality
20+
* even if the attacker has the server's private key. Empheral
21+
* DH (EDH) keys provide this, and in fact provide Perfect Forward
22+
* Secrecy (PFS) except for situations where the session can
23+
* be hijacked during a periodic handshake/renegotiation.
24+
* Even that backdoor can be closed if client certificates
25+
* are used (since the imposter will be unable to successfully
26+
* complete renegotiation).
27+
*
28+
* N.B., the static private key should still be protected to
29+
* the largest extent possible, to minimize the risk of
30+
* impersonations.
31+
*
32+
* Another benefit of EDH is that it allows the backend and
33+
* clients to use DSA keys. DSA keys can only provide digital
34+
* signatures, not encryption, and are often acceptable in
35+
* jurisdictions where RSA keys are unacceptable.
36+
*
37+
* The downside to EDH is that it makes it impossible to
38+
* use ssldump(1) if there's a problem establishing an SSL
39+
* session. In this case you'll need to temporarily disable
40+
* EDH by commenting out the callback.
41+
*
1642
* PATCH LEVEL
1743
* milestone 1: fix basic coding errors
1844
* [*] existing SSL code pulled out of existing files.
@@ -25,8 +51,9 @@
2551
*
2652
* milestone 3: improve confidentially, support perfect forward secrecy
2753
* [ ] use 'random' file, read from '/dev/urandom?'
28-
* [] emphermal DH keys, default values
54+
* [*] emphermal DH keys, default values
2955
* [ ] periodic renegotiation
56+
* [ ] private key permissions
3057
*
3158
* milestone 4: provide endpoint authentication (client)
3259
* [ ] server verifies client certificates
@@ -74,6 +101,7 @@
74101
#ifdefUSE_SSL
75102
#include<openssl/ssl.h>
76103
#include<openssl/e_os.h>
104+
#include<openssl/dh.h>
77105
#endif
78106

79107
externvoidExitPostmaster(int);
@@ -87,6 +115,9 @@ ssize_t secure_read(Port *, void *ptr, size_t len);
87115
ssize_tsecure_write(Port*,constvoid*ptr,size_tlen);
88116

89117
#ifdefUSE_SSL
118+
staticDH*load_dh_file(intkeylength);
119+
staticDH*load_dh_buffer(constchar*,size_t);
120+
staticDH*tmp_dh_cb(SSL*s,intis_export,intkeylength);
90121
staticintinitialize_SSL(void);
91122
staticvoiddestroy_SSL(void);
92123
staticintopen_server_SSL(Port*);
@@ -98,6 +129,70 @@ static const char *SSLerrmessage(void);
98129
staticSSL_CTX*SSL_context=NULL;
99130
#endif
100131

132+
/* ------------------------------------------------------------ */
133+
/* Hardcoded values */
134+
/* ------------------------------------------------------------ */
135+
136+
/*
137+
*Hardcoded DH parameters, used in empheral DH keying.
138+
*As discussed above, EDH protects the confidentiality of
139+
*sessions even if the static private key is compromised,
140+
*so we are *highly* motivated to ensure that we can use
141+
*EDH even if the DBA... or an attacker... deletes the
142+
*$DataDir/dh*.pem files.
143+
*
144+
*We could refuse SSL connections unless a good DH parameter
145+
*file exists, but some clients may quietly renegotiate an
146+
*unsecured connection without fully informing the user.
147+
*Very uncool.
148+
*
149+
*Alternately, the backend could attempt to load these files
150+
*on startup if SSL is enabled - and refuse to start if any
151+
*do not exist - but this would tend to piss off DBAs.
152+
*
153+
*If you want to create your own hardcoded DH parameters
154+
*for fun and profit, review "Assigned Number for SKIP
155+
*Protocols" (http://www.skip-vpn.org/spec/numbers.html)
156+
*for suggestions.
157+
*/
158+
staticconstcharfile_dh512[]=
159+
"-----BEGIN DH PARAMETERS-----\n\
160+
MEYCQQD1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWak\n\
161+
XUGfnHy9iUsiGSa6q6Jew1XpKgVfAgEC\n\
162+
-----END DH PARAMETERS-----\n";
163+
164+
staticconstcharfile_dh1024[]=
165+
"-----BEGIN DH PARAMETERS-----\n\
166+
MIGHAoGBAPSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsY\n\
167+
jY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6\n\
168+
ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpL3jHAgEC\n\
169+
-----END DH PARAMETERS-----\n";
170+
171+
staticconstcharfile_dh2048[]=
172+
"-----BEGIN DH PARAMETERS-----\n\
173+
MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\
174+
89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\
175+
T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\
176+
zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\
177+
Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\
178+
CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\
179+
-----END DH PARAMETERS-----\n";
180+
181+
staticconstcharfile_dh4096[]=
182+
"-----BEGIN DH PARAMETERS-----\n\
183+
MIICCAKCAgEA+hRyUsFN4VpJ1O8JLcCo/VWr19k3BCgJ4uk+d+KhehjdRqNDNyOQ\n\
184+
l/MOyQNQfWXPeGKmOmIig6Ev/nm6Nf9Z2B1h3R4hExf+zTiHnvVPeRBhjdQi81rt\n\
185+
Xeoh6TNrSBIKIHfUJWBh3va0TxxjQIs6IZOLeVNRLMqzeylWqMf49HsIXqbcokUS\n\
186+
Vt1BkvLdW48j8PPv5DsKRN3tloTxqDJGo9tKvj1Fuk74A+Xda1kNhB7KFlqMyN98\n\
187+
VETEJ6c7KpfOo30mnK30wqw3S8OtaIR/maYX72tGOno2ehFDkq3pnPtEbD2CScxc\n\
188+
alJC+EL7RPk5c/tgeTvCngvc1KZn92Y//EI7G9tPZtylj2b56sHtMftIoYJ9+ODM\n\
189+
sccD5Piz/rejE3Ome8EOOceUSCYAhXn8b3qvxVI1ddd1pED6FHRhFvLrZxFvBEM9\n\
190+
ERRMp5QqOaHJkM+Dxv8Cj6MqrCbfC4u+ZErxodzuusgDgvZiLF22uxMZbobFWyte\n\
191+
OvOzKGtwcTqO/1wV5gKkzu1ZVswVUQd5Gg8lJicwqRWyyNRczDDoG9jVDxmogKTH\n\
192+
AaqLulO7R8Ifa1SwF2DteSGVtgWEN8gDpN3RBmmPTDngyF2DHb5qmpnznwtFKdTL\n\
193+
KWbuHn491xNO25CQWMtem80uKw+pTnisBRF/454n1Jnhub144YRBoN8CAQI=\n\
194+
-----END DH PARAMETERS-----\n";
195+
101196
/* ------------------------------------------------------------ */
102197
/* Procedures common to all secure sessions */
103198
/* ------------------------------------------------------------ */
@@ -245,6 +340,161 @@ secure_write (Port *port, const void *ptr, size_t len)
245340
/* SSL specific code */
246341
/* ------------------------------------------------------------ */
247342
#ifdefUSE_SSL
343+
/*
344+
*Load precomputed DH parameters.
345+
*
346+
*To prevent "downgrade" attacks, we perform a number of checks
347+
*to verify that the DBA-generated DH parameters file contains
348+
*what we expect it to contain.
349+
*/
350+
staticDH*
351+
load_dh_file (intkeylength)
352+
{
353+
FILE*fp;
354+
charfnbuf[2048];
355+
DH*dh=NULL;
356+
intcodes;
357+
358+
/* attempt to open file. It's not an error if it doesn't exist. */
359+
snprintf(fnbuf,sizeoffnbuf,"%s/dh%d.pem",DataDir,keylength);
360+
if ((fp=fopen(fnbuf,"r"))==NULL)
361+
returnNULL;
362+
363+
/*flock(fileno(fp), LOCK_SH); */
364+
dh=PEM_read_DHparams(fp,NULL,NULL,NULL);
365+
/*flock(fileno(fp), LOCK_UN); */
366+
fclose(fp);
367+
368+
/* is the prime the correct size? */
369+
if (dh!=NULL&&8*DH_size(dh)<keylength)
370+
{
371+
elog(DEBUG,"DH errors (%s): %d bits expected, %d bits found",
372+
fnbuf,keylength,8*DH_size(dh));
373+
dh=NULL;
374+
}
375+
376+
/* make sure the DH parameters are usable */
377+
if (dh!=NULL)
378+
{
379+
if (DH_check(dh,&codes))
380+
{
381+
elog(DEBUG,"DH_check error (%s): %s",fnbuf,SSLerrmessage());
382+
returnNULL;
383+
}
384+
if (codes&DH_CHECK_P_NOT_PRIME)
385+
{
386+
elog(DEBUG,"DH error (%s): p is not prime",fnbuf);
387+
returnNULL;
388+
}
389+
if ((codes&DH_NOT_SUITABLE_GENERATOR)&&
390+
(codes&DH_CHECK_P_NOT_SAFE_PRIME))
391+
{
392+
elog(DEBUG,
393+
"DH error (%s): neither suitable generator or safe prime",
394+
fnbuf);
395+
returnNULL;
396+
}
397+
}
398+
399+
returndh;
400+
}
401+
402+
/*
403+
*Load hardcoded DH parameters.
404+
*
405+
*To prevent problems if the DH parameters files don't even
406+
*exist, we can load DH parameters hardcoded into this file.
407+
*/
408+
staticDH*
409+
load_dh_buffer (constchar*buffer,size_tlen)
410+
{
411+
BIO*bio;
412+
DH*dh=NULL;
413+
414+
bio=BIO_new_mem_buf((char*)buffer,len);
415+
if (bio==NULL)
416+
returnNULL;
417+
dh=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);
418+
if (dh==NULL)
419+
elog(DEBUG,"DH load buffer: %s",SSLerrmessage());
420+
BIO_free(bio);
421+
422+
returndh;
423+
}
424+
425+
/*
426+
*Generate an empheral DH key. Because this can take a long
427+
*time to compute, we can use precomputed parameters of the
428+
*common key sizes.
429+
*
430+
*Since few sites will bother to precompute these parameter
431+
*files, we also provide a fallback to the parameters provided
432+
*by the OpenSSL project.
433+
*
434+
*These values can be static (once loaded or computed) since
435+
*the OpenSSL library can efficiently generate random keys from
436+
*the information provided.
437+
*/
438+
staticDH*
439+
tmp_dh_cb (SSL*s,intis_export,intkeylength)
440+
{
441+
DH*r=NULL;
442+
staticDH*dh=NULL;
443+
staticDH*dh512=NULL;
444+
staticDH*dh1024=NULL;
445+
staticDH*dh2048=NULL;
446+
staticDH*dh4096=NULL;
447+
448+
switch (keylength)
449+
{
450+
case512:
451+
if (dh512==NULL)
452+
dh512=load_dh_file(keylength);
453+
if (dh512==NULL)
454+
dh512=load_dh_buffer(file_dh512,sizeoffile_dh512);
455+
r=dh512;
456+
break;
457+
458+
case1024:
459+
if (dh1024==NULL)
460+
dh1024=load_dh_file(keylength);
461+
if (dh1024==NULL)
462+
dh1024=load_dh_buffer(file_dh1024,sizeoffile_dh1024);
463+
r=dh1024;
464+
break;
465+
466+
case2048:
467+
if (dh2048==NULL)
468+
dh2048=load_dh_file(keylength);
469+
if (dh2048==NULL)
470+
dh2048=load_dh_buffer(file_dh2048,sizeoffile_dh2048);
471+
r=dh2048;
472+
break;
473+
474+
case4096:
475+
if (dh4096==NULL)
476+
dh4096=load_dh_file(keylength);
477+
if (dh4096==NULL)
478+
dh4096=load_dh_buffer(file_dh4096,sizeoffile_dh4096);
479+
r=dh4096;
480+
break;
481+
482+
default:
483+
if (dh==NULL)
484+
dh=load_dh_file(keylength);
485+
r=dh;
486+
}
487+
488+
/* this may take a long time, but it may be necessary... */
489+
if (r==NULL||8*DH_size(r)<keylength)
490+
{
491+
elog(DEBUG,"DH: generating parameters (%d bits)....",keylength);
492+
r=DH_generate_parameters(keylength,DH_GENERATOR_2,NULL,NULL);
493+
}
494+
495+
returnr;
496+
}
497+
248498
/*
249499
*Initialize global SSL context.
250500
*/
@@ -290,6 +540,10 @@ initialize_SSL (void)
290540
}
291541
}
292542

543+
/* set up empheral DH keys */
544+
SSL_CTX_set_tmp_dh_callback(SSL_context,tmp_dh_cb);
545+
SSL_CTX_set_options(SSL_context,SSL_OP_SINGLE_DH_USE);
546+
293547
return0;
294548
}
295549

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp