1/*
2 * Copyright (c) 2015 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11#include <sendmail.h>
12
13SM_RCSID("@(#)$Id: tls.c,v 8.127 2013-11-27 02:51:11 gshapiro Exp $")
14
15#if STARTTLS
16# include <tls.h>
17
18/*
19**  DATA2HEX -- create a printable hex string from binary data ("%02X:")
20**
21**	Parameters:
22**		buf -- data
23**		len -- length of data
24**		hex -- output buffer
25**		hlen -- length of output buffer
26**
27**	Returns:
28**		<0: errno
29**		>0: length of data in hex
30*/
31
32int
33data2hex(buf, blen, hex, hlen)
34	unsigned char *buf;
35	int blen;
36	unsigned char *hex;
37	int hlen;
38{
39	int r, h;
40	static const char hexcodes[] = "0123456789ABCDEF";
41
42	SM_REQUIRE(buf != NULL);
43	SM_REQUIRE(hex != NULL);
44	if (blen * 3 + 2 > hlen)
45		return -ERANGE;
46
47	for (r = 0, h = 0; r < blen && h + 3 < hlen; r++)
48	{
49		hex[h++] = hexcodes[(buf[r] & 0xf0) >> 4];
50		hex[h++] = hexcodes[(buf[r] & 0x0f)];
51		if (r + 1 < blen)
52			hex[h++] = ':';
53	}
54	if (h >= hlen)
55		return -ERANGE;
56	hex[h] = '\0';
57	return h;
58}
59
60# if DANE
61
62/*
63**  TLS_DATA_MD -- calculate MD for data
64**
65**	Parameters:
66**		buf -- data (in and out!)
67**		len -- length of data
68**		md -- digest algorithm
69**
70**	Returns:
71**		<=0: cert fp calculation failed
72**		>0: len of fp
73**
74**	Side Effects:
75**		writes digest to buf
76*/
77
78static int
79tls_data_md(buf, len, md)
80	unsigned char *buf;
81	int len;
82	const EVP_MD *md;
83{
84	unsigned int md_len;
85	EVP_MD_CTX *mdctx;
86	unsigned char md_buf[EVP_MAX_MD_SIZE];
87
88	SM_REQUIRE(buf != NULL);
89	SM_REQUIRE(md != NULL);
90	SM_REQUIRE(len >= EVP_MAX_MD_SIZE);
91
92	mdctx = EVP_MD_CTX_create();
93	if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
94		return -EINVAL;
95	if (EVP_DigestUpdate(mdctx, (void *)buf, len) != 1)
96		return -EINVAL;
97	if (EVP_DigestFinal_ex(mdctx, md_buf, &md_len) != 1)
98		return -EINVAL;
99	EVP_MD_CTX_destroy(mdctx);
100
101	if (md_len > len)
102		return -ERANGE;
103	(void) memcpy(buf, md_buf, md_len);
104	return (int)md_len;
105}
106
107/*
108**  PUBKEY_FP -- generate public key fingerprint
109**
110**	Parameters:
111**		cert -- TLS cert
112**		mdalg -- name of digest algorithm
113**		fp -- (pointer to) fingerprint buffer (output)
114**
115**	Returns:
116**		<=0: cert fp calculation failed
117**		>0: len of fp
118*/
119
120int
121pubkey_fp(cert, mdalg, fp)
122	X509 *cert;
123	const char *mdalg;
124	unsigned char **fp;
125{
126	int len, r;
127	unsigned char *end;
128	const EVP_MD *md;
129
130	SM_ASSERT(cert != NULL);
131	SM_ASSERT(fp != NULL);
132	SM_ASSERT(mdalg != NULL);
133
134	len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL);
135
136	/* what's an acceptable upper limit? */
137	if (len <= 0 || len >= 8192)
138		return -EINVAL;
139	if (len < EVP_MAX_MD_SIZE)
140		len = EVP_MAX_MD_SIZE;
141	*fp = end = sm_malloc(len);
142	if (NULL == end)
143		return -ENOMEM;
144
145	if ('\0' == mdalg[0])
146	{
147		r = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &end);
148		if (r <= 0 || r != len)
149			return -EINVAL;
150		return len;
151	}
152
153	md = EVP_get_digestbyname(mdalg);
154	if (NULL == md)
155	{
156		SM_FREE(*fp);
157		return DANE_VRFY_FAIL;
158	}
159	len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &end);
160	r = tls_data_md(*fp, len, md);
161	if (r < 0)
162		sm_free(*fp);
163	return r;
164}
165
166/*
167**  DANE_TLSA_CHK -- check whether a TLSA RR is ok to use
168**
169**	Parameters:
170**		rr -- RR
171**		len -- length of RR
172**		host -- name of host for RR (only for logging)
173**		log -- whether to log problems
174**
175**	Returns:
176**		>=0: "alg" aka "matching type"
177**		<0: TLSA_*, see tls.h
178*/
179
180int
181dane_tlsa_chk(rr, len, host, log)
182	const unsigned char *rr;
183	int len;
184	const char *host;
185	bool log;
186{
187	int alg;
188# if HAVE_SSL_CTX_dane_enable
189	int sel, usg;
190# endif
191
192	if (len < 4)
193	{
194		if (log && LogLevel > 8)
195			sm_syslog(LOG_WARNING, NOQID,
196				  "TLSA=%s, len=%d, status=bogus",
197				  host, len);
198		return TLSA_BOGUS;
199	}
200	SM_ASSERT(rr != NULL);
201
202	alg = (int)rr[2];
203# if HAVE_SSL_CTX_dane_enable
204	usg = (int)rr[0];
205	sel = (int)rr[1];
206	if (usg >= 2 && usg <= 3 && sel >= 0 && sel <= 1 &&
207	    alg >= 0 && alg <= 2)
208		return alg;
209# else
210	if ((int)rr[0] == 3 && (int)rr[1] == 1 && (alg >= 0 && alg <= 2))
211		return alg;
212# endif
213	if (log && LogLevel > 9)
214		sm_syslog(LOG_NOTICE, NOQID,
215			  "TLSA=%s, type=%d-%d-%d:%02x, status=unsupported",
216			  host, (int)rr[0], (int)rr[1], (int)rr[2],
217			  (int)rr[3]);
218	return TLSA_UNSUPP;
219}
220
221/*
222**  DANE_TLSA_CLR -- clear data in a dane_tlsa structure (for use)
223**
224**	Parameters:
225**		dane_tlsa -- dane_tlsa to clear
226**
227**	Returns:
228**		1 if NULL
229**		0 if ok
230*/
231
232int
233dane_tlsa_clr(dane_tlsa)
234	dane_tlsa_P dane_tlsa;
235{
236	int i;
237
238	if (dane_tlsa == NULL)
239		return 1;
240	for (i = 0; i < dane_tlsa->dane_tlsa_n; i++)
241	{
242		SM_FREE(dane_tlsa->dane_tlsa_rr[i]);
243		dane_tlsa->dane_tlsa_len[i] = 0;
244	}
245	SM_FREE(dane_tlsa->dane_tlsa_sni);
246	memset(dane_tlsa, '\0', sizeof(*dane_tlsa));
247	return 0;
248
249}
250
251/*
252**  DANE_TLSA_FREE -- free a dane_tlsa structure
253**
254**	Parameters:
255**		dane_tlsa -- dane_tlsa to free
256**
257**	Returns:
258**		0 if ok
259**		1 if NULL
260*/
261
262int
263dane_tlsa_free(dane_tlsa)
264	dane_tlsa_P dane_tlsa;
265{
266	if (dane_tlsa == NULL)
267		return 1;
268	dane_tlsa_clr(dane_tlsa);
269	SM_FREE(dane_tlsa);
270	return 0;
271
272}
273# endif /* DANE */
274
275#endif /* STARTTLS */
276