xref: /freebsd/contrib/sendmail/src/tlsh.c (revision 9f44a47fd07924afc035991af15d84e6585dea4f)
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 -- get public key fingerprint
109 **
110 **	Parameters:
111 **		cert -- TLS cert
112 **		mdalg -- name of digest algorithm
113 **		fp -- (pointer to) fingerprint buffer
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 	char **fp;
125 {
126 	int len, r;
127 	unsigned char *buf, *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 	end = buf = sm_malloc(len);
142 	if (NULL == buf)
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 		*fp = (char *)buf;
151 		return len;
152 	}
153 
154 	md = EVP_get_digestbyname(mdalg);
155 	if (NULL == md)
156 	{
157 		SM_FREE(buf);
158 		return DANE_VRFY_FAIL;
159 	}
160 	len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &end);
161 	r = tls_data_md(buf, len, md);
162 	if (r < 0)
163 		sm_free(buf);
164 	else
165 		*fp = (char *)buf;
166 	return r;
167 }
168 
169 /*
170 **  DANE_TLSA_CHK -- check whether a TLSA RR is ok to use
171 **
172 **	Parameters:
173 **		rr -- RR
174 **		len -- length of RR
175 **		host -- name of host for RR (only for logging)
176 **		log -- whether to log problems
177 **
178 **	Returns:
179 **		TLSA_*, see tls.h
180 */
181 
182 int
183 dane_tlsa_chk(rr, len, host, log)
184 	const char *rr;
185 	int len;
186 	const char *host;
187 	bool log;
188 {
189 	int alg;
190 
191 	if (len < 4)
192 	{
193 		if (log && LogLevel > 8)
194 			sm_syslog(LOG_WARNING, NOQID,
195 				  "TLSA=%s, len=%d, status=bogus",
196 				  host, len);
197 		return TLSA_BOGUS;
198 	}
199 	SM_ASSERT(rr != NULL);
200 
201 	alg = (int)rr[2];
202 	if ((int)rr[0] == 3 && (int)rr[1] == 1 && (alg >= 0 && alg <= 2))
203 		return alg;
204 	if (log && LogLevel > 9)
205 		sm_syslog(LOG_NOTICE, NOQID,
206 			  "TLSA=%s, type=%d-%d-%d:%02x, status=unsupported",
207 			  host, (int)rr[0], (int)rr[1], (int)rr[2],
208 			  (int)rr[3]);
209 	return TLSA_UNSUPP;
210 }
211 
212 /*
213 **  DANE_TLSA_CLR -- clear data in a dane_tlsa structure (for use)
214 **
215 **	Parameters:
216 **		dane_tlsa -- dane_tlsa to clear
217 **
218 **	Returns:
219 **		1 if NULL
220 **		0 if ok
221 */
222 
223 int
224 dane_tlsa_clr(dane_tlsa)
225 	dane_tlsa_P dane_tlsa;
226 {
227 	int i;
228 
229 	if (dane_tlsa == NULL)
230 		return 1;
231 	for (i = 0; i < dane_tlsa->dane_tlsa_n; i++)
232 	{
233 		SM_FREE(dane_tlsa->dane_tlsa_rr[i]);
234 		dane_tlsa->dane_tlsa_len[i] = 0;
235 	}
236 	SM_FREE(dane_tlsa->dane_tlsa_sni);
237 	memset(dane_tlsa, '\0', sizeof(*dane_tlsa));
238 	return 0;
239 
240 }
241 
242 /*
243 **  DANE_TLSA_FREE -- free a dane_tlsa structure
244 **
245 **	Parameters:
246 **		dane_tlsa -- dane_tlsa to free
247 **
248 **	Returns:
249 **		0 if ok
250 **		1 if NULL
251 */
252 
253 int
254 dane_tlsa_free(dane_tlsa)
255 	dane_tlsa_P dane_tlsa;
256 {
257 	if (dane_tlsa == NULL)
258 		return 1;
259 	dane_tlsa_clr(dane_tlsa);
260 	SM_FREE(dane_tlsa);
261 	return 0;
262 
263 }
264 # endif /* DANE */
265 
266 #endif /* STARTTLS */
267