Skip to content
/ src Public

Commit c4df3bf

Browse files
committed
Implement RSA privilege separation for OpenSMTPD, based on my previous
implementation for relayd(8). The smtpd(8) pony processes (mta client, smtp server) don't keep the private keys in memory but send their private key operations as imsgs to the "lookup"/mta process. It's worth mentioning that this prevents acidental private key leakage as it could have been caused by "Heartbleed". ok gilles@
1 parent 1249177 commit c4df3bf

File tree

14 files changed

+538
-98
lines changed

14 files changed

+538
-98
lines changed

usr.sbin/smtpd/ca.c

Lines changed: 326 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
/* $OpenBSD: ca.c,v 1.3 2013/11/21 08:36:51 eric Exp $ */
1+
/* $OpenBSD: ca.c,v 1.4 2014/04/29 19:13:13 reyk Exp $ */
22

33
/*
4+
* Copyright (c) 2014 Reyk Floeter <reyk@openbsd.org>
45
* Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
56
*
67
* Permission to use, copy, modify, and distribute this software for any
@@ -17,16 +18,75 @@
1718
*/
1819

1920
#include <sys/types.h>
21+
#include <sys/queue.h>
22+
#include <sys/socket.h>
2023

21-
#include <openssl/err.h>
22-
#include <openssl/ssl.h>
24+
#include <string.h>
25+
#include <stdlib.h>
26+
#include <imsg.h>
2327

28+
#include <openssl/pem.h>
29+
#include <openssl/evp.h>
30+
#include <openssl/rsa.h>
31+
#include <openssl/engine.h>
32+
33+
#include "smtpd.h"
2434
#include "log.h"
35+
#include "ssl.h"
36+
37+
static int ca_verify_cb(int, X509_STORE_CTX *);
38+
39+
static int rsae_send_imsg(int, const u_char *, u_char *, RSA *,
40+
int, u_int);
41+
static int rsae_pub_enc(int, const u_char *, u_char *, RSA *, int);
42+
static int rsae_pub_dec(int,const u_char *, u_char *, RSA *, int);
43+
static int rsae_priv_enc(int, const u_char *, u_char *, RSA *, int);
44+
static int rsae_priv_dec(int, const u_char *, u_char *, RSA *, int);
45+
static int rsae_mod_exp(BIGNUM *, const BIGNUM *, RSA *, BN_CTX *);
46+
static int rsae_bn_mod_exp(BIGNUM *, const BIGNUM *, const BIGNUM *,
47+
const BIGNUM *, BN_CTX *, BN_MONT_CTX *);
48+
static int rsae_init(RSA *);
49+
static int rsae_finish(RSA *);
50+
static int rsae_sign(int, const u_char *, u_int, u_char *, u_int *,
51+
const RSA *);
52+
static int rsae_verify(int dtype, const u_char *m, u_int, const u_char *,
53+
u_int, const RSA *);
54+
static int rsae_keygen(RSA *, int, BIGNUM *, BN_GENCB *);
55+
56+
void
57+
ca_init(void)
58+
{
59+
BIO *in = NULL;
60+
EVP_PKEY *pkey = NULL;
61+
struct pki *pki;
62+
const char *k;
63+
void *iter_dict;
64+
65+
log_debug("debug: init private ssl-tree");
66+
iter_dict = NULL;
67+
while (dict_iter(env->sc_pki_dict, &iter_dict, &k, (void **)&pki)) {
68+
if (pki->pki_key == NULL)
69+
continue;
70+
71+
if ((in = BIO_new_mem_buf(pki->pki_key,
72+
pki->pki_key_len)) == NULL)
73+
fatalx("ca_launch: key");
2574

26-
int ca_X509_verify(X509 *, STACK_OF(X509) *, const char *, const char *, const char **);
75+
if ((pkey = PEM_read_bio_PrivateKey(in,
76+
NULL, NULL, NULL)) == NULL)
77+
fatalx("ca_launch: PEM");
78+
BIO_free(in);
79+
80+
pki->pki_pkey = pkey;
81+
82+
explicit_bzero(pki->pki_key, pki->pki_key_len);
83+
free(pki->pki_key);
84+
pki->pki_key = NULL;
85+
}
86+
}
2787

