/ sslViewer / sslAppUtils.cpp
sslAppUtils.cpp
   1  /*
   2   * Copyright (c) 2006-2008,2010-2013 Apple Inc. All Rights Reserved.
   3   */
   4  
   5  #include "sslAppUtils.h"
   6  //#include "sslThreading.h"
   7  //#include "identPicker.h"
   8  //#include <utilLib/common.h>
   9  #include <stdlib.h>
  10  #include <stdio.h>
  11  #include <sys/param.h>
  12  #include <Security/SecBase.h>
  13  
  14  #include <CoreFoundation/CoreFoundation.h>
  15  #include <Security/Security.h>
  16  #include <Security/SecIdentityPriv.h>
  17  #include <AssertMacros.h>
  18  #include <sys/time.h>
  19  
  20  #include "utilities/SecCFRelease.h"
  21  
  22  /* Set true when PR-3074739 is merged to TOT */
  23  #define NEW_SSL_ERRS_3074739		1
  24  
  25  
  26  const char *sslGetCipherSuiteString(SSLCipherSuite cs)
  27  {
  28      static char noSuite[40];
  29  
  30      switch (cs) {
  31              /* TLS cipher suites, RFC 2246 */
  32          case SSL_NULL_WITH_NULL_NULL:               return "TLS_NULL_WITH_NULL_NULL";
  33          case SSL_RSA_WITH_NULL_MD5:                 return "TLS_RSA_WITH_NULL_MD5";
  34          case SSL_RSA_WITH_NULL_SHA:                 return "TLS_RSA_WITH_NULL_SHA";
  35          case SSL_RSA_EXPORT_WITH_RC4_40_MD5:        return "TLS_RSA_EXPORT_WITH_RC4_40_MD5";
  36          case SSL_RSA_WITH_RC4_128_MD5:              return "TLS_RSA_WITH_RC4_128_MD5";
  37          case SSL_RSA_WITH_RC4_128_SHA:              return "TLS_RSA_WITH_RC4_128_SHA";
  38          case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:    return "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
  39          case SSL_RSA_WITH_IDEA_CBC_SHA:             return "TLS_RSA_WITH_IDEA_CBC_SHA";
  40          case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:     return "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA";
  41          case SSL_RSA_WITH_DES_CBC_SHA:              return "TLS_RSA_WITH_DES_CBC_SHA";
  42          case SSL_RSA_WITH_3DES_EDE_CBC_SHA:         return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
  43          case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:  return "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
  44          case SSL_DH_DSS_WITH_DES_CBC_SHA:           return "TLS_DH_DSS_WITH_DES_CBC_SHA";
  45          case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:      return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
  46          case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:  return "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
  47          case SSL_DH_RSA_WITH_DES_CBC_SHA:           return "TLS_DH_RSA_WITH_DES_CBC_SHA";
  48          case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:      return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
  49          case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
  50          case SSL_DHE_DSS_WITH_DES_CBC_SHA:          return "TLS_DHE_DSS_WITH_DES_CBC_SHA";
  51          case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:     return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
  52          case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
  53          case SSL_DHE_RSA_WITH_DES_CBC_SHA:          return "TLS_DHE_RSA_WITH_DES_CBC_SHA";
  54          case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:     return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
  55          case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:    return "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5";
  56          case SSL_DH_anon_WITH_RC4_128_MD5:          return "TLS_DH_anon_WITH_RC4_128_MD5";
  57          case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA: return "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
  58          case SSL_DH_anon_WITH_DES_CBC_SHA:          return "TLS_DH_anon_WITH_DES_CBC_SHA";
  59          case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:     return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
  60  
  61              /* SSLv3 Fortezza cipher suites, from NSS */
  62          case SSL_FORTEZZA_DMS_WITH_NULL_SHA:        return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
  63          case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
  64  
  65              /* TLS addenda using AES-CBC, RFC 3268 */
  66          case TLS_RSA_WITH_AES_128_CBC_SHA:          return "TLS_RSA_WITH_AES_128_CBC_SHA";
  67          case TLS_DH_DSS_WITH_AES_128_CBC_SHA:       return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
  68          case TLS_DH_RSA_WITH_AES_128_CBC_SHA:       return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
  69          case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:      return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
  70          case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:      return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
  71          case TLS_DH_anon_WITH_AES_128_CBC_SHA:      return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
  72          case TLS_RSA_WITH_AES_256_CBC_SHA:          return "TLS_RSA_WITH_AES_256_CBC_SHA";
  73          case TLS_DH_DSS_WITH_AES_256_CBC_SHA:       return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
  74          case TLS_DH_RSA_WITH_AES_256_CBC_SHA:       return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
  75          case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:      return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
  76          case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:      return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
  77          case TLS_DH_anon_WITH_AES_256_CBC_SHA:      return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
  78  
  79              /* ECDSA addenda, RFC 4492 */
  80          case TLS_ECDH_ECDSA_WITH_NULL_SHA:          return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
  81          case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:       return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
  82          case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:  return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
  83          case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:   return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
  84          case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:   return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
  85          case TLS_ECDHE_ECDSA_WITH_NULL_SHA:         return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
  86          case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:      return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
  87          case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
  88          case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:  return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
  89          case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:  return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
  90          case TLS_ECDH_RSA_WITH_NULL_SHA:            return "TLS_ECDH_RSA_WITH_NULL_SHA";
  91          case TLS_ECDH_RSA_WITH_RC4_128_SHA:         return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
  92          case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:    return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
  93          case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:     return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
  94          case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:     return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
  95          case TLS_ECDHE_RSA_WITH_NULL_SHA:           return "TLS_ECDHE_RSA_WITH_NULL_SHA";
  96          case TLS_ECDHE_RSA_WITH_RC4_128_SHA:        return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
  97          case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:   return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
  98          case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:    return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
  99          case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:    return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
 100          case TLS_ECDH_anon_WITH_NULL_SHA:           return "TLS_ECDH_anon_WITH_NULL_SHA";
 101          case TLS_ECDH_anon_WITH_RC4_128_SHA:        return "TLS_ECDH_anon_WITH_RC4_128_SHA";
 102          case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:   return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
 103          case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:    return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
 104          case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:    return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
 105  
 106              /* TLS 1.2 addenda, RFC 5246 */
 107          case TLS_RSA_WITH_AES_128_CBC_SHA256:       return "TLS_RSA_WITH_AES_128_CBC_SHA256";
 108          case TLS_RSA_WITH_AES_256_CBC_SHA256:       return "TLS_RSA_WITH_AES_256_CBC_SHA256";
 109          case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:    return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
 110          case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:    return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
 111          case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:   return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
 112          case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:   return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
 113          case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:    return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
 114          case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:    return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
 115          case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:   return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
 116          case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:   return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
 117          case TLS_DH_anon_WITH_AES_128_CBC_SHA256:   return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
 118          case TLS_DH_anon_WITH_AES_256_CBC_SHA256:   return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
 119  
 120              /* TLS addenda using AES-GCM, RFC 5288 */
 121          case TLS_RSA_WITH_AES_128_GCM_SHA256:       return "TLS_RSA_WITH_AES_128_GCM_SHA256";
 122          case TLS_RSA_WITH_AES_256_GCM_SHA384:       return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
 123          case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:   return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
 124          case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:   return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
 125          case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:    return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
 126          case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:    return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
 127          case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:   return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
 128          case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:   return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
 129          case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:    return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
 130          case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:    return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
 131          case TLS_DH_anon_WITH_AES_128_GCM_SHA256:   return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
 132          case TLS_DH_anon_WITH_AES_256_GCM_SHA384:   return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
 133  
 134              /* ECDSA addenda, RFC 5289 */
 135          case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:   return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
 136          case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:   return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
 137          case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:    return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
 138          case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:    return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
 139          case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:     return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
 140          case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:     return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
 141          case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:      return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
 142          case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:      return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
 143          case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:   return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
 144          case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:   return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
 145          case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:    return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
 146          case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:    return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
 147          case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:     return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
 148          case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:     return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
 149          case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:      return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
 150          case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:      return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
 151              
 152              /*
 153               * Tags for SSL 2 cipher kinds which are not specified for SSL 3.
 154               */
 155          case SSL_RSA_WITH_RC2_CBC_MD5:              return "TLS_RSA_WITH_RC2_CBC_MD5";
 156          case SSL_RSA_WITH_IDEA_CBC_MD5:             return "TLS_RSA_WITH_IDEA_CBC_MD5";
 157          case SSL_RSA_WITH_DES_CBC_MD5:              return "TLS_RSA_WITH_DES_CBC_MD5";
 158          case SSL_RSA_WITH_3DES_EDE_CBC_MD5:         return "TLS_RSA_WITH_3DES_EDE_CBC_MD5";
 159          case SSL_NO_SUCH_CIPHERSUITE:               return "SSL_NO_SUCH_CIPHERSUITE";
 160              
 161          default:
 162              snprintf(noSuite, sizeof(noSuite), "Unknown ciphersuite 0x%04x", (unsigned)cs);
 163              return noSuite;
 164      }
 165  }
 166  
 167  /* 
 168   * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
 169   * return a string representation.
 170   */
 171  const char *sslGetProtocolVersionString(SSLProtocol prot)
 172  {
 173  	static char noProt[20];
 174      
 175  #pragma clang diagnostic push
 176  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 177  	switch(prot) {
 178  		case kSSLProtocolUnknown:
 179  			return "kSSLProtocolUnknown";
 180  		case kSSLProtocol2:
 181  			return "kSSLProtocol2";
 182  		case kSSLProtocol3:
 183  			return "kSSLProtocol3";
 184  		case kSSLProtocol3Only:
 185  			return "kSSLProtocol3Only";
 186  		case kTLSProtocol1:
 187  			return "kTLSProtocol1";
 188  		case kTLSProtocol1Only:
 189  			return "kTLSProtocol1Only";
 190          case kTLSProtocol11:
 191  			return "kTLSProtocol11";
 192          case kTLSProtocol12:
 193  			return "kTLSProtocol12";
 194  		default:
 195  			sprintf(noProt, "Unknown (%d)", (unsigned)prot);
 196  			return noProt;	
 197  	}
 198  #pragma clang diagnostic pop
 199  }
 200  
 201  /* 
 202   * Return string representation of SecureTransport-related OSStatus.
 203   */
 204  const char *sslGetSSLErrString(OSStatus err)
 205  {
 206  	static char errSecSuccessStr[20];
 207  	
 208  	switch(err) {
 209  		case errSecSuccess:
 210  			return "errSecSuccess";
 211  		case errSecAllocate:
 212  			return "errSecAllocate";
 213  		case errSecParam:
 214  			return "errSecParam";
 215  		case errSecUnimplemented:
 216  			return "errSecUnimplemented";
 217  		case errSecIO:
 218  			return "errSecIO";
 219  		case errSecBadReq:
 220  			return "errSecBadReq";
 221  		case errSSLProtocol:
 222  			return "errSSLProtocol";
 223  		case errSSLNegotiation:
 224  			return "errSSLNegotiation";
 225  		case errSSLFatalAlert:
 226  			return "errSSLFatalAlert";
 227  		case errSSLWouldBlock:
 228  			return "errSSLWouldBlock";
 229  		case errSSLSessionNotFound:
 230  			return "errSSLSessionNotFound";
 231  		case errSSLClosedGraceful:
 232  			return "errSSLClosedGraceful";
 233  		case errSSLClosedAbort:
 234  			return "errSSLClosedAbort";
 235     		case errSSLXCertChainInvalid:
 236  			return "errSSLXCertChainInvalid";
 237  		case errSSLBadCert:
 238  			return "errSSLBadCert"; 
 239  		case errSSLCrypto:
 240  			return "errSSLCrypto";
 241  		case errSSLInternal:
 242  			return "errSSLInternal";
 243  		case errSSLModuleAttach:
 244  			return "errSSLModuleAttach";
 245  		case errSSLUnknownRootCert:
 246  			return "errSSLUnknownRootCert";
 247  		case errSSLNoRootCert:
 248  			return "errSSLNoRootCert";
 249  		case errSSLCertExpired:
 250  			return "errSSLCertExpired";
 251  		case errSSLCertNotYetValid:
 252  			return "errSSLCertNotYetValid";
 253  		case errSSLClosedNoNotify:
 254  			return "errSSLClosedNoNotify";
 255  		case errSSLBufferOverflow:
 256  			return "errSSLBufferOverflow";
 257  		case errSSLBadCipherSuite:
 258  			return "errSSLBadCipherSuite";
 259  		/* TLS/Panther addenda */
 260  		case errSSLPeerUnexpectedMsg:
 261  			return "errSSLPeerUnexpectedMsg";
 262  		case errSSLPeerBadRecordMac:
 263  			return "errSSLPeerBadRecordMac";
 264  		case errSSLPeerDecryptionFail:
 265  			return "errSSLPeerDecryptionFail";
 266  		case errSSLPeerRecordOverflow:
 267  			return "errSSLPeerRecordOverflow";
 268  		case errSSLPeerDecompressFail:
 269  			return "errSSLPeerDecompressFail";
 270  		case errSSLPeerHandshakeFail:
 271  			return "errSSLPeerHandshakeFail";
 272  		case errSSLPeerBadCert:
 273  			return "errSSLPeerBadCert";
 274  		case errSSLPeerUnsupportedCert:
 275  			return "errSSLPeerUnsupportedCert";
 276  		case errSSLPeerCertRevoked:
 277  			return "errSSLPeerCertRevoked";
 278  		case errSSLPeerCertExpired:
 279  			return "errSSLPeerCertExpired";
 280  		case errSSLPeerCertUnknown:
 281  			return "errSSLPeerCertUnknown";
 282  		case errSSLIllegalParam:
 283  			return "errSSLIllegalParam";
 284  		case errSSLPeerUnknownCA:
 285  			return "errSSLPeerUnknownCA";
 286  		case errSSLPeerAccessDenied:
 287  			return "errSSLPeerAccessDenied";
 288  		case errSSLPeerDecodeError:
 289  			return "errSSLPeerDecodeError";
 290  		case errSSLPeerDecryptError:
 291  			return "errSSLPeerDecryptError";
 292  		case errSSLPeerExportRestriction:
 293  			return "errSSLPeerExportRestriction";
 294  		case errSSLPeerProtocolVersion:
 295  			return "errSSLPeerProtocolVersion";
 296  		case errSSLPeerInsufficientSecurity:
 297  			return "errSSLPeerInsufficientSecurity";
 298  		case errSSLPeerInternalError:
 299  			return "errSSLPeerInternalError";
 300  		case errSSLPeerUserCancelled:
 301  			return "errSSLPeerUserCanceled";
 302  		case errSSLPeerNoRenegotiation:
 303  			return "errSSLPeerNoRenegotiation";
 304  		case errSSLHostNameMismatch:
 305  			return "errSSLHostNameMismatch";
 306  		case errSSLConnectionRefused:
 307  			return "errSSLConnectionRefused";
 308  		case errSSLDecryptionFail:
 309  			return "errSSLDecryptionFail";
 310  		case errSSLBadRecordMac:
 311  			return "errSSLBadRecordMac";
 312  		case errSSLRecordOverflow:
 313  			return "errSSLRecordOverflow";
 314  		case errSSLBadConfiguration:
 315  			return "errSSLBadConfiguration";
 316  		
 317  		/* some from the Sec layer */
 318  		case errSecNotAvailable:			return "errSecNotAvailable";
 319  		case errSecDuplicateItem:			return "errSecDuplicateItem";
 320  		case errSecItemNotFound:			return "errSecItemNotFound";
 321  #if 0
 322  		case errSessionInvalidId:			return "errSessionInvalidId";
 323  		case errSessionInvalidAttributes:	return "errSessionInvalidAttributes";
 324  		case errSessionAuthorizationDenied:	return "errSessionAuthorizationDenied";
 325  		case errSessionInternal:			return "errSessionInternal";
 326  		case errSessionInvalidFlags:		return "errSessionInvalidFlags";
 327  #endif
 328  
 329  		default:
 330  #if 0
 331  			if (err < (CSSM_BASE_ERROR + 
 332  			         (CSSM_ERRORCODE_MODULE_EXTENT * 8)))
 333  			{
 334  				/* assume CSSM error */
 335  				return cssmErrToStr(err);
 336  			}
 337  			else
 338  #endif
 339  			{
 340  				sprintf(errSecSuccessStr, "Unknown (%d)", (unsigned)err);
 341  				return errSecSuccessStr;	
 342  			}
 343  	}
 344  }
 345  
 346  void printSslErrStr(
 347  	const char 	*op,
 348  	OSStatus 	err)
 349  {
 350  	printf("*** %s: %s\n", op, sslGetSSLErrString(err));
 351  }
 352  
 353  const char *sslGetClientCertStateString(SSLClientCertificateState state)
 354  {
 355  	static char noState[20];
 356  	
 357  #pragma clang diagnostic push
 358  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 359  	switch(state) {
 360  		case kSSLClientCertNone:
 361  			return "ClientCertNone";
 362  		case kSSLClientCertRequested:
 363  			return "CertRequested";
 364  		case kSSLClientCertSent:
 365  			return "ClientCertSent";
 366  		case kSSLClientCertRejected:
 367  			return "ClientCertRejected";
 368  		default:
 369  			sprintf(noState, "Unknown (%d)", (unsigned)state);
 370  			return noState;	
 371  	}
 372  #pragma clang diagnostic pop
 373  }
 374  
 375  /*
 376   * Convert a keychain name (which may be NULL) into the CFArrayRef required
 377   * by SSLSetCertificate. This is a bare-bones example of this operation,
 378   * since it requires and assumes that there is exactly one SecIdentity
 379   * in the keychain - i.e., there is exactly one matching cert/private key 
 380   * pair. A real world server would probably search a keychain for a SecIdentity 
 381   * matching some specific criteria. 
 382   */
 383  CFArrayRef getSslCerts( 
 384  	const char			*kcName,				// may be NULL, i.e., use default
 385  	bool                encryptOnly,
 386  	bool                completeCertChain,
 387  	const char			*anchorFile,			// optional trusted anchor
 388  	SecKeychainRef		*pKcRef)				// RETURNED
 389  {
 390  #if 0
 391  	SecKeychainRef 		kcRef = nil;
 392  	OSStatus			ortn;
 393  	
 394  	*pKcRef = nil;
 395  	
 396  	/* pick a keychain */
 397  	if(kcName) {
 398  		ortn = SecKeychainOpen(kcName, &kcRef);
 399  		if(ortn) {
 400  			printf("SecKeychainOpen returned %d.\n", (int)ortn);
 401  			printf("Cannot open keychain at %s. Aborting.\n", kcName);
 402  			return NULL;
 403  		}
 404  	}
 405  	else {
 406  		/* use default keychain */
 407  		ortn = SecKeychainCopyDefault(&kcRef);
 408  		if(ortn) {
 409  			printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn);
 410  			return nil;
 411  		}
 412  	}
 413  	*pKcRef = kcRef;
 414  	return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile);
 415  #else
 416  	SecCertificateRef cert = NULL;
 417  	SecIdentityRef identity = NULL;
 418  	CFMutableArrayRef certificates = NULL, result = NULL;
 419  	CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL;
 420  	SecTrustRef trust = NULL;
 421  	SecKeyRef key = NULL;
 422  	CFTypeRef pkdigest = NULL;
 423  
 424  	// Find the first private key in the keychain and return both it's
 425  	// attributes and a ref to it.
 426  	require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut);
 427  	CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey);
 428  	CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
 429  	CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue);
 430  	CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue);
 431  	require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult),
 432  		errOut);
 433  	require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef),
 434  		errOut);
 435  	require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel),
 436  		errOut);
 437  
 438  	// Find the first certificate that has the same public key hash as the
 439  	// returned private key and return it as a ref.
 440  	require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut);
 441  	CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate);
 442  	CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest);
 443  	CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue);
 444  	require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut);
 445  
 446  	// Create an identity from the key and certificate.
 447  	require(identity = SecIdentityCreate(NULL, cert, key), errOut);
 448  
 449  	// Build a (partial) certificate chain from cert
 450  	require(certificates = CFArrayCreateMutable(NULL, 0,
 451  		&kCFTypeArrayCallBacks), errOut);
 452  	CFArrayAppendValue(certificates, cert);
 453  	require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust),
 454  		errOut);
 455  
 456  	CFIndex certCount, ix;
 457  	// We need at least 1 certificate
 458      // SecTrustGetCertificateCount implicitly does a trust evaluation to determine
 459      // the number of certs in the chain.
 460  	require(certCount = SecTrustGetCertificateCount(trust), errOut);
 461  
 462  	// Build a result where element 0 is the identity and the other elements
 463  	// are the certs in the chain starting at the first intermediate up to the
 464  	// anchor, if we found one, or as far as we were able to build the chain
 465  	// if not.
 466  	require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks),
 467  		errOut);
 468  
 469  	// We are commited to returning a result now, so do not use require below
 470  	// this line without setting result to NULL again.
 471  	CFArrayAppendValue(result, identity);
 472  	for (ix = 1; ix < certCount; ++ix) {
 473  		CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix));
 474  	}
 475  
 476  errOut:
 477  	CFReleaseSafe(trust);
 478  	CFReleaseSafe(certificates);
 479  	CFReleaseSafe(identity);
 480  	CFReleaseSafe(cert);
 481  	CFReleaseSafe(certQuery);
 482  	CFReleaseSafe(keyResult);
 483  	CFReleaseSafe(keyQuery);
 484  
 485      return result;
 486  #endif
 487  }
 488  
 489  #if 0
 490  /*
 491   * Determine if specified SecCertificateRef is a self-signed cert.
 492   * We do this by comparing the subject and issuerr names; no cryptographic
 493   * verification is performed.
 494   *
 495   * Returns true if the cert appears to be a root. 
 496   */
 497  static bool isCertRefRoot(
 498  	SecCertificateRef certRef)
 499  {
 500  	bool brtn = false;
 501  #if 0
 502  	/* just search for the two attrs we want */
 503  	UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr};
 504  	SecKeychainAttributeInfo attrInfo;
 505  	attrInfo.count = 2;
 506  	attrInfo.tag = tags;
 507  	attrInfo.format = NULL;
 508  	SecKeychainAttributeList *attrList = NULL;
 509  	SecKeychainAttribute *attr1 = NULL;
 510  	SecKeychainAttribute *attr2 = NULL;
 511  	
 512  	OSStatus ortn = SecKeychainItemCopyAttributesAndData(
 513  		(SecKeychainItemRef)certRef, 
 514  		&attrInfo,
 515  		NULL,			// itemClass
 516  		&attrList, 
 517  		NULL,			// length - don't need the data
 518  		NULL);			// outData
 519  	if(ortn) {
 520  		cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
 521  		/* may want to be a bit more robust here, but this should
 522  		 * never happen */
 523  		return false;
 524  	}
 525  	/* subsequent errors to errOut: */
 526  	
 527  	if((attrList == NULL) || (attrList->count != 2)) {
 528  		printf("***Unexpected result fetching label attr\n");
 529  		goto errOut;
 530  	}
 531  	
 532  	/* rootness is just byte-for-byte compare of the two names */ 
 533  	attr1 = &attrList->attr[0];
 534  	attr2 = &attrList->attr[1];
 535  	if(attr1->length == attr2->length) {
 536  		if(memcmp(attr1->data, attr2->data, attr1->length) == 0) {
 537  			brtn = true;
 538  		}
 539  	}
 540  errOut:
 541  	SecKeychainItemFreeAttributesAndData(attrList, NULL);
 542  #endif
 543  	return brtn;
 544  }
 545  #endif
 546  
 547  #if 0
 548  /*
 549   * Given a SecIdentityRef, do our best to construct a complete, ordered, and 
 550   * verified cert chain, returning the result in a CFArrayRef. The result is 
 551   * suitable for use when calling SSLSetCertificate().
 552   */
 553  OSStatus sslCompleteCertChain(
 554  	SecIdentityRef 		identity, 
 555  	SecCertificateRef	trustedAnchor,	// optional additional trusted anchor
 556  	bool 				includeRoot, 	// include the root in outArray
 557  	CFArrayRef			*outArray)		// created and RETURNED
 558  {
 559  	CFMutableArrayRef 			certArray;
 560  	SecTrustRef					secTrust = NULL;
 561  	SecPolicyRef				policy = NULL;
 562  	SecPolicySearchRef			policySearch = NULL;
 563  	SecTrustResultType			secTrustResult;
 564  	CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;			// not used
 565  	CFArrayRef					certChain = NULL;   // constructed chain
 566  	CFIndex 					numResCerts;
 567  	
 568  	certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
 569  	CFArrayAppendValue(certArray, identity);
 570  	
 571  	/*
 572  	 * Case 1: identity is a root; we're done. Note that this case
 573  	 * overrides the includeRoot argument.
 574  	 */
 575  	SecCertificateRef certRef;
 576  	OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef);
 577  	if(ortn) {
 578  		/* should never happen */
 579  		cssmPerror("SecIdentityCopyCertificate", ortn);
 580  		return ortn;
 581  	}
 582  	bool isRoot = isCertRefRoot(certRef);
 583  	if(isRoot) {
 584  		*outArray = certArray;
 585  		CFRelease(certRef);
 586  		return errSecSuccess;
 587  	}
 588  	
 589  	/* 
 590  	 * Now use SecTrust to get a complete cert chain, using all of the 
 591  	 * user's keychains to look for intermediate certs.
 592  	 * NOTE this does NOT handle root certs which are not in the system
 593  	 * root cert DB. (The above case, where the identity is a root cert, does.)
 594  	 */
 595  	CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
 596  	CFArraySetValueAtIndex(subjCerts, 0, certRef);
 597  			
 598  	/* the array owns the subject cert ref now */
 599  	CFRelease(certRef);
 600  	
 601  	/* Get a SecPolicyRef for generic X509 cert chain verification */
 602  	ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
 603  		&CSSMOID_APPLE_X509_BASIC,
 604  		NULL,				// value
 605  		&policySearch);
 606  	if(ortn) {
 607  		cssmPerror("SecPolicySearchCreate", ortn);
 608  		goto errOut;
 609  	}
 610  	ortn = SecPolicySearchCopyNext(policySearch, &policy);
 611  	if(ortn) {
 612  		cssmPerror("SecPolicySearchCopyNext", ortn);
 613  		goto errOut;
 614  	}
 615  
 616  	/* build a SecTrustRef for specified policy and certs */
 617  	ortn = SecTrustCreateWithCertificates(subjCerts,
 618  		policy, &secTrust);
 619  	if(ortn) {
 620  		cssmPerror("SecTrustCreateWithCertificates", ortn);
 621  		goto errOut;
 622  	}
 623  	
 624  	if(trustedAnchor) {
 625  		/* 
 626  		 * Tell SecTrust to trust this one in addition to the current
 627  		 * trusted system-wide anchors.
 628  		 */
 629  		CFMutableArrayRef newAnchors;
 630  		CFArrayRef currAnchors;
 631  		
 632  		ortn = SecTrustCopyAnchorCertificates(&currAnchors);
 633  		if(ortn) {
 634  			/* should never happen */
 635  			cssmPerror("SecTrustCopyAnchorCertificates", ortn);
 636  			goto errOut;
 637  		}
 638  		newAnchors = CFArrayCreateMutableCopy(NULL,
 639  			CFArrayGetCount(currAnchors) + 1,
 640  			currAnchors);
 641  		CFRelease(currAnchors);
 642  		CFArrayAppendValue(newAnchors, trustedAnchor);
 643  		ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
 644  		CFRelease(newAnchors);
 645  		if(ortn) {
 646  			cssmPerror("SecTrustSetAnchorCertificates", ortn);
 647  			goto errOut;
 648  		}
 649  	}
 650  	/* evaluate: GO */
 651  	ortn = SecTrustEvaluate(secTrust, &secTrustResult);
 652  	if(ortn) {
 653  		cssmPerror("SecTrustEvaluate", ortn);
 654  		goto errOut;
 655  	}
 656  	switch(secTrustResult) {
 657  		case kSecTrustResultUnspecified:
 658  			/* cert chain valid, no special UserTrust assignments */
 659  		case kSecTrustResultProceed:
 660  			/* cert chain valid AND user explicitly trusts this */
 661  			break;
 662  		default:
 663  			/*
 664  			 * Cert chain construction failed. 
 665  			 * Just go with the single subject cert we were given.
 666  			 */
 667  			printf("***Warning: could not construct completed cert chain\n");
 668  			ortn = errSecSuccess;
 669  			goto errOut;
 670  	}
 671  
 672  	/* get resulting constructed cert chain */
 673  	ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
 674  	if(ortn) {
 675  		cssmPerror("SecTrustEvaluate", ortn);
 676  		goto errOut;
 677  	}
 678  	
 679  	/*
 680  	 * Copy certs from constructed chain to our result array, skipping 
 681  	 * the leaf (which is already there, as a SecIdentityRef) and possibly
 682  	 * a root.
 683  	 */
 684  	numResCerts = CFArrayGetCount(certChain);
 685  	if(numResCerts < 2) {
 686  		/*
 687  		 * Can't happen: if subject was a root, we'd already have returned. 
 688  		 * If chain doesn't verify to a root, we'd have bailed after
 689  		 * SecTrustEvaluate().
 690  		 */
 691  		printf("***sslCompleteCertChain screwup: numResCerts %d\n", 
 692  			(int)numResCerts);
 693  		ortn = errSecSuccess;
 694  		goto errOut;
 695  	}
 696  	if(!includeRoot) {
 697  		/* skip the last (root) cert) */
 698  		numResCerts--;
 699  	}
 700  	for(CFIndex dex=1; dex<numResCerts; dex++) {
 701  		certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
 702  		CFArrayAppendValue(certArray, certRef);
 703  	}
 704  errOut:
 705  	/* clean up */
 706  	if(secTrust) {
 707  		CFRelease(secTrust);
 708  	}
 709  	if(subjCerts) {
 710  		CFRelease(subjCerts);
 711  	}
 712  	if(policy) {
 713  		CFRelease(policy);
 714  	}
 715  	if(policySearch) {
 716  		CFRelease(policySearch);
 717  	}
 718  	*outArray = certArray;
 719  	return ortn;
 720  }
 721  
 722  
 723  /*
 724   * Given an open keychain, find a SecIdentityRef and munge it into
 725   * a CFArrayRef required by SSLSetCertificate().
 726   */
 727  CFArrayRef sslKcRefToCertArray(
 728  	SecKeychainRef		kcRef,
 729  	bool                encryptOnly,
 730  	bool                completeCertChain,
 731  	const char			*trustedAnchorFile)
 732  {
 733  	/* quick check to make sure the keychain exists */
 734  	SecKeychainStatus kcStat;
 735  	OSStatus ortn = SecKeychainGetStatus(kcRef, &kcStat);
 736  	if(ortn) {
 737  		printSslErrStr("SecKeychainGetStatus", ortn);
 738  		printf("Can not open keychain. Aborting.\n");
 739  		return nil;
 740  	}
 741  	
 742  	/*
 743  	 * Search for "any" identity matching specified key use; 
 744  	 * in this app, we expect there to be exactly one. 
 745  	 */
 746  	SecIdentitySearchRef srchRef = nil;
 747  	ortn = SecIdentitySearchCreate(kcRef, 
 748  		encryptOnly ? CSSM_KEYUSE_DECRYPT : CSSM_KEYUSE_SIGN,
 749  		&srchRef);
 750  	if(ortn) {
 751  		printf("SecIdentitySearchCreate returned %d.\n", (int)ortn);
 752  		printf("Cannot find signing key in keychain. Aborting.\n");
 753  		return nil;
 754  	}
 755  	SecIdentityRef identity = nil;
 756  	ortn = SecIdentitySearchCopyNext(srchRef, &identity);
 757  	if(ortn) {
 758  		printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn);
 759  		printf("Cannot find signing key in keychain. Aborting.\n");
 760  		return nil;
 761  	}
 762  	if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
 763  		printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
 764  		return nil;
 765  	}
 766  
 767  	/* 
 768  	 * Found one. 
 769  	 */
 770  	if(completeCertChain) {
 771  		/* 
 772  		 * Place it and the other certs needed to verify it -
 773  		 * up to but not including the root - in a CFArray.
 774  		 */
 775  		SecCertificateRef anchorCert = NULL;
 776  		if(trustedAnchorFile) {
 777  			ortn = sslReadAnchor(trustedAnchorFile, &anchorCert);
 778  			if(ortn) {
 779  				printf("***Error reading anchor file\n");
 780  			}
 781  		}
 782  		CFArrayRef ca;
 783  		ortn = sslCompleteCertChain(identity, anchorCert, false, &ca);
 784  		if(anchorCert) {
 785  			CFRelease(anchorCert);
 786  		}
 787  		return ca;
 788  	}
 789  	else {
 790  		/* simple case, just this one identity */
 791  		CFArrayRef ca = CFArrayCreate(NULL,
 792  			(const void **)&identity,
 793  			1,
 794  			NULL);
 795  		if(ca == nil) {
 796  			printf("CFArrayCreate error\n");
 797  		}
 798  		return ca;
 799  	}
 800  }
 801  #endif
 802  
 803  #pragma clang diagnostic push
 804  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
 805  
 806  OSStatus addTrustedSecCert(
 807  	SSLContextRef 		ctx,
 808  	SecCertificateRef 	secCert, 
 809  	bool                replaceAnchors)
 810  {
 811  	OSStatus ortn;
 812  	CFMutableArrayRef array;
 813  	
 814  	if(secCert == NULL) {
 815  		printf("***addTrustedSecCert screwup\n");
 816  		return errSecParam;
 817  	}
 818  	array = CFArrayCreateMutable(kCFAllocatorDefault,
 819  		(CFIndex)1, &kCFTypeArrayCallBacks);
 820  	if(array == NULL) {
 821  		return errSecAllocate;	
 822  	}
 823  	CFArrayAppendValue(array, secCert);
 824  	ortn = SSLSetTrustedRoots(ctx, array, replaceAnchors ? true : false);
 825  	if(ortn) {
 826  		printSslErrStr("SSLSetTrustedRoots", ortn);
 827  	}
 828  	CFRelease(array);
 829  	return ortn;
 830  }
 831  
 832  #pragma clang diagnostic pop
 833  
 834  OSStatus sslAddTrustedRoot(
 835  	SSLContextRef 	ctx,
 836  	const char 		*anchorFile, 
 837  	bool            replaceAnchors)
 838  {
 839  	return 0;
 840  }
 841  
 842  OSStatus addIdentityAsTrustedRoot(
 843  	SSLContextRef 	ctx,
 844  	CFArrayRef		identArray)
 845  {
 846  	return errSecSuccess;
 847  }   
 848  
 849  /*
 850   * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the 
 851   * SecureTransport library does not implement all of these; we only specify
 852   * the ones it claims to support.
 853   */
 854  const SSLCipherSuite suites40[] = {
 855  	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
 856  	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
 857  	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
 858  	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
 859  	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
 860  	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
 861  	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
 862  	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
 863  	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
 864  	SSL_NO_SUCH_CIPHERSUITE
 865  };
 866  const SSLCipherSuite suitesDES[] = {
 867  	SSL_RSA_WITH_DES_CBC_SHA,
 868  	SSL_DH_DSS_WITH_DES_CBC_SHA,
 869  	SSL_DH_RSA_WITH_DES_CBC_SHA,
 870  	SSL_DHE_DSS_WITH_DES_CBC_SHA,
 871  	SSL_DHE_RSA_WITH_DES_CBC_SHA,
 872  	SSL_DH_anon_WITH_DES_CBC_SHA,
 873  	SSL_RSA_WITH_DES_CBC_MD5,
 874  	SSL_NO_SUCH_CIPHERSUITE
 875  };
 876  const SSLCipherSuite suitesDES40[] = {
 877  	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
 878  	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
 879  	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
 880  	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
 881  	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
 882  	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
 883  	SSL_NO_SUCH_CIPHERSUITE
 884  };
 885  const SSLCipherSuite suites3DES[] = {
 886  	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
 887  	SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
 888  	SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
 889  	SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
 890  	SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
 891  	SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
 892  	SSL_RSA_WITH_3DES_EDE_CBC_MD5,
 893  	SSL_NO_SUCH_CIPHERSUITE
 894  };
 895  const SSLCipherSuite suitesRC4[] = {
 896  	SSL_RSA_WITH_RC4_128_MD5,
 897  	SSL_RSA_WITH_RC4_128_SHA,
 898  	SSL_DH_anon_WITH_RC4_128_MD5,
 899  	SSL_NO_SUCH_CIPHERSUITE
 900  };
 901  const SSLCipherSuite suitesRC4_40[] = {
 902  	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
 903  	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
 904  	SSL_NO_SUCH_CIPHERSUITE
 905  };
 906  const SSLCipherSuite suitesRC2[] = {
 907  	SSL_RSA_WITH_RC2_CBC_MD5,
 908  	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
 909  	SSL_NO_SUCH_CIPHERSUITE
 910  };
 911  const SSLCipherSuite suitesAES128[] = {
 912  	TLS_RSA_WITH_AES_128_CBC_SHA,
 913  	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
 914  	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
 915  	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
 916  	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
 917  	TLS_DH_anon_WITH_AES_128_CBC_SHA,
 918      SSL_NO_SUCH_CIPHERSUITE
 919  };
 920  const SSLCipherSuite suitesAES256[] = {
 921  	TLS_RSA_WITH_AES_256_CBC_SHA,
 922  	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
 923  	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
 924  	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
 925  	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
 926  	TLS_DH_anon_WITH_AES_256_CBC_SHA,
 927      SSL_NO_SUCH_CIPHERSUITE
 928  };
 929  const SSLCipherSuite suitesDH[] = {
 930      SSL_DH_DSS_WITH_DES_CBC_SHA,
 931      SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
 932      SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
 933      SSL_DH_RSA_WITH_DES_CBC_SHA,
 934      SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
 935      SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
 936      SSL_DHE_DSS_WITH_DES_CBC_SHA,
 937      SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
 938      SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
 939      SSL_DHE_RSA_WITH_DES_CBC_SHA,
 940      SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
 941      SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
 942      SSL_DH_anon_WITH_RC4_128_MD5,
 943      SSL_DH_anon_WITH_DES_CBC_SHA,
 944      SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
 945      SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
 946      SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
 947  	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
 948  	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
 949  	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
 950  	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
 951  	TLS_DH_anon_WITH_AES_128_CBC_SHA,
 952  	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
 953  	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
 954  	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
 955  	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
 956  	TLS_DH_anon_WITH_AES_256_CBC_SHA,
 957  	SSL_NO_SUCH_CIPHERSUITE
 958  };
 959  const SSLCipherSuite suitesDHAnon[] = {
 960      SSL_DH_anon_WITH_RC4_128_MD5,
 961      SSL_DH_anon_WITH_DES_CBC_SHA,
 962      SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
 963      SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
 964      SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
 965  	TLS_DH_anon_WITH_AES_128_CBC_SHA,
 966  	TLS_DH_anon_WITH_AES_256_CBC_SHA,
 967  	SSL_NO_SUCH_CIPHERSUITE
 968  };
 969  const SSLCipherSuite suitesDH_RSA[] = {
 970      SSL_DH_RSA_WITH_DES_CBC_SHA,
 971      SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
 972      SSL_DHE_RSA_WITH_DES_CBC_SHA,
 973      SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
 974      SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
 975      SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
 976  	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
 977  	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
 978  	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
 979  	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
 980  	SSL_NO_SUCH_CIPHERSUITE
 981  };
 982  const SSLCipherSuite suitesDH_DSS[] = {
 983      SSL_DH_DSS_WITH_DES_CBC_SHA,
 984      SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
 985      SSL_DHE_DSS_WITH_DES_CBC_SHA,
 986      SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
 987      SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
 988      SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
 989  	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
 990  	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
 991  	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
 992  	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
 993  	SSL_NO_SUCH_CIPHERSUITE
 994  };
 995  const SSLCipherSuite suites_SHA1[] = {
 996  	SSL_RSA_WITH_RC4_128_SHA,
 997  	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
 998  	SSL_RSA_WITH_IDEA_CBC_SHA,
 999  	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1000  	SSL_RSA_WITH_DES_CBC_SHA,
1001  	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
1002  	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1003  	SSL_DH_DSS_WITH_DES_CBC_SHA,
1004  	SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1005  	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1006  	SSL_DH_RSA_WITH_DES_CBC_SHA,
1007  	SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1008  	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1009  	SSL_DHE_DSS_WITH_DES_CBC_SHA,
1010  	SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1011  	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1012  	SSL_DHE_RSA_WITH_DES_CBC_SHA,
1013  	SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1014  	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1015  	SSL_DH_anon_WITH_DES_CBC_SHA,
1016  	SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1017  	SSL_FORTEZZA_DMS_WITH_NULL_SHA,
1018  	SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
1019  	TLS_RSA_WITH_AES_128_CBC_SHA,
1020  	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1021  	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1022  	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1023  	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1024  	TLS_DH_anon_WITH_AES_128_CBC_SHA,
1025  	TLS_RSA_WITH_AES_256_CBC_SHA,
1026  	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1027  	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1028  	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1029  	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1030  	TLS_DH_anon_WITH_AES_256_CBC_SHA,
1031  	SSL_NO_SUCH_CIPHERSUITE
1032  };
1033  const SSLCipherSuite suites_MD5[] = {
1034  	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
1035  	SSL_RSA_WITH_RC4_128_MD5,
1036  	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
1037  	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1038  	SSL_DH_anon_WITH_RC4_128_MD5,
1039  	SSL_NO_SUCH_CIPHERSUITE
1040  };
1041  
1042  
1043  /*
1044   * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1045   * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1046   * supports and do a SSLSetEnabledCiphers() specifying those. 
1047   */
1048  OSStatus sslSetEnabledCiphers(
1049  	SSLContextRef ctx,
1050  	const SSLCipherSuite *ciphers)
1051  {
1052  	size_t numSupported;
1053  	OSStatus ortn;
1054  	SSLCipherSuite *supported = NULL;
1055  	SSLCipherSuite *enabled = NULL;
1056  	unsigned enabledDex = 0;	// index into enabled
1057  	unsigned supportedDex = 0;	// index into supported
1058  	unsigned inDex = 0;			// index into ciphers
1059  	
1060  	/* first get all the supported ciphers */
1061  #pragma clang diagnostic push
1062  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1063  	ortn = SSLGetNumberSupportedCiphers(ctx, &numSupported);
1064  	if(ortn) {
1065  		printSslErrStr("SSLGetNumberSupportedCiphers", ortn);
1066  		return ortn;
1067  	}
1068  	supported = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1069  	ortn = SSLGetSupportedCiphers(ctx, supported, &numSupported);
1070  	if(ortn) {
1071  		printSslErrStr("SSLGetSupportedCiphers", ortn);
1072  		return ortn;
1073  	}
1074  	
1075  	/* 
1076  	 * Malloc an array we'll use for SSLGetEnabledCiphers - this will  be
1077  	 * bigger than the number of suites we actually specify 
1078  	 */
1079  	enabled = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1080  	
1081  	/* 
1082  	 * For each valid suite in ciphers, see if it's in the list of 
1083  	 * supported ciphers. If it is, add it to the list of ciphers to be
1084  	 * enabled. 
1085  	 */
1086  	for(inDex=0; ciphers[inDex] != SSL_NO_SUCH_CIPHERSUITE; inDex++) {
1087  		for(supportedDex=0; supportedDex<numSupported; supportedDex++) {
1088  			if(ciphers[inDex] == supported[supportedDex]) {
1089  				enabled[enabledDex++] = ciphers[inDex];
1090  				break;
1091  			}
1092  		}
1093  	}
1094  	
1095  	/* send it on down. */
1096  	ortn = SSLSetEnabledCiphers(ctx, enabled, enabledDex);
1097  	if(ortn) {
1098  		printSslErrStr("SSLSetEnabledCiphers", ortn);
1099  	}
1100  #pragma clang diagnostic pop
1101  	free(enabled);
1102  	free(supported);
1103  	return ortn;
1104  }
1105  
1106  /*
1107   * Specify a restricted set of cipherspecs.
1108   */
1109  OSStatus sslSetCipherRestrictions(
1110  	SSLContextRef ctx,
1111  	char cipherRestrict)
1112  {
1113  	OSStatus ortn;
1114  	
1115  	if(cipherRestrict == '\0') {
1116  		return errSecSuccess;		// actually should not have been called 
1117  	}
1118  	switch(cipherRestrict) {
1119  		case 'e':
1120  			ortn = sslSetEnabledCiphers(ctx, suites40);
1121  			break;
1122  		case 'd':
1123  			ortn = sslSetEnabledCiphers(ctx, suitesDES);
1124  			break;
1125  		case 'D':
1126  			ortn = sslSetEnabledCiphers(ctx, suitesDES40);
1127  			break;
1128  		case '3':
1129  			ortn = sslSetEnabledCiphers(ctx, suites3DES);
1130  			break;
1131  		case '4':
1132  			ortn = sslSetEnabledCiphers(ctx, suitesRC4);
1133  			break;
1134  		case '$':
1135  			ortn = sslSetEnabledCiphers(ctx, suitesRC4_40);
1136  			break;
1137  		case '2':
1138  			ortn = sslSetEnabledCiphers(ctx, suitesRC2);
1139  			break;
1140  		case 'a':
1141  			ortn = sslSetEnabledCiphers(ctx, suitesAES128);
1142  			break;
1143  		case 'A':
1144  			ortn = sslSetEnabledCiphers(ctx, suitesAES256);
1145  			break;
1146  		case 'h':
1147  			ortn = sslSetEnabledCiphers(ctx, suitesDH);
1148  			break;
1149  		case 'H':
1150  			ortn = sslSetEnabledCiphers(ctx, suitesDHAnon);
1151  			break;
1152  		case 'r':
1153  			ortn = sslSetEnabledCiphers(ctx, suitesDH_RSA);
1154  			break;
1155  		case 's':
1156  			ortn = sslSetEnabledCiphers(ctx, suitesDH_DSS);
1157  			break;
1158  		default:
1159  			printf("***bad cipherSpec***\n");
1160  			exit(1);
1161  	}
1162  	return ortn;
1163  }
1164  
1165  #if 0
1166  int sslVerifyClientCertState(
1167  	char						*whichSide,		// "client" or "server"
1168  	SSLClientCertificateState	expectState,
1169  	SSLClientCertificateState	gotState)
1170  {
1171  	if(expectState == SSL_CLIENT_CERT_IGNORE) {
1172  		/* app says "don't bopther checking" */
1173  		return 0;
1174  	}
1175  	if(expectState == gotState) {
1176  		return 0;
1177  	}
1178  	printf("***%s: Expected clientCertState %s; got %s\n", whichSide,
1179  		sslGetClientCertStateString(expectState),
1180  		sslGetClientCertStateString(gotState));
1181  	return 1;
1182  }
1183  
1184  int sslVerifyRtn(
1185  	char		*whichSide,		// "client" or "server"
1186  	OSStatus	expectRtn,
1187  	OSStatus	gotRtn)		
1188  {
1189  	if(expectRtn == gotRtn) {
1190  		return 0;
1191  	}
1192  	printf("***%s: Expected return %s; got %s\n", whichSide,
1193  		sslGetSSLErrString(expectRtn),
1194  		sslGetSSLErrString(gotRtn));
1195  	return 1;
1196  }
1197  
1198  int sslVerifyProtVers(
1199  	char		*whichSide,		// "client" or "server"
1200  	SSLProtocol	expectProt,
1201  	SSLProtocol	gotProt)		
1202  {
1203  	if(expectProt == SSL_PROTOCOL_IGNORE) {
1204  		/* app says "don't bopther checking" */
1205  		return 0;
1206  	}
1207  	if(expectProt == gotProt) {
1208  		return 0;
1209  	}
1210  	printf("***%s: Expected return %s; got %s\n", whichSide,
1211  		sslGetProtocolVersionString(expectProt),
1212  		sslGetProtocolVersionString(gotProt));
1213  	return 1;
1214  }
1215  
1216  int sslVerifyCipher(
1217  	char			*whichSide,		// "client" or "server"
1218  	SSLCipherSuite	expectCipher,
1219  	SSLCipherSuite	gotCipher)		
1220  {
1221  	if(expectCipher == SSL_CIPHER_IGNORE) {
1222  		/* app says "don't bopther checking" */
1223  		return 0;
1224  	}
1225  	if(expectCipher == gotCipher) {
1226  		return 0;
1227  	}
1228  	printf("***%s: Expected return %s; got %s\n", whichSide,
1229  		sslGetCipherSuiteString(expectCipher),
1230  		sslGetCipherSuiteString(gotCipher));
1231  	return 1;
1232  }
1233  
1234  
1235  OSStatus sslSetProtocols(
1236  	SSLContextRef 	ctx,
1237  	const char		*acceptedProts,
1238  	SSLProtocol		tryVersion)			// only used if acceptedProts NULL
1239  {
1240  	OSStatus ortn;
1241  	
1242  	if(acceptedProts) {
1243  		#if JAGUAR_BUILD
1244  		printf("***SSLSetProtocolVersionEnabled not supported in this config.\n");
1245  		exit(1);
1246  		#endif
1247  		ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
1248  		if(ortn) {
1249  			printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
1250  			return ortn;
1251  		}
1252  		for(const char *cp = acceptedProts; *cp; cp++) {
1253  			SSLProtocol prot;
1254  			switch(*cp) {
1255  				case '2':
1256  					prot = kSSLProtocol2;
1257  					break;
1258  				case '3':
1259  					prot = kSSLProtocol3;
1260  					break;
1261  				case 't':
1262  					prot = kTLSProtocol1;
1263  					break;
1264  				default:
1265  					printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts);
1266  					exit(1);
1267  			}
1268  			ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
1269  			if(ortn) {
1270  				printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
1271  				return ortn;
1272  			}
1273  		}
1274  	}
1275  	else {
1276  		ortn = SSLSetProtocolVersion(ctx, tryVersion);
1277  		if(ortn) {
1278  			printSslErrStr("SSLSetProtocolVersion", ortn);
1279  			return ortn;
1280  		} 
1281  	}
1282  	return errSecSuccess;
1283  }
1284  
1285  void sslShowResult(
1286  	char				*whichSide,		// "client" or "server"
1287  	SslAppTestParams	*params)
1288  {
1289  	printf("%s status:\n", whichSide);
1290  	if(params->acceptedProts) {
1291  		printf("   Allowed SSL versions   : %s\n", params->acceptedProts);
1292  	}
1293  	else {
1294  		printf("   Attempted  SSL version : %s\n", 
1295  			sslGetProtocolVersionString(params->tryVersion));
1296  	}
1297  	printf("   Result                 : %s\n", sslGetSSLErrString(params->ortn));
1298  	printf("   Negotiated SSL version : %s\n", 
1299  		sslGetProtocolVersionString(params->negVersion));
1300  	printf("   Negotiated CipherSuite : %s\n",
1301  		sslGetCipherSuiteString(params->negCipher));
1302  	if(params->certState != kSSLClientCertNone) {
1303  		printf("   Client Cert State      : %s\n",
1304  			sslGetClientCertStateString(params->certState));
1305  	}
1306  }
1307  #endif
1308  
1309  /* print a '.' every few seconds to keep UI alive while connecting */
1310  static time_t lastTime = (time_t)0;
1311  #define TIME_INTERVAL		3
1312  
1313  void sslOutputDot()
1314  {
1315  	time_t thisTime = time(0);
1316  	
1317  	if((thisTime - lastTime) >= TIME_INTERVAL) {
1318  		printf("."); fflush(stdout);
1319  		lastTime = thisTime;
1320  	}
1321  }
1322  
1323  #if 0
1324  /* main server pthread body */
1325  static void *sslServerThread(void *arg)
1326  {
1327  	SslAppTestParams *testParams = (SslAppTestParams *)arg;
1328  	OSStatus status;
1329  	
1330  	status = sslAppServe(testParams);
1331  	pthread_exit((void*)status);
1332  	/* NOT REACHED */
1333  	return (void *)status;
1334  }
1335  
1336  /*
1337   * Run one session, with the server in a separate thread.
1338   * On entry, serverParams->port is the port we attempt to run on;
1339   * the server thread may overwrite that with a different port if it's 
1340   * unable to open the port we specify. Whatever is left in 
1341   * serverParams->port is what's used for the client side. 
1342   */
1343  #define CLIENT_WAIT_SECONDS		1
1344  int sslRunSession(
1345  	SslAppTestParams*serverParams,
1346  	SslAppTestParams *clientParams,
1347  	const char 		*testDesc)
1348  {
1349  	pthread_t serverPthread;
1350  	OSStatus clientRtn;
1351  	void *serverRtn;
1352  	
1353  	if(testDesc && !clientParams->quiet) {
1354  		printf("===== %s =====\n", testDesc);
1355  	}
1356  	
1357  	if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) {
1358  		printf("***Error initializing mutex; aborting.\n");
1359  		return -1;
1360  	}
1361  	if(pthread_cond_init(&serverParams->pthreadCond, NULL)) {
1362  		printf("***Error initializing pthreadCond; aborting.\n");
1363  		return -1;
1364  	}
1365  	serverParams->serverReady = false;		// server sets true
1366  	
1367  	int result = pthread_create(&serverPthread, NULL, 
1368  			sslServerThread, serverParams);
1369  	if(result) {
1370  		printf("***Error starting up server thread; aborting.\n");
1371  		return result;
1372  	}
1373  	
1374  	/* wait for server to set up a socket we can connect to */
1375  	if(pthread_mutex_lock(&serverParams->pthreadMutex)) {
1376  		printf("***Error acquiring server lock; aborting.\n");
1377  		return -1;
1378  	}
1379  	while(!serverParams->serverReady) {
1380  		if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) {
1381  			printf("***Error waiting server thread; aborting.\n");
1382  			return -1;
1383  		}
1384  	}
1385  	pthread_mutex_unlock(&serverParams->pthreadMutex);
1386  	pthread_cond_destroy(&serverParams->pthreadCond);
1387  	pthread_mutex_destroy(&serverParams->pthreadMutex);
1388  	
1389  	clientParams->port = serverParams->port;
1390  	clientRtn = sslAppClient(clientParams);
1391  	/* server doesn't shut down its socket until it sees this */
1392  	serverParams->clientDone = 1;
1393  	result = pthread_join(serverPthread, &serverRtn);
1394  	if(result) {
1395  		printf("***pthread_join returned %d, aborting\n", result);
1396  		return result;
1397  	}
1398  	
1399  	if(serverParams->verbose) {
1400  		sslShowResult("server", serverParams);
1401  	}
1402  	if(clientParams->verbose) {
1403  		sslShowResult("client", clientParams);
1404  	}
1405  	
1406  	/* verify results */
1407  	int ourRtn = 0;
1408  	ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn);
1409  	ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn);
1410  	ourRtn += sslVerifyProtVers("server", serverParams->expectVersion, 
1411  		serverParams->negVersion);
1412  	ourRtn += sslVerifyProtVers("client", clientParams->expectVersion, 
1413  		clientParams->negVersion);
1414  	ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState, 
1415  		serverParams->certState);
1416  	ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState, 
1417  		clientParams->certState);
1418  	if(serverParams->ortn == errSecSuccess) {
1419  		ourRtn += sslVerifyCipher("server", serverParams->expectCipher, 
1420  			serverParams->negCipher);
1421  	}
1422  	if(clientParams->ortn == errSecSuccess) {
1423  		ourRtn += sslVerifyCipher("client", clientParams->expectCipher, 
1424  			clientParams->negCipher);
1425  	}
1426  	return ourRtn;
1427  }
1428  
1429  static bool isCertRoot(
1430  	SecCertificateRef cert)
1431  {
1432  	/* FIXME - per Radar 3247491, the Sec-level functions we'd like to use for this
1433  	 * haven't been written yet...
1434  	CSSM_X509_NAME subject;
1435  	CSSM_X509_NAME issuer;
1436  	OSStatus ortn;
1437  	... */
1438  	return true;
1439  }
1440  
1441  /*
1442   * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1443   */
1444  OSStatus sslAddTrustedRoots(
1445  	SSLContextRef 	ctx,
1446  	SecKeychainRef	keychain,
1447  	bool			*foundOne)		// RETURNED, true if we found 
1448  									//    at least one root cert
1449  {
1450  	OSStatus 				ortn;
1451  	SecCertificateRef 		secCert;
1452  	SecKeychainSearchRef 	srch;
1453  	
1454  	*foundOne = false;
1455  	ortn = SecKeychainSearchCreateFromAttributes(keychain,
1456  		kSecCertificateItemClass,
1457  		NULL,			// any attrs
1458  		&srch);
1459  	if(ortn) {
1460  		printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn);
1461  		return ortn;
1462  	}
1463  	
1464  	/*
1465  	 * Only use root certs. Not an error if we don't find any.
1466  	 */
1467  	do {
1468  		ortn = SecKeychainSearchCopyNext(srch, 
1469  			(SecKeychainItemRef *)&secCert);
1470  		if(ortn) {
1471  			break;
1472  		}
1473  		
1474  		/* see if it's a root */
1475  		if(!isCertRoot(secCert)) {
1476  			continue;
1477  		}
1478  		
1479  		/* Tell Secure Transport to trust this one. */
1480  		ortn = addTrustedSecCert(ctx, secCert, false);
1481  		if(ortn) {
1482  			/* fatal */
1483  			printSslErrStr("addTrustedSecCert", ortn);
1484  			return ortn;
1485  		}
1486  		CFRelease(secCert);
1487  		*foundOne = true;
1488  	} while(ortn == errSecSuccess);
1489  	CFRelease(srch);
1490  	return errSecSuccess;
1491  }
1492  
1493  /*
1494   * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1495   */
1496  OSStatus sslIdentityPicker(
1497  	SecKeychainRef		kcRef,			// NULL means use default list
1498  	const char			*trustedAnchor,	// optional additional trusted anchor
1499  	bool				includeRoot,	// true --> root is appended to outArray
1500  										// false --> root not included
1501  	CFArrayRef			*outArray)		// created and RETURNED
1502  {
1503  	SecCertificateRef trustedCert = NULL;
1504  	OSStatus ortn;
1505  	
1506  	if(trustedAnchor) { 
1507  		ortn = sslReadAnchor(trustedAnchor, &trustedCert);
1508  		if(ortn) {
1509  			printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1510  				trustedAnchor);
1511  			trustedCert = NULL;
1512  		}
1513  	}
1514  	ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, outArray);
1515  	if(trustedCert) {
1516  		CFRelease(trustedCert);
1517  	}
1518  	return ortn;
1519  }
1520  
1521  /*
1522   * Given a keychain name, convert it into a full path using the "SSL regression 
1523   * test suite algorithm". The Sec layer by default locates root root's keychains
1524   * in different places depending on whether we're actually logged in as root
1525   * or running via e.g. cron, so we force the location of root keychains to 
1526   * a hard-coded path. User keychain names we leave alone.
1527   */
1528  void sslKeychainPath(
1529  	const char *kcName,
1530  	char *kcPath)			// allocd by caller, MAXPATHLEN
1531  {
1532  	if(kcName[0] == '\0') {
1533  		kcPath[0] = '\0';
1534  	}
1535  	else if(geteuid() == 0) {
1536  		/* root */
1537  		sprintf(kcPath, "/Library/Keychains/%s", kcName);
1538  	}
1539  	else {
1540  		/* user, leave alone */
1541  		strcpy(kcPath, kcName);
1542  	}
1543  }
1544  
1545  /* Verify presence of required file. Returns nonzero if not found. */
1546  int sslCheckFile(const char *path)
1547  {
1548  	struct stat sb;
1549  
1550  	if(stat(path, &sb)) {
1551  		printf("***Can't find file %s.\n", path);
1552  		printf("   Try running in the build directory, perhaps after running the\n"
1553  			   "   makeLocalCert script.\n");
1554  		return 1;
1555  	}
1556  	return 0;
1557  }
1558  
1559  #endif
1560  
1561  /* Stringify a SSL_ECDSA_NamedCurve */
1562  extern const char *sslCurveString(
1563  	SSL_ECDSA_NamedCurve namedCurve)
1564  {
1565  	static char unk[100];
1566  
1567  	switch(namedCurve) {
1568  		case SSL_Curve_None:	  return "Curve_None";
1569  		case SSL_Curve_secp256r1: return "secp256r1";
1570  		case SSL_Curve_secp384r1: return "secp384r1";
1571  		case SSL_Curve_secp521r1: return "secp521r1";
1572  		default:
1573  			sprintf(unk, "Unknown <%d>", (int)namedCurve);
1574  			return unk;
1575  	}
1576  }
1577  
1578  
1579  
1580  
1581  #include <Security/SecCertificatePriv.h>
1582  #include <Security/SecKey.h>
1583  
1584  SecKeyRef create_private_key_from_der(bool ecdsa, const unsigned char *pkey_der, size_t pkey_der_len)
1585  {
1586      SecKeyRef privKey;
1587      CFErrorRef error = NULL;
1588      CFDataRef keyData = CFDataCreate(kCFAllocatorDefault, pkey_der, pkey_der_len);
1589      CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
1590      CFDictionarySetValue(parameters, kSecAttrKeyType, ecdsa?kSecAttrKeyTypeECSECPrimeRandom:kSecAttrKeyTypeRSA);
1591      CFDictionarySetValue(parameters, kSecAttrKeyClass, kSecAttrKeyClassPrivate);
1592      privKey = SecKeyCreateWithData(keyData, parameters, &error);
1593      CFReleaseNull(keyData);
1594      CFReleaseNull(parameters);
1595      CFReleaseNull(error);
1596      return privKey;
1597  }
1598  
1599  CFArrayRef chain_from_der(bool ecdsa, const unsigned char *pkey_der, size_t pkey_der_len, const unsigned char *cert_der, size_t cert_der_len)
1600  {
1601      SecKeyRef pkey = NULL;
1602      SecCertificateRef cert = NULL;
1603      SecIdentityRef ident = NULL;
1604      CFArrayRef items = NULL;
1605  
1606      require(pkey = create_private_key_from_der(ecdsa, pkey_der, pkey_der_len), errOut);
1607      require(cert = SecCertificateCreateWithBytes(kCFAllocatorDefault, cert_der, cert_der_len), errOut);
1608      require(ident = SecIdentityCreate(kCFAllocatorDefault, cert, pkey), errOut);
1609      require(items = CFArrayCreate(kCFAllocatorDefault, (const void **)&ident, 1, &kCFTypeArrayCallBacks), errOut);
1610  
1611  errOut:
1612      CFReleaseSafe(pkey);
1613      CFReleaseSafe(cert);
1614      CFReleaseSafe(ident);
1615      return items;
1616  }
1617