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/* 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 76static int 77tls_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 120int 121pubkey_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 179int 180dane_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 220int 221dane_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 250int 251dane_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 */ 264