xref: /freebsd/contrib/sendmail/src/tlsh.c (revision 8aac90f18aef7c9eea906c3ff9a001ca7b94f375)
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 
13 SM_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 
32 int
33 data2hex(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 
78 static int
79 tls_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 
120 int
121 pubkey_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 
180 int
181 dane_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 
232 int
233 dane_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 
262 int
263 dane_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