]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - src/tlsh.c
Import sendmail 8.16.1
[FreeBSD/FreeBSD.git] / src / tlsh.c
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 /*
61 **  TLS_DATA_MD -- calculate MD for data
62 **
63 **      Parameters:
64 **              buf -- data (in and out!)
65 **              len -- length of data
66 **              md -- digest algorithm
67 **
68 **      Returns:
69 **              <=0: cert fp calculation failed
70 **              >0: len of fp
71 **
72 **      Side Effects:
73 **              writes digest to buf
74 */
75
76 static int
77 tls_data_md(buf, len, md)
78         unsigned char *buf;
79         int len;
80         const EVP_MD *md;
81 {
82         unsigned int md_len;
83         EVP_MD_CTX *mdctx;
84         unsigned char md_buf[EVP_MAX_MD_SIZE];
85
86         SM_REQUIRE(buf != NULL);
87         SM_REQUIRE(md != NULL);
88         SM_REQUIRE(len >= EVP_MAX_MD_SIZE);
89
90         mdctx = EVP_MD_CTX_create();
91         if (EVP_DigestInit_ex(mdctx, md, NULL) != 1)
92                 return -EINVAL;
93         if (EVP_DigestUpdate(mdctx, (void *)buf, len) != 1)
94                 return -EINVAL;
95         if (EVP_DigestFinal_ex(mdctx, md_buf, &md_len) != 1)
96                 return -EINVAL;
97         EVP_MD_CTX_destroy(mdctx);
98
99         if (md_len > len)
100                 return -ERANGE;
101         (void) memcpy(buf, md_buf, md_len);
102         return (int)md_len;
103 }
104
105 #if DANE
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                 return DANE_VRFY_FAIL;
157         len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &end);
158         r = tls_data_md(buf, len, md);
159         if (r < 0)
160                 sm_free(buf);
161         else
162                 *fp = (char *)buf;
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 **              TLSA_*, see tls.h
177 */
178
179 int
180 dane_tlsa_chk(rr, len, host, log)
181         const char *rr;
182         int len;
183         const char *host;
184         bool log;
185 {
186         int alg;
187
188         if (len < 4)
189         {
190                 if (log && LogLevel > 8)
191                         sm_syslog(LOG_WARNING, NOQID,
192                                   "TLSA=%s, len=%d, status=bogus",
193                                   host, len);
194                 return TLSA_BOGUS;
195         }
196         SM_ASSERT(rr != NULL);
197
198         alg = (int)rr[2];
199         if ((int)rr[0] == 3 && (int)rr[1] == 1 && (alg >= 0 || alg <= 2))
200                 return alg;
201         if (log && LogLevel > 9)
202                 sm_syslog(LOG_NOTICE, NOQID,
203                           "TLSA=%s, type=%d-%d-%d:%02x, status=unsupported",
204                           host, (int)rr[0], (int)rr[1], (int)rr[2],
205                           (int)rr[3]);
206         return TLSA_UNSUPP;
207 }
208
209 /*
210 **  DANE_TLSA_CLR -- clear data in a dane_tlsa structure (for use)
211 **
212 **      Parameters:
213 **              dane_tlsa -- dane_tlsa to clear
214 **
215 **      Returns:
216 **              1 if NULL
217 **              0 if ok
218 */
219
220 int
221 dane_tlsa_clr(dane_tlsa)
222         dane_tlsa_P dane_tlsa;
223 {
224         int i;
225
226         if (dane_tlsa == NULL)
227                 return 1;
228         for (i = 0; i < dane_tlsa->dane_tlsa_n; i++)
229         {
230                 SM_FREE(dane_tlsa->dane_tlsa_rr[i]);
231                 dane_tlsa->dane_tlsa_len[i] = 0;
232         }
233         SM_FREE(dane_tlsa->dane_tlsa_sni);
234         memset(dane_tlsa, '\0', sizeof(*dane_tlsa));
235         return 0;
236
237 }
238
239 /*
240 **  DANE_TLSA_FREE -- free a dane_tlsa structure
241 **
242 **      Parameters:
243 **              dane_tlsa -- dane_tlsa to free
244 **
245 **      Returns:
246 **              0 if ok
247 **              1 if NULL
248 */
249
250 int
251 dane_tlsa_free(dane_tlsa)
252         dane_tlsa_P dane_tlsa;
253 {
254         if (dane_tlsa == NULL)
255                 return 1;
256         dane_tlsa_clr(dane_tlsa);
257         SM_FREE(dane_tlsa);
258         return 0;
259
260 }
261 #endif /* DANE */
262
263 #endif /* STARTTLS */