~ubuntu-branches/ubuntu/maverick/postfix/maverick-security

« back to all changes in this revision

Viewing changes to src/tls/tls_dh.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones, Wietse Venema, LaMont Jones
  • Date: 2009-06-03 14:17:08 UTC
  • mfrom: (1.1.22 upstream)
  • Revision ID: james.westby@ubuntu.com-20090603141708-o9u59xlor7nmd2x1
[Wietse Venema]

* New upstream release: 2.6.2~rc1

[LaMont Jones]

* move postfix-add-{filter,policy} manpages to section 8, and deliver
* provide: default-mta on ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
/*      #define TLS_INTERNAL
8
8
/*      #include <tls.h>
9
9
/*
10
 
/*      void    tls_set_dh_1024_from_file(path)
 
10
/*      void    tls_set_dh_from_file(path, bits)
11
11
/*      const char *path;
 
12
/*      int     bits;
12
13
/*
13
 
/*      void    tls_set_dh_512_from_file(path)
14
 
/*      const char *path;
 
14
/*      int     tls_set_eecdh_curve(server_ctx, grade)
 
15
/*      SSL_CTX *server_ctx;
 
16
/*      const char *grade;
15
17
/*
16
18
/*      DH      *tls_tmp_dh_cb(ssl, export, keylength)
17
19
/*      SSL     *ssl; /* unused */
23
25
/*      tls_tmp_dh_cb() is a call-back routine for the
24
26
/*      SSL_CTX_set_tmp_dh_callback() function.
25
27
/*
26
 
/*      tls_set_dh_1024_from_file() and tls_set_dh_512_from_file()
27
 
/*      override the compiled-in DH parameters with those specified
28
 
/*      in the named files. The file format is as expected by the
29
 
/*      PEM_read_DHparams() routine.
 
28
/*      tls_set_dh_from_file() overrides compiled-in DH parameters
 
29
/*      with those specified in the named files. The file format
 
30
/*      is as expected by the PEM_read_DHparams() routine. The
 
31
/*      "bits" argument must be 512 or 1024.
 
32
/*
 
33
/*      tls_set_eecdh_curve() enables ephemeral Elliptic-Curve DH
 
34
/*      key exchange algorithms by instantiating in the server SSL
 
35
/*      context a suitable curve (corresponding to the specified
 
36
/*      EECDH security grade) from the set of named curves in RFC
 
37
/*      4492 Section 5.1.1. Errors generate warnings, but do not
 
38
/*      disable TLS, rather we continue without EECDH. A zero
 
39
/*      result indicates that the grade is invalid or the corresponding
 
40
/*      curve could not be used.
30
41
/* DIAGNOSTICS
31
 
/*      In case of error, tls_set_dh_1024_from_file() and
32
 
/*      tls_set_dh_512_from_file() log a warning and ignore the request.
 
42
/*      In case of error, tls_set_dh_from_file() logs a warning and
 
43
/*      ignores the request.
33
44
/* LICENSE
34
45
/* .ad
35
46
/* .fi
62
73
 
63
74
#include <msg.h>
64
75
 
 
76
 /*
 
77
  * Global library
 
78
  */
 
79
#include <mail_params.h>
 
80
 
65
81
/* TLS library. */
66
82
 
67
83
#define TLS_INTERNAL
70
86
/* Application-specific. */
71
87
 
72
88
 /*
73
 
  * Compiled-in DH parameters. These are used when no parameters are
74
 
  * explicitly loaded from file.
 
89
  * Compiled-in EDH primes (the compiled-in generator is always 2). These are
 
90
  * used when no parameters are explicitly loaded from a site-specific file.
75
91
  * 
76
 
  * XXX What is the origin of these parameters?
 
92
  * 512-bit parameters are used for export ciphers, and 1024-bit parameters are
 
93
  * used for non-export ciphers. An ~80-bit strong EDH key exchange is really
 
94
  * too weak to protect 128+ bit keys, but larger DH primes are
 
95
  * computationally expensive. When greater security is required, use EECDH.
 
96
  */
 
97
 
 
98
 /*
 
99
  * Generated via "openssl dhparam -2 -noout -C 512 2>/dev/null" TODO:
 
100
  * generate at compile-time.
77
101
  */
78
102
static unsigned char dh512_p[] = {
79
103
    0x88, 0x3F, 0x00, 0xAF, 0xFC, 0x0C, 0x8A, 0xB8, 0x35, 0xCD, 0xE5, 0xC2,
83
107
    0x6E, 0x01, 0x45, 0xDE, 0xC9, 0xB1, 0x1F, 0x64, 0x54, 0xFA, 0xD9, 0xAB,
84
108
    0x4F, 0x70, 0xBA, 0x5B,
85
109
};
86
 
static unsigned char dh512_g[] = {
87
 
    0x02,
88
 
};
89
110
 
 
111
 /*
 
112
  * Generated via "openssl dhparam -2 -noout -C 1024 2>/dev/null" TODO:
 
113
  * generate at compile-time.
 
114
  */
90
115
static unsigned char dh1024_p[] = {
91
116
    0xB0, 0xFE, 0xB4, 0xCF, 0xD4, 0x55, 0x07, 0xE7, 0xCC, 0x88, 0x59, 0x0D,
92
117
    0x17, 0x26, 0xC5, 0x0C, 0xA5, 0x4A, 0x92, 0x23, 0x81, 0x78, 0xDA, 0x88,
101
126
    0x6D, 0xAF, 0xD4, 0x93, 0xE7, 0xBA, 0xAE, 0x9B,
102
127
};
103
128
 
104
 
static unsigned char dh1024_g[] = {
105
 
    0x02,
106
 
};
107
 
 
108
129
 /*
109
130
  * Cached results.
110
131
  */
111
132
static DH *dh_1024 = 0;
112
133
static DH *dh_512 = 0;
113
134
 
114
 
/* tls_set_dh_1024_from_file - set Diffie-Hellman parameters from file */
115
 
 
116
 
void    tls_set_dh_1024_from_file(const char *path)
117
 
{
118
 
    FILE   *paramfile;
119
 
 
120
 
    if ((paramfile = fopen(path, "r")) != 0) {
121
 
        dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
122
 
        if (dh_1024 == 0) {
123
 
            msg_warn("cannot load 1024-bit DH parameters from file %s"
124
 
                     " -- using compiled-in defaults", path);
125
 
            tls_print_errors();
126
 
        }
127
 
        (void) fclose(paramfile);               /* 200411 */
128
 
    } else {
129
 
        msg_warn("cannot load 1024-bit DH parameters from file %s: %m"
130
 
                 " -- using compiled-in defaults", path);
131
 
    }
132
 
}
133
 
 
134
 
/* tls_set_dh_512_from_file - set Diffie-Hellman parameters from file */
135
 
 
136
 
void    tls_set_dh_512_from_file(const char *path)
137
 
{
138
 
    FILE   *paramfile;
139
 
 
140
 
    if ((paramfile = fopen(path, "r")) != 0) {
141
 
        dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
142
 
        if (dh_512 == 0) {
143
 
            msg_warn("cannot load 512-bit DH parameters from file %s"
144
 
                     " -- using compiled-in defaults", path);
145
 
            tls_print_errors();
146
 
        }
147
 
        (void) fclose(paramfile);               /* 200411 */
148
 
    } else {
149
 
        msg_warn("cannot load 512-bit DH parameters from file %s: %m"
150
 
                 " -- using compiled-in defaults", path);
151
 
    }
152
 
}
153
 
 
154
 
/* tls_get_dh_512 - get 512-bit DH parameters, compiled-in or from file */
155
 
 
156
 
static DH *tls_get_dh_512(void)
157
 
{
158
 
    DH     *dh;
159
 
 
160
 
    if (dh_512 == 0) {
161
 
        /* Use the compiled-in parameters. */
162
 
        if ((dh = DH_new()) == 0) {
163
 
            msg_warn("cannot create DH parameter set: %m");     /* 200411 */
164
 
            return (0);
165
 
        }
166
 
        dh->p = BN_bin2bn(dh512_p, sizeof(dh512_p), (BIGNUM *) 0);
167
 
        dh->g = BN_bin2bn(dh512_g, sizeof(dh512_g), (BIGNUM *) 0);
168
 
        if ((dh->p == 0) || (dh->g == 0)) {
169
 
            msg_warn("cannot load compiled-in DH parameters");  /* 200411 */
170
 
            DH_free(dh);                        /* 200411 */
171
 
            return (0);
172
 
        } else
173
 
            dh_512 = dh;
174
 
    }
175
 
    return (dh_512);
176
 
}
177
 
 
178
 
/* tls_get_dh_1024 - get 1024-bit DH parameters, compiled-in or from file */
179
 
 
180
 
static DH *tls_get_dh_1024(void)
181
 
{
182
 
    DH     *dh;
183
 
 
184
 
    if (dh_1024 == 0) {
185
 
        /* Use the compiled-in parameters. */
186
 
        if ((dh = DH_new()) == 0) {
187
 
            msg_warn("cannot create DH parameter set: %m");     /* 200411 */
188
 
            return (0);
189
 
        }
190
 
        dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), (BIGNUM *) 0);
191
 
        dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), (BIGNUM *) 0);
192
 
        if ((dh->p == 0) || (dh->g == 0)) {
193
 
            msg_warn("cannot load compiled-in DH parameters");  /* 200411 */
194
 
            DH_free(dh);                        /* 200411 */
195
 
            return (0);
196
 
        } else
197
 
            dh_1024 = dh;
198
 
    }
199
 
    return (dh_1024);
 
135
/* tls_set_dh_from_file - set Diffie-Hellman parameters from file */
 
136
 
 
137
void    tls_set_dh_from_file(const char *path, int bits)
 
138
{
 
139
    FILE   *paramfile;
 
140
    DH    **dhPtr;
 
141
 
 
142
    switch (bits) {
 
143
    case 512:
 
144
        dhPtr = &dh_512;
 
145
        break;
 
146
    case 1024:
 
147
        dhPtr = &dh_1024;
 
148
        break;
 
149
    default:
 
150
        msg_panic("Invalid DH parameters size %d, file %s", bits, path);
 
151
    }
 
152
 
 
153
    if ((paramfile = fopen(path, "r")) != 0) {
 
154
        if ((*dhPtr = PEM_read_DHparams(paramfile, 0, 0, 0)) == 0) {
 
155
            msg_warn("cannot load %d-bit DH parameters from file %s"
 
156
                     " -- using compiled-in defaults", bits, path);
 
157
            tls_print_errors();
 
158
        }
 
159
        (void) fclose(paramfile);               /* 200411 */
 
160
    } else {
 
161
        msg_warn("cannot load %d-bit DH parameters from file %s: %m"
 
162
                 " -- using compiled-in defaults", bits, path);
 
163
    }
 
164
}
 
165
 
 
166
/* tls_get_dh - get compiled-in DH parameters */
 
167
 
 
168
static DH *tls_get_dh(const unsigned char *p, int plen)
 
169
{
 
170
    DH     *dh;
 
171
    static unsigned char g[] = {0x02,};
 
172
 
 
173
    /* Use the compiled-in parameters. */
 
174
    if ((dh = DH_new()) == 0) {
 
175
        msg_warn("cannot create DH parameter set: %m"); /* 200411 */
 
176
        return (0);
 
177
    }
 
178
    dh->p = BN_bin2bn(p, plen, (BIGNUM *) 0);
 
179
    dh->g = BN_bin2bn(g, 1, (BIGNUM *) 0);
 
180
    if ((dh->p == 0) || (dh->g == 0)) {
 
181
        msg_warn("cannot load compiled-in DH parameters");      /* 200411 */
 
182
        DH_free(dh);                            /* 200411 */
 
183
        return (0);
 
184
    }
 
185
    return (dh);
200
186
}
201
187
 