2888
static int
29-
verify_cb(int ok, X509_STORE_CTX *ctx)
89+
ca_verify_cb(int ok, X509_STORE_CTX *ctx)
3090
{
3191
switch (X509_STORE_CTX_get_error(ctx)) {
3292
case X509_V_OK:
@@ -50,7 +110,7 @@ verify_cb(int ok, X509_STORE_CTX *ctx)
50110
}
51111

52112
int
53-
ca_X509_verify(X509 *certificate, STACK_OF(X509) *chain, const char *CAfile,
113+
ca_X509_verify(void *certificate, void *chain, const char *CAfile,
54114
const char *CRLfile, const char **errstr)
55115
{
56116
X509_STORE *store = NULL;
@@ -72,7 +132,7 @@ ca_X509_verify(X509 *certificate, STACK_OF(X509) *chain, const char *CAfile,
72132
if (X509_STORE_CTX_init(xsc, store, certificate, chain) != 1)
73133
goto end;
74134

75-
X509_STORE_CTX_set_verify_cb(xsc, verify_cb);
135+
X509_STORE_CTX_set_verify_cb(xsc, ca_verify_cb);
76136

77137
ret = X509_verify_cert(xsc);
78138

@@ -92,3 +152,262 @@ ca_X509_verify(X509 *certificate, STACK_OF(X509) *chain, const char *CAfile,
92152

93153
return ret > 0 ? 1 : 0;
94154
}
155+
156+
void
157+
ca_imsg(struct mproc *p, struct imsg *imsg)
158+
{
159+
RSA *rsa;
160+
const void *from = NULL;
161+
u_char *to = NULL;
162+
struct msg m;
163+
const char *pkiname;
164+
size_t flen, tlen, padding;
165+
struct pki *pki;
166+
int ret = 0;
167+
168+
m_msg(&m, imsg);
169+
m_get_string(&m, &pkiname);
170+
m_get_data(&m, &from, &flen);
171+
m_get_size(&m, &tlen);
172+
m_get_size(&m, &padding);
173+
m_end(&m);
174+
175+
pki = dict_get(env->sc_pki_dict, pkiname);
176+
if (pki == NULL || pki->pki_pkey == NULL ||
177+
(rsa = EVP_PKEY_get1_RSA(pki->pki_pkey)) == NULL)
178+
fatalx("ca_imsg: invalid pki");
179+
180+
if ((to = calloc(1, tlen)) == NULL)
181+
fatalx("ca_imsg: calloc");
182+
183+
switch (imsg->hdr.type) {
184+
case IMSG_CA_PRIVENC:
185+
ret = RSA_private_encrypt(flen, from, to, rsa,
186+
padding);
187+
break;
188+
case IMSG_CA_PRIVDEC:
189+
ret = RSA_private_decrypt(flen, from, to, rsa,
190+
padding);
191+
break;
192+
}
193+
194+
m_create(p, imsg->hdr.type, 0, 0, -1);
195+
m_add_int(p, ret);
196+
if (ret > 0)
197+
m_add_data(p, to, (size_t)ret);
198+
m_close(p);
199+
200+
free(to);
201+
RSA_free(rsa);
202+
}
203+
204+
/*
205+
* RSA privsep engine (called from unprivileged processes)
206+
*/
207+
208+
const RSA_METHOD *rsa_default = NULL;
209+
210+
static RSA_METHOD rsae_method = {
211+
"RSA privsep engine",
212+
rsae_pub_enc,
213+
rsae_pub_dec,
214+
rsae_priv_enc,
215+
rsae_priv_dec,
216+
rsae_mod_exp,
217+
rsae_bn_mod_exp,
218+
rsae_init,
219+
rsae_finish,
220+
0,
221+
NULL,
222+
rsae_sign,
223+
rsae_verify,
224+
rsae_keygen
225+
};
226+
227+
static int
228+
rsae_send_imsg(int flen, const u_char *from, u_char *to, RSA *rsa,
229+
int padding, u_int cmd)
230+
{
231+
int ret = 0;
232+
struct imsgbuf *ibuf;
233+
struct imsg imsg;
234+
int n, done = 0;
235+
const void *toptr;
236+
char *pkiname;
237+
size_t tlen;
238+
struct msg m;
239+
240+
if ((pkiname = RSA_get_ex_data(rsa, 0)) == NULL)
241+
return (0);
242+
243+
/*
244+
* Send a synchronous imsg because we cannot defer the RSA
245+
* operation in OpenSSL's engine layer.
246+
*/
247+
m_create(p_lka, cmd, 0, 0, -1);
248+
m_add_string(p_lka, pkiname);
249+
m_add_data(p_lka, (const void *)from, (size_t)flen);
250+
m_add_size(p_lka, (size_t)RSA_size(rsa));
251+
m_add_size(p_lka, (size_t)padding);
252+
m_flush(p_lka);
253+
254+
ibuf = &p_lka->imsgbuf;
255+
256+
while (!done) {
257+
if ((n = imsg_read(ibuf)) == -1)
258+
fatalx("imsg_read");
259+
if (n == 0)
260+
fatalx("pipe closed");
261+
262+
while (!done) {
263+
if ((n = imsg_get(ibuf, &imsg)) == -1)
264+
fatalx("imsg_get error");
265+
if (n == 0)
266+
break;
267+
if (imsg.hdr.type != cmd)
268+
fatalx("invalid response");
269+
270+
m_msg(&m, &imsg);
271+
m_get_int(&m, &ret);
272+
if (ret > 0)
273+
m_get_data(&m, &toptr, &tlen);
274+
m_end(&m);
275+
276+
if (ret > 0)
277+
memcpy(to, toptr, tlen);
278+
done = 1;
279+
280+
imsg_free(&imsg);
281+
}
282+
}
283+
mproc_event_add(p_lka);
284+
285+
return (ret);
286+
}
287+
288+
static int
289+
rsae_pub_enc(int flen,const u_char *from, u_char *to, RSA *rsa,int padding)
290+
{
291+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
292+
return (rsa_default->rsa_pub_enc(flen, from, to, rsa, padding));
293+
}
294+
295+
static int
296+
rsae_pub_dec(int flen,const u_char *from, u_char *to, RSA *rsa,int padding)
297+
{
298+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
299+
return (rsa_default->rsa_pub_dec(flen, from, to, rsa, padding));
300+
}
301+
302+
static int
303+
rsae_priv_enc(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
304+
{
305+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
306+
if (RSA_get_ex_data(rsa, 0) != NULL) {
307+
return (rsae_send_imsg(flen, from, to, rsa, padding,
308+
IMSG_CA_PRIVENC));
309+
}
310+
return (rsa_default->rsa_priv_enc(flen, from, to, rsa, padding));
311+
}
312+
313+
static int
314+
rsae_priv_dec(int flen, const u_char *from, u_char *to, RSA *rsa, int padding)
315+
{
316+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
317+
if (RSA_get_ex_data(rsa, 0) != NULL) {
318+
return (rsae_send_imsg(flen, from, to, rsa, padding,
319+
IMSG_CA_PRIVDEC));
320+
}
321+
return (rsa_default->rsa_priv_dec(flen, from, to, rsa, padding));
322+
}
323+
324+
static int
325+
rsae_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
326+
{
327+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
328+
return (rsa_default->rsa_mod_exp(r0, I, rsa, ctx));
329+
}
330+
331+
static int
332+
rsae_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
333+
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
334+
{
335+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
336+
return (rsa_default->bn_mod_exp(r, a, p, m, ctx, m_ctx));
337+
}
338+
339+
static int
340+
rsae_init(RSA *rsa)
341+
{
342+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
343+
if (rsa_default->init == NULL)
344+
return (1);
345+
return (rsa_default->init(rsa));
346+
}
347+
348+
static int
349+
rsae_finish(RSA *rsa)
350+
{
351+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
352+
if (rsa_default->finish == NULL)
353+
return (1);
354+
return (rsa_default->finish(rsa));
355+
}
356+
357+
static int
358+
rsae_sign(int type, const u_char *m, u_int m_length, u_char *sigret,
359+
u_int *siglen, const RSA *rsa)
360+
{
361+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
362+
return (rsa_default->rsa_sign(type, m, m_length,
363+
sigret, siglen, rsa));
364+
}
365+
366+
static int
367+
rsae_verify(int dtype, const u_char *m, u_int m_length, const u_char *sigbuf,
368+
u_int siglen, const RSA *rsa)
369+
{
370+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
371+
return (rsa_default->rsa_verify(dtype, m, m_length,
372+
sigbuf, siglen, rsa));
373+
}
374+
375+
static int
376+
rsae_keygen(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
377+
{
378+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
379+
return (rsa_default->rsa_keygen(rsa, bits, e, cb));
380+
}
381+
382+
int
383+
ca_engine_init(void)
384+
{
385+
ENGINE *e;
386+
387+
log_debug("debug: %s: %s", proc_name(smtpd_process), __func__);
388+
389+
if ((e = ENGINE_get_default_RSA()) == NULL ||
390+
(rsa_default = ENGINE_get_RSA(e)) == NULL)
391+
return (-1);
392+
393+
if (rsa_default->flags & RSA_FLAG_SIGN_VER)
394+
fatalx("unsupported RSA engine");
395+
396+
if (rsa_default->rsa_mod_exp == NULL)
397+
rsae_method.rsa_mod_exp = NULL;
398+
if (rsa_default->rsa_mod_exp == NULL)
399+
rsae_method.rsa_mod_exp = NULL;
400+
if (rsa_default->bn_mod_exp == NULL)
401+
rsae_method.bn_mod_exp = NULL;
402+
if (rsa_default->rsa_keygen == NULL)
403+
rsae_method.rsa_keygen = NULL;
404+
rsae_method.flags = rsa_default->flags |
405+
RSA_METHOD_FLAG_NO_CHECK;
406+
rsae_method.app_data = rsa_default->app_data;
407+
408+
if (!ENGINE_set_RSA(e, &rsae_method) ||
409+
!ENGINE_set_default_RSA(e))
410+
return (-1);
411+
412+
return (0);
413+
}

0 commit comments

Comments
 (0)