202
188
/* tls_tmp_dh_cb - call-back for Diffie-Hellman parameters */
205
191
{
206
192
    DH     *dh_tmp;
207
193
 
208
 
    if (export) {
209
 
        if (keylength == 512)
210
 
            dh_tmp = tls_get_dh_512();          /* export cipher */
211
 
        else if (keylength == 1024)
212
 
            dh_tmp = tls_get_dh_1024();         /* normal */
213
 
        else
214
 
            dh_tmp = tls_get_dh_1024();         /* cheat */
215
 
    } else {
216
 
        dh_tmp = tls_get_dh_1024();             /* sign-only certificate */
 
194
    if (export && keylength == 512) {           /* 40-bit export cipher */
 
195
        if (dh_512 == 0)
 
196
            dh_512 = tls_get_dh(dh512_p, (int) sizeof(dh512_p));
 
197
        dh_tmp = dh_512;
 
198
    } else {                                    /* ADH, DHE-RSA or DSA */
 
199
        if (dh_1024 == 0)
 
200
            dh_1024 = tls_get_dh(dh1024_p, (int) sizeof(dh1024_p));
 
201
        dh_tmp = dh_1024;
217
202
    }
218
203
    return (dh_tmp);
219
204
}
220
205
 
 
206
int     tls_set_eecdh_curve(SSL_CTX *server_ctx, const char *grade)
 
207
{
 
208
#if OPENSSL_VERSION_NUMBER >= 0x00909000 && !defined(OPENSSL_NO_ECDH)
 
209
    int     nid;
 
210
    EC_KEY *ecdh;
 
211
    const char *curve;
 
212
    int     g;
 
213
 
 
214
#define TLS_EECDH_INVALID       0
 
215
#define TLS_EECDH_NONE          1
 
216
#define TLS_EECDH_STRONG        2
 
217
#define TLS_EECDH_ULTRA         3
 
218
    static NAME_CODE eecdh_table[] = {
 
219
        "none", TLS_EECDH_NONE,
 
220
        "strong", TLS_EECDH_STRONG,
 
221
        "ultra", TLS_EECDH_ULTRA,
 
222
        0, TLS_EECDH_INVALID,
 
223
    };
 
224
 
 
225
    switch (g = name_code(eecdh_table, NAME_CODE_FLAG_NONE, grade)) {
 
226
    default:
 
227
        msg_panic("Invalid eecdh grade code: %d", g);
 
228
    case TLS_EECDH_INVALID:
 
229
        msg_warn("Invalid TLS eecdh grade \"%s\": EECDH disabled", grade);
 
230
        return (0);
 
231
    case TLS_EECDH_NONE:
 
232
        return (1);
 
233
    case TLS_EECDH_STRONG:
 
234
        curve = var_tls_eecdh_strong;
 
235
        break;
 
236
    case TLS_EECDH_ULTRA:
 
237
        curve = var_tls_eecdh_ultra;
 
238
        break;
 
239
    }
 
240
 
 
241
    /*
 
242
     * Elliptic-Curve Diffie-Hellman parameters are either "named curves"
 
243
     * from RFC 4492 section 5.1.1, or explicitly described curves over
 
244
     * binary fields. OpenSSL only supports the "named curves", which provide
 
245
     * maximum interoperability. The recommended curve for 128-bit
 
246
     * work-factor key exchange is "prime256v1" a.k.a. "secp256r1" from
 
247
     * Section 2.7 of http://www.secg.org/download/aid-386/sec2_final.pdf
 
248
     */
 
249
 
 
250
    if ((nid = OBJ_sn2nid(curve)) == NID_undef) {
 
251
        msg_warn("unknown curve \"%s\": disabling EECDH support", curve);
 
252
        return (0);
 
253
    }
 
254
    ERR_clear_error();
 
255
    if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0
 
256
        || SSL_CTX_set_tmp_ecdh(server_ctx, ecdh) == 0) {
 
257
        msg_warn("unable to use curve \"%s\": disabling EECDH support", curve);
 
258
        tls_print_errors();
 
259
        return (0);
 
260
    }
 
261
#endif
 
262
    return (1);
 
263
}
 
264
 
221
265
#ifdef TEST
222
266
 
223
 
int main(int unused_argc, char **unused_argv)
 
267
int     main(int unused_argc, char **unused_argv)
224
268
{
225
269
    tls_tmp_dh_cb(0, 1, 512);
226
270
    tls_tmp_dh_cb(0, 1, 1024);