2 * Copyright (c) 2006-2008,2010-2012 Apple Inc. All Rights Reserved.
5 #include "sslAppUtils.h"
10 #include <Security/SecBase.h>
12 #include <CoreFoundation/CoreFoundation.h>
13 #include <Security/Security.h>
14 #include <Security/SecIdentityPriv.h>
15 #include <AssertMacros.h>
17 #define CFReleaseSafe(CF) { CFTypeRef _cf = (CF); if (_cf) CFRelease(_cf); }
19 const char *sslGetCipherSuiteString(SSLCipherSuite cs
)
21 static char noSuite
[40];
24 /* TLS cipher suites, RFC 2246 */
25 case SSL_NULL_WITH_NULL_NULL
: return "TLS_NULL_WITH_NULL_NULL";
26 case SSL_RSA_WITH_NULL_MD5
: return "TLS_RSA_WITH_NULL_MD5";
27 case SSL_RSA_WITH_NULL_SHA
: return "TLS_RSA_WITH_NULL_SHA";
28 case SSL_RSA_EXPORT_WITH_RC4_40_MD5
: return "TLS_RSA_EXPORT_WITH_RC4_40_MD5";
29 case SSL_RSA_WITH_RC4_128_MD5
: return "TLS_RSA_WITH_RC4_128_MD5";
30 case SSL_RSA_WITH_RC4_128_SHA
: return "TLS_RSA_WITH_RC4_128_SHA";
31 case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
: return "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
32 case SSL_RSA_WITH_IDEA_CBC_SHA
: return "TLS_RSA_WITH_IDEA_CBC_SHA";
33 case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
: return "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA";
34 case SSL_RSA_WITH_DES_CBC_SHA
: return "TLS_RSA_WITH_DES_CBC_SHA";
35 case SSL_RSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
36 case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
: return "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
37 case SSL_DH_DSS_WITH_DES_CBC_SHA
: return "TLS_DH_DSS_WITH_DES_CBC_SHA";
38 case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
: return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
39 case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
: return "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
40 case SSL_DH_RSA_WITH_DES_CBC_SHA
: return "TLS_DH_RSA_WITH_DES_CBC_SHA";
41 case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
42 case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
: return "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
43 case SSL_DHE_DSS_WITH_DES_CBC_SHA
: return "TLS_DHE_DSS_WITH_DES_CBC_SHA";
44 case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
: return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
45 case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
: return "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
46 case SSL_DHE_RSA_WITH_DES_CBC_SHA
: return "TLS_DHE_RSA_WITH_DES_CBC_SHA";
47 case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
48 case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
: return "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5";
49 case SSL_DH_anon_WITH_RC4_128_MD5
: return "TLS_DH_anon_WITH_RC4_128_MD5";
50 case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
: return "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
51 case SSL_DH_anon_WITH_DES_CBC_SHA
: return "TLS_DH_anon_WITH_DES_CBC_SHA";
52 case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
: return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
54 /* SSLv3 Fortezza cipher suites, from NSS */
55 case SSL_FORTEZZA_DMS_WITH_NULL_SHA
: return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
56 case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA
:return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
58 /* TLS addenda using AES-CBC, RFC 3268 */
59 case TLS_RSA_WITH_AES_128_CBC_SHA
: return "TLS_RSA_WITH_AES_128_CBC_SHA";
60 case TLS_DH_DSS_WITH_AES_128_CBC_SHA
: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
61 case TLS_DH_RSA_WITH_AES_128_CBC_SHA
: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
62 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA
: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
63 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA
: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
64 case TLS_DH_anon_WITH_AES_128_CBC_SHA
: return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
65 case TLS_RSA_WITH_AES_256_CBC_SHA
: return "TLS_RSA_WITH_AES_256_CBC_SHA";
66 case TLS_DH_DSS_WITH_AES_256_CBC_SHA
: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
67 case TLS_DH_RSA_WITH_AES_256_CBC_SHA
: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
68 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA
: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
69 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA
: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
70 case TLS_DH_anon_WITH_AES_256_CBC_SHA
: return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
72 /* ECDSA addenda, RFC 4492 */
73 case TLS_ECDH_ECDSA_WITH_NULL_SHA
: return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
74 case TLS_ECDH_ECDSA_WITH_RC4_128_SHA
: return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
75 case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
76 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
77 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
78 case TLS_ECDHE_ECDSA_WITH_NULL_SHA
: return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
79 case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
: return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
80 case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
81 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
82 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
83 case TLS_ECDH_RSA_WITH_NULL_SHA
: return "TLS_ECDH_RSA_WITH_NULL_SHA";
84 case TLS_ECDH_RSA_WITH_RC4_128_SHA
: return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
85 case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
86 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
87 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
88 case TLS_ECDHE_RSA_WITH_NULL_SHA
: return "TLS_ECDHE_RSA_WITH_NULL_SHA";
89 case TLS_ECDHE_RSA_WITH_RC4_128_SHA
: return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
90 case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
: return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
91 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
92 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
93 case TLS_ECDH_anon_WITH_NULL_SHA
: return "TLS_ECDH_anon_WITH_NULL_SHA";
94 case TLS_ECDH_anon_WITH_RC4_128_SHA
: return "TLS_ECDH_anon_WITH_RC4_128_SHA";
95 case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
: return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
96 case TLS_ECDH_anon_WITH_AES_128_CBC_SHA
: return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
97 case TLS_ECDH_anon_WITH_AES_256_CBC_SHA
: return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
99 /* TLS 1.2 addenda, RFC 5246 */
100 case TLS_RSA_WITH_AES_128_CBC_SHA256
: return "TLS_RSA_WITH_AES_128_CBC_SHA256";
101 case TLS_RSA_WITH_AES_256_CBC_SHA256
: return "TLS_RSA_WITH_AES_256_CBC_SHA256";
102 case TLS_DH_DSS_WITH_AES_128_CBC_SHA256
: return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
103 case TLS_DH_RSA_WITH_AES_128_CBC_SHA256
: return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
104 case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
: return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
105 case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
: return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
106 case TLS_DH_DSS_WITH_AES_256_CBC_SHA256
: return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
107 case TLS_DH_RSA_WITH_AES_256_CBC_SHA256
: return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
108 case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
: return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
109 case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
: return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
110 case TLS_DH_anon_WITH_AES_128_CBC_SHA256
: return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
111 case TLS_DH_anon_WITH_AES_256_CBC_SHA256
: return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
113 /* TLS addenda using AES-GCM, RFC 5288 */
114 case TLS_RSA_WITH_AES_128_GCM_SHA256
: return "TLS_RSA_WITH_AES_128_GCM_SHA256";
115 case TLS_RSA_WITH_AES_256_GCM_SHA384
: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
116 case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
: return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
117 case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
: return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
118 case TLS_DH_RSA_WITH_AES_128_GCM_SHA256
: return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
119 case TLS_DH_RSA_WITH_AES_256_GCM_SHA384
: return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
120 case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
: return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
121 case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
: return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
122 case TLS_DH_DSS_WITH_AES_128_GCM_SHA256
: return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
123 case TLS_DH_DSS_WITH_AES_256_GCM_SHA384
: return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
124 case TLS_DH_anon_WITH_AES_128_GCM_SHA256
: return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
125 case TLS_DH_anon_WITH_AES_256_GCM_SHA384
: return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
127 /* ECDSA addenda, RFC 5289 */
128 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
: return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
129 case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
: return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
130 case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
: return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
131 case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
: return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
132 case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
: return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
133 case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
: return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
134 case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
: return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
135 case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
: return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
136 case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
: return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
137 case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
: return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
138 case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
: return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
139 case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
: return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
140 case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
: return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
141 case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
: return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
142 case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
: return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
143 case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
: return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
146 * Tags for SSL 2 cipher kinds which are not specified for SSL 3.
148 case SSL_RSA_WITH_RC2_CBC_MD5
: return "TLS_RSA_WITH_RC2_CBC_MD5";
149 case SSL_RSA_WITH_IDEA_CBC_MD5
: return "TLS_RSA_WITH_IDEA_CBC_MD5";
150 case SSL_RSA_WITH_DES_CBC_MD5
: return "TLS_RSA_WITH_DES_CBC_MD5";
151 case SSL_RSA_WITH_3DES_EDE_CBC_MD5
: return "TLS_RSA_WITH_3DES_EDE_CBC_MD5";
152 case SSL_NO_SUCH_CIPHERSUITE
: return "SSL_NO_SUCH_CIPHERSUITE";
155 sprintf(noSuite
, "Unknown (0x%04X)", (unsigned)cs
);
161 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
162 * return a string representation.
164 const char *sslGetProtocolVersionString(SSLProtocol prot
)
166 static char noProt
[20];
169 case kSSLProtocolUnknown
: return "kSSLProtocolUnknown";
170 case kSSLProtocol2
: return "kSSLProtocol2";
171 case kSSLProtocol3
: return "kSSLProtocol3";
172 case kSSLProtocol3Only
: return "kSSLProtocol3Only";
173 case kTLSProtocol1
: return "kTLSProtocol1";
174 case kTLSProtocol1Only
: return "kTLSProtocol1Only";
175 case kTLSProtocol11
: return "kTLSProtocol11";
176 case kTLSProtocol12
: return "kTLSProtocol12";
178 sprintf(noProt
, "Unknown (%d)", (unsigned)prot
);
184 * Return string representation of SecureTransport-related OSStatus.
186 const char *sslGetSSLErrString(OSStatus err
)
188 static char errSecSuccessStr
[20];
191 case errSecSuccess
: return "errSecSuccess";
192 case errSecAllocate
: return "errSecAllocate";
193 case errSecParam
: return "errSecParam";
194 case errSecUnimplemented
: return "errSecUnimplemented";
195 case errSecIO
: return "errSecIO";
196 case errSecBadReq
: return "errSecBadReq";
198 case errSSLProtocol
: return "errSSLProtocol";
199 case errSSLNegotiation
: return "errSSLNegotiation";
200 case errSSLFatalAlert
: return "errSSLFatalAlert";
201 case errSSLWouldBlock
: return "errSSLWouldBlock";
202 case errSSLSessionNotFound
: return "errSSLSessionNotFound";
203 case errSSLClosedGraceful
: return "errSSLClosedGraceful";
204 case errSSLClosedAbort
: return "errSSLClosedAbort";
205 case errSSLXCertChainInvalid
: return "errSSLXCertChainInvalid";
206 case errSSLBadCert
: return "errSSLBadCert";
207 case errSSLCrypto
: return "errSSLCrypto";
208 case errSSLInternal
: return "errSSLInternal";
209 case errSSLModuleAttach
: return "errSSLModuleAttach";
210 case errSSLUnknownRootCert
: return "errSSLUnknownRootCert";
211 case errSSLNoRootCert
: return "errSSLNoRootCert";
212 case errSSLCertExpired
: return "errSSLCertExpired";
213 case errSSLCertNotYetValid
: return "errSSLCertNotYetValid";
214 case errSSLClosedNoNotify
: return "errSSLClosedNoNotify";
215 case errSSLBufferOverflow
: return "errSSLBufferOverflow";
216 case errSSLBadCipherSuite
: return "errSSLBadCipherSuite";
217 /* TLS/Panther addenda */
218 case errSSLPeerUnexpectedMsg
: return "errSSLPeerUnexpectedMsg";
219 case errSSLPeerBadRecordMac
: return "errSSLPeerBadRecordMac";
220 case errSSLPeerDecryptionFail
: return "errSSLPeerDecryptionFail";
221 case errSSLPeerRecordOverflow
: return "errSSLPeerRecordOverflow";
222 case errSSLPeerDecompressFail
: return "errSSLPeerDecompressFail";
223 case errSSLPeerHandshakeFail
: return "errSSLPeerHandshakeFail";
224 case errSSLPeerBadCert
: return "errSSLPeerBadCert";
225 case errSSLPeerUnsupportedCert
: return "errSSLPeerUnsupportedCert";
226 case errSSLPeerCertRevoked
: return "errSSLPeerCertRevoked";
227 case errSSLPeerCertExpired
: return "errSSLPeerCertExpired";
228 case errSSLPeerCertUnknown
: return "errSSLPeerCertUnknown";
229 case errSSLIllegalParam
: return "errSSLIllegalParam";
230 case errSSLPeerUnknownCA
: return "errSSLPeerUnknownCA";
231 case errSSLPeerAccessDenied
: return "errSSLPeerAccessDenied";
232 case errSSLPeerDecodeError
: return "errSSLPeerDecodeError";
233 case errSSLPeerDecryptError
: return "errSSLPeerDecryptError";
234 case errSSLPeerExportRestriction
: return "errSSLPeerExportRestriction";
235 case errSSLPeerProtocolVersion
: return "errSSLPeerProtocolVersion";
236 case errSSLPeerInsufficientSecurity
:return "errSSLPeerInsufficientSecurity";
237 case errSSLPeerInternalError
: return "errSSLPeerInternalError";
238 case errSSLPeerUserCancelled
: return "errSSLPeerUserCancelled";
239 case errSSLPeerNoRenegotiation
: return "errSSLPeerNoRenegotiation";
240 case errSSLHostNameMismatch
: return "errSSLHostNameMismatch";
241 case errSSLConnectionRefused
: return "errSSLConnectionRefused";
242 case errSSLDecryptionFail
: return "errSSLDecryptionFail";
243 case errSSLBadRecordMac
: return "errSSLBadRecordMac";
244 case errSSLRecordOverflow
: return "errSSLRecordOverflow";
245 case errSSLBadConfiguration
: return "errSSLBadConfiguration";
247 /* some from the Sec layer */
248 case errSecNotAvailable
: return "errSecNotAvailable";
249 case errSecDuplicateItem
: return "errSecDuplicateItem";
250 case errSecItemNotFound
: return "errSecItemNotFound";
251 #if !TARGET_OS_IPHONE
252 case errSecReadOnly
: return "errSecReadOnly";
253 case errSecAuthFailed
: return "errSecAuthFailed";
254 case errSecNoSuchKeychain
: return "errSecNoSuchKeychain";
255 case errSecInvalidKeychain
: return "errSecInvalidKeychain";
256 case errSecNoSuchAttr
: return "errSecNoSuchAttr";
257 case errSecInvalidItemRef
: return "errSecInvalidItemRef";
258 case errSecInvalidSearchRef
: return "errSecInvalidSearchRef";
259 case errSecNoSuchClass
: return "errSecNoSuchClass";
260 case errSecNoDefaultKeychain
: return "errSecNoDefaultKeychain";
261 case errSecWrongSecVersion
: return "errSecWrongSecVersion";
262 case errSecInvalidTrustSettings
: return "errSecInvalidTrustSettings";
263 case errSecNoTrustSettings
: return "errSecNoTrustSettings";
267 if (err
< (CSSM_BASE_ERROR
+
268 (CSSM_ERRORCODE_MODULE_EXTENT
* 8)))
270 /* assume CSSM error */
271 return cssmErrToStr(err
);
276 sprintf(errSecSuccessStr
, "Unknown (%d)", (unsigned)err
);
277 return errSecSuccessStr
;
286 printf("*** %s: %s\n", op
, sslGetSSLErrString(err
));
289 const char *sslGetClientCertStateString(SSLClientCertificateState state
)
291 static char noState
[20];
294 case kSSLClientCertNone
: return "ClientCertNone";
295 case kSSLClientCertRequested
: return "CertRequested";
296 case kSSLClientCertSent
: return "ClientCertSent";
297 case kSSLClientCertRejected
: return "ClientCertRejected";
299 sprintf(noState
, "Unknown (%d)", (unsigned)state
);
305 const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType
)
307 static char noType
[20];
310 case SSLClientAuthNone
: return "None";
311 case SSLClientAuth_RSASign
: return "RSASign";
312 case SSLClientAuth_DSSSign
: return "DSSSign";
313 case SSLClientAuth_RSAFixedDH
: return "RSAFixedDH";
314 case SSLClientAuth_DSS_FixedDH
: return "DSS_FixedDH";
315 case SSLClientAuth_ECDSASign
: return "ECDSASign";
316 case SSLClientAuth_RSAFixedECDH
: return "RSAFixedECDH";
317 case SSLClientAuth_ECDSAFixedECDH
: return "ECDSAFixedECDH";
319 sprintf(noType
, "Unknown (%d)", (unsigned)authType
);
325 * Convert a keychain name (which may be NULL) into the CFArrayRef required
326 * by SSLSetCertificate. This is a bare-bones example of this operation,
327 * since it requires and assumes that there is exactly one SecIdentity
328 * in the keychain - i.e., there is exactly one matching cert/private key
329 * pair. A real world server would probably search a keychain for a SecIdentity
330 * matching some specific criteria.
332 CFArrayRef
getSslCerts(
333 const char *kcName
, // may be NULL, i.e., use default
335 bool completeCertChain
,
336 const char *anchorFile
, // optional trusted anchor
337 SecKeychainRef
*pKcRef
) // RETURNED
340 SecKeychainRef kcRef
= nil
;
345 /* pick a keychain */
347 ortn
= SecKeychainOpen(kcName
, &kcRef
);
349 printf("SecKeychainOpen returned %d.\n", (int)ortn
);
350 printf("Cannot open keychain at %s. Aborting.\n", kcName
);
355 /* use default keychain */
356 ortn
= SecKeychainCopyDefault(&kcRef
);
358 printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn
);
363 return sslKcRefToCertArray(kcRef
, encryptOnly
, completeCertChain
, anchorFile
);
365 SecCertificateRef cert
= NULL
;
366 SecIdentityRef identity
= NULL
;
367 CFMutableArrayRef certificates
= NULL
, result
= NULL
;
368 CFMutableDictionaryRef certQuery
= NULL
, keyQuery
= NULL
, keyResult
= NULL
;
369 SecTrustRef trust
= NULL
;
370 SecKeyRef key
= NULL
;
371 CFTypeRef pkdigest
= NULL
;
373 // Find the first private key in the keychain and return both its
374 // attributes and a ref to it.
375 require(keyQuery
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
), errOut
);
376 CFDictionaryAddValue(keyQuery
, kSecClass
, kSecClassKey
);
377 CFDictionaryAddValue(keyQuery
, kSecAttrKeyClass
, kSecAttrKeyClassPrivate
);
378 CFDictionaryAddValue(keyQuery
, kSecReturnRef
, kCFBooleanTrue
);
379 CFDictionaryAddValue(keyQuery
, kSecReturnAttributes
, kCFBooleanTrue
);
380 require_noerr(SecItemCopyMatching(keyQuery
, (CFTypeRef
*)&keyResult
),
382 require(key
= (SecKeyRef
)CFDictionaryGetValue(keyResult
, kSecValueRef
),
384 require(pkdigest
= CFDictionaryGetValue(keyResult
, kSecAttrApplicationLabel
),
387 // Find the first certificate that has the same public key hash as the
388 // returned private key and return it as a ref.
389 require(certQuery
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
), errOut
);
390 CFDictionaryAddValue(certQuery
, kSecClass
, kSecClassCertificate
);
391 CFDictionaryAddValue(certQuery
, kSecAttrPublicKeyHash
, pkdigest
);
392 CFDictionaryAddValue(certQuery
, kSecReturnRef
, kCFBooleanTrue
);
393 require_noerr(SecItemCopyMatching(certQuery
, (CFTypeRef
*)&cert
), errOut
);
395 // Create an identity from the key and certificate.
396 require(identity
= SecIdentityCreate(NULL
, cert
, key
), errOut
);
398 // Build a (partial) certificate chain from cert
399 require(certificates
= CFArrayCreateMutable(NULL
, 0,
400 &kCFTypeArrayCallBacks
), errOut
);
401 CFArrayAppendValue(certificates
, cert
);
402 require_noerr(SecTrustCreateWithCertificates(certificates
, NULL
, &trust
),
404 SecTrustResultType tresult
;
405 require_noerr(SecTrustEvaluate(trust
, &tresult
), errOut
);
407 CFIndex certCount
, ix
;
408 // We need at least 1 certificate
409 require(certCount
= SecTrustGetCertificateCount(trust
), errOut
);
411 // Build a result where element 0 is the identity and the other elements
412 // are the certs in the chain starting at the first intermediate up to the
413 // anchor, if we found one, or as far as we were able to build the chain
415 require(result
= CFArrayCreateMutable(NULL
, certCount
, &kCFTypeArrayCallBacks
),
418 // We are commited to returning a result now, so do not use require below
419 // this line without setting result to NULL again.
420 CFArrayAppendValue(result
, identity
);
421 for (ix
= 1; ix
< certCount
; ++ix
) {
422 CFArrayAppendValue(result
, SecTrustGetCertificateAtIndex(trust
, ix
));
426 CFReleaseSafe(trust
);
427 CFReleaseSafe(certificates
);
428 CFReleaseSafe(identity
);
430 CFReleaseSafe(certQuery
);
431 CFReleaseSafe(keyResult
);
432 CFReleaseSafe(keyQuery
);
436 #else /* !TARGET_OS_IOS */
437 SecIdentityRef identity
= NULL
;
438 CFMutableDictionaryRef query
= NULL
;
439 CFArrayRef items
= NULL
;
440 require(query
= CFDictionaryCreateMutable(NULL
, 0, NULL
, NULL
), errOut
);
441 CFDictionaryAddValue(query
, kSecClass
, kSecClassIdentity
);
442 CFDictionaryAddValue(query
, kSecReturnRef
, kCFBooleanTrue
);
443 require_noerr(SecItemCopyMatching(query
, (CFTypeRef
*)&identity
), errOut
);
445 items
= CFArrayCreate(kCFAllocatorDefault
,
446 (const void **)&identity
, 1, &kCFTypeArrayCallBacks
);
449 CFReleaseSafe(identity
);
450 CFReleaseSafe(query
);
460 * Determine if specified SecCertificateRef is a self-signed cert.
461 * We do this by comparing the subject and issuerr names; no cryptographic
462 * verification is performed.
464 * Returns true if the cert appears to be a root.
466 static bool isCertRefRoot(
467 SecCertificateRef certRef
)
471 /* just search for the two attrs we want */
472 UInt32 tags
[2] = {kSecSubjectItemAttr
, kSecIssuerItemAttr
};
473 SecKeychainAttributeInfo attrInfo
;
476 attrInfo
.format
= NULL
;
477 SecKeychainAttributeList
*attrList
= NULL
;
478 SecKeychainAttribute
*attr1
= NULL
;
479 SecKeychainAttribute
*attr2
= NULL
;
481 OSStatus ortn
= SecKeychainItemCopyAttributesAndData(
482 (SecKeychainItemRef
)certRef
,
486 NULL
, // length - don't need the data
489 cssmPerror("SecKeychainItemCopyAttributesAndData", ortn
);
490 /* may want to be a bit more robust here, but this should
494 /* subsequent errors to errOut: */
496 if((attrList
== NULL
) || (attrList
->count
!= 2)) {
497 printf("***Unexpected result fetching label attr\n");
501 /* rootness is just byte-for-byte compare of the two names */
502 attr1
= &attrList
->attr
[0];
503 attr2
= &attrList
->attr
[1];
504 if(attr1
->length
== attr2
->length
) {
505 if(memcmp(attr1
->data
, attr2
->data
, attr1
->length
) == 0) {
510 SecKeychainItemFreeAttributesAndData(attrList
, NULL
);
518 * Given a SecIdentityRef, do our best to construct a complete, ordered, and
519 * verified cert chain, returning the result in a CFArrayRef. The result is
520 * suitable for use when calling SSLSetCertificate().
522 OSStatus
sslCompleteCertChain(
523 SecIdentityRef identity
,
524 SecCertificateRef trustedAnchor
, // optional additional trusted anchor
525 bool includeRoot
, // include the root in outArray
526 CFArrayRef
*outArray
) // created and RETURNED
528 CFMutableArrayRef certArray
;
529 SecTrustRef secTrust
= NULL
;
530 SecPolicyRef policy
= NULL
;
531 SecPolicySearchRef policySearch
= NULL
;
532 SecTrustResultType secTrustResult
;
533 CSSM_TP_APPLE_EVIDENCE_INFO
*dummyEv
; // not used
534 CFArrayRef certChain
= NULL
; // constructed chain
537 certArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
538 CFArrayAppendValue(certArray
, identity
);
541 * Case 1: identity is a root; we're done. Note that this case
542 * overrides the includeRoot argument.
544 SecCertificateRef certRef
;
545 OSStatus ortn
= SecIdentityCopyCertificate(identity
, &certRef
);
547 /* should never happen */
548 cssmPerror("SecIdentityCopyCertificate", ortn
);
551 bool isRoot
= isCertRefRoot(certRef
);
553 *outArray
= certArray
;
555 return errSecSuccess
;
559 * Now use SecTrust to get a complete cert chain, using all of the
560 * user's keychains to look for intermediate certs.
561 * NOTE this does NOT handle root certs which are not in the system
562 * root cert DB. (The above case, where the identity is a root cert, does.)
564 CFMutableArrayRef subjCerts
= CFArrayCreateMutable(NULL
, 1, &kCFTypeArrayCallBacks
);
565 CFArraySetValueAtIndex(subjCerts
, 0, certRef
);
567 /* the array owns the subject cert ref now */
570 /* Get a SecPolicyRef for generic X509 cert chain verification */
571 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
572 &CSSMOID_APPLE_X509_BASIC
,
576 cssmPerror("SecPolicySearchCreate", ortn
);
579 ortn
= SecPolicySearchCopyNext(policySearch
, &policy
);
581 cssmPerror("SecPolicySearchCopyNext", ortn
);
585 /* build a SecTrustRef for specified policy and certs */
586 ortn
= SecTrustCreateWithCertificates(subjCerts
,
589 cssmPerror("SecTrustCreateWithCertificates", ortn
);
595 * Tell SecTrust to trust this one in addition to the current
596 * trusted system-wide anchors.
598 CFMutableArrayRef newAnchors
;
599 CFArrayRef currAnchors
;
601 ortn
= SecTrustCopyAnchorCertificates(&currAnchors
);
603 /* should never happen */
604 cssmPerror("SecTrustCopyAnchorCertificates", ortn
);
607 newAnchors
= CFArrayCreateMutableCopy(NULL
,
608 CFArrayGetCount(currAnchors
) + 1,
610 CFRelease(currAnchors
);
611 CFArrayAppendValue(newAnchors
, trustedAnchor
);
612 ortn
= SecTrustSetAnchorCertificates(secTrust
, newAnchors
);
613 CFRelease(newAnchors
);
615 cssmPerror("SecTrustSetAnchorCertificates", ortn
);
620 ortn
= SecTrustEvaluate(secTrust
, &secTrustResult
);
622 cssmPerror("SecTrustEvaluate", ortn
);
625 switch(secTrustResult
) {
626 case kSecTrustResultUnspecified
:
627 /* cert chain valid, no special UserTrust assignments */
628 case kSecTrustResultProceed
:
629 /* cert chain valid AND user explicitly trusts this */
633 * Cert chain construction failed.
634 * Just go with the single subject cert we were given.
636 printf("***Warning: could not construct completed cert chain\n");
637 ortn
= errSecSuccess
;
641 /* get resulting constructed cert chain */
642 ortn
= SecTrustGetResult(secTrust
, &secTrustResult
, &certChain
, &dummyEv
);
644 cssmPerror("SecTrustEvaluate", ortn
);
649 * Copy certs from constructed chain to our result array, skipping
650 * the leaf (which is already there, as a SecIdentityRef) and possibly
653 numResCerts
= CFArrayGetCount(certChain
);
654 if(numResCerts
< 2) {
656 * Can't happen: if subject was a root, we'd already have returned.
657 * If chain doesn't verify to a root, we'd have bailed after
658 * SecTrustEvaluate().
660 printf("***sslCompleteCertChain screwup: numResCerts %d\n",
662 ortn
= errSecSuccess
;
666 /* skip the last (root) cert) */
669 for(CFIndex dex
=1; dex
<numResCerts
; dex
++) {
670 certRef
= (SecCertificateRef
)CFArrayGetValueAtIndex(certChain
, dex
);
671 CFArrayAppendValue(certArray
, certRef
);
679 CFRelease(subjCerts
);
685 CFRelease(policySearch
);
687 *outArray
= certArray
;
693 * Given an open keychain, find a SecIdentityRef and munge it into
694 * a CFArrayRef required by SSLSetCertificate().
696 CFArrayRef
sslKcRefToCertArray(
697 SecKeychainRef kcRef
,
699 bool completeCertChain
,
700 const char *trustedAnchorFile
)
702 /* quick check to make sure the keychain exists */
703 SecKeychainStatus kcStat
;
704 OSStatus ortn
= SecKeychainGetStatus(kcRef
, &kcStat
);
706 printSslErrStr("SecKeychainGetStatus", ortn
);
707 printf("Can not open keychain. Aborting.\n");
712 * Search for "any" identity matching specified key use;
713 * in this app, we expect there to be exactly one.
715 SecIdentitySearchRef srchRef
= nil
;
716 ortn
= SecIdentitySearchCreate(kcRef
,
717 encryptOnly
? CSSM_KEYUSE_DECRYPT
: CSSM_KEYUSE_SIGN
,
720 printf("SecIdentitySearchCreate returned %d.\n", (int)ortn
);
721 printf("Cannot find signing key in keychain. Aborting.\n");
724 SecIdentityRef identity
= nil
;
725 ortn
= SecIdentitySearchCopyNext(srchRef
, &identity
);
727 printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn
);
728 printf("Cannot find signing key in keychain. Aborting.\n");
731 if(CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
732 printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
739 if(completeCertChain
) {
741 * Place it and the other certs needed to verify it -
742 * up to but not including the root - in a CFArray.
744 SecCertificateRef anchorCert
= NULL
;
745 if(trustedAnchorFile
) {
746 ortn
= sslReadAnchor(trustedAnchorFile
, &anchorCert
);
748 printf("***Error reading anchor file\n");
752 ortn
= sslCompleteCertChain(identity
, anchorCert
, false, &ca
);
754 CFRelease(anchorCert
);
759 /* simple case, just this one identity */
760 CFArrayRef ca
= CFArrayCreate(NULL
,
761 (const void **)&identity
,
765 printf("CFArrayCreate error\n");
772 OSStatus
addTrustedSecCert(
774 SecCertificateRef secCert
,
778 CFMutableArrayRef array
;
780 if(secCert
== NULL
) {
781 printf("***addTrustedSecCert screwup\n");
784 array
= CFArrayCreateMutable(kCFAllocatorDefault
,
785 (CFIndex
)1, &kCFTypeArrayCallBacks
);
787 return errSecAllocate
;
789 CFArrayAppendValue(array
, secCert
);
790 ortn
= SSLSetTrustedRoots(ctx
, array
, replaceAnchors
? true : false);
792 printSslErrStr("SSLSetTrustedRoots", ortn
);
798 OSStatus
sslReadAnchor(
799 const char *anchorFile
,
800 SecCertificateRef
*certRef
)
802 SecCertificateRef secCert
;
803 unsigned char *certData
;
807 if(readFile(anchorFile
, &certData
, &certLen
)) {
810 dataRef
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
,
811 (const UInt8
*)certData
, (CFIndex
)certLen
, kCFAllocatorNull
);
812 secCert
= SecCertificateCreateWithData(kCFAllocatorDefault
, dataRef
);
813 CFReleaseSafe(dataRef
);
816 printf("***SecCertificateCreateWithData returned NULL\n");
822 return errSecSuccess
;
825 OSStatus
sslAddTrustedRoot(
827 const char *anchorFile
,
832 SecCertificateRef secCert
;
834 ortn
= sslReadAnchor(anchorFile
, &secCert
);
836 printf("***Error reading %s. SSLSetTrustedRoots skipped.\n",
840 return addTrustedSecCert(ctx
, secCert
, replaceAnchors
);
847 /* Per 3537606 this is no longer necessary */
849 * Assume incoming identity contains a root (e.g., created by
850 * certtool) and add that cert to ST's trusted anchors. This
851 * enables ST's verify of the incoming chain to succeed without
852 * a kludgy "AllowAnyRoot" specification.
854 OSStatus
addIdentityAsTrustedRoot(
856 CFArrayRef identArray
)
858 CFIndex numItems
= CFArrayGetCount(identArray
);
860 printf("***addIdentityAsTrustedRoot: empty identArray\n");
864 /* Root should be the last item - could be identity, could be cert */
865 CFTypeRef theItem
= CFArrayGetValueAtIndex(identArray
, numItems
- 1);
866 if(CFGetTypeID(theItem
) == SecIdentityGetTypeID()) {
868 SecCertificateRef certRef
;
869 OSStatus ortn
= SecIdentityCopyCertificate(
870 (SecIdentityRef
)theItem
, &certRef
);
872 cssmPerror("SecIdentityCopyCertificate", ortn
);
873 printf("***Error gettting cert from identity\n");
876 ortn
= addTrustedSecCert(ctx
, certRef
, false);
880 else if(CFGetTypeID(theItem
) == SecCertificateGetTypeID()) {
882 return addTrustedSecCert(ctx
, (SecCertificateRef
)theItem
, false);
885 printf("***Bogus item in identity array\n");
890 OSStatus
addIdentityAsTrustedRoot(
892 CFArrayRef identArray
)
894 return errSecSuccess
;
899 * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the
900 * SecureTransport library does not implement all of these; we only specify
901 * the ones it claims to support.
903 const SSLCipherSuite suites40
[] = {
904 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
905 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
906 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
907 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
908 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
909 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
910 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
911 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
912 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
913 SSL_NO_SUCH_CIPHERSUITE
915 const SSLCipherSuite suitesDES
[] = {
916 SSL_RSA_WITH_DES_CBC_SHA
,
917 SSL_DH_DSS_WITH_DES_CBC_SHA
,
918 SSL_DH_RSA_WITH_DES_CBC_SHA
,
919 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
920 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
921 SSL_DH_anon_WITH_DES_CBC_SHA
,
922 SSL_RSA_WITH_DES_CBC_MD5
,
923 SSL_NO_SUCH_CIPHERSUITE
925 const SSLCipherSuite suitesDES40
[] = {
926 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
927 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
928 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
929 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
930 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
931 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
932 SSL_NO_SUCH_CIPHERSUITE
934 const SSLCipherSuite suites3DES
[] = {
935 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
936 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
937 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
938 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
939 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
940 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
941 SSL_RSA_WITH_3DES_EDE_CBC_MD5
,
942 SSL_NO_SUCH_CIPHERSUITE
944 const SSLCipherSuite suitesRC4
[] = {
945 SSL_RSA_WITH_RC4_128_MD5
,
946 SSL_RSA_WITH_RC4_128_SHA
,
947 SSL_DH_anon_WITH_RC4_128_MD5
,
948 SSL_NO_SUCH_CIPHERSUITE
950 const SSLCipherSuite suitesRC4_40
[] = {
951 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
952 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
953 SSL_NO_SUCH_CIPHERSUITE
955 const SSLCipherSuite suitesRC2
[] = {
956 SSL_RSA_WITH_RC2_CBC_MD5
,
957 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
958 SSL_NO_SUCH_CIPHERSUITE
960 const SSLCipherSuite suitesAES128
[] = {
961 TLS_RSA_WITH_AES_128_CBC_SHA
,
962 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
963 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
964 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
965 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
966 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
967 SSL_NO_SUCH_CIPHERSUITE
969 const SSLCipherSuite suitesAES256
[] = {
970 TLS_RSA_WITH_AES_256_CBC_SHA
,
971 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
972 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
973 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
974 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
975 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
976 SSL_NO_SUCH_CIPHERSUITE
978 const SSLCipherSuite suitesDH
[] = {
979 SSL_DH_DSS_WITH_DES_CBC_SHA
,
980 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
981 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
982 SSL_DH_RSA_WITH_DES_CBC_SHA
,
983 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
984 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
985 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
986 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
987 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
988 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
989 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
990 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
991 SSL_DH_anon_WITH_RC4_128_MD5
,
992 SSL_DH_anon_WITH_DES_CBC_SHA
,
993 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
994 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
995 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
996 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
997 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
998 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
999 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1000 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1001 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1002 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1003 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1004 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1005 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1006 SSL_NO_SUCH_CIPHERSUITE
1008 const SSLCipherSuite suitesDHAnon
[] = {
1009 SSL_DH_anon_WITH_RC4_128_MD5
,
1010 SSL_DH_anon_WITH_DES_CBC_SHA
,
1011 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
1012 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
1013 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
1014 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1015 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1016 SSL_NO_SUCH_CIPHERSUITE
1018 const SSLCipherSuite suitesDH_RSA
[] = {
1019 SSL_DH_RSA_WITH_DES_CBC_SHA
,
1020 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
1021 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
1022 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1023 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1024 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1025 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
1026 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1027 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1028 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1029 SSL_NO_SUCH_CIPHERSUITE
1031 const SSLCipherSuite suitesDH_DSS
[] = {
1032 SSL_DH_DSS_WITH_DES_CBC_SHA
,
1033 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
1034 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
1035 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
1036 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1037 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1038 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
1039 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
1040 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1041 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1042 SSL_NO_SUCH_CIPHERSUITE
1044 const SSLCipherSuite suites_SHA1
[] = {
1045 SSL_RSA_WITH_RC4_128_SHA
,
1046 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1047 SSL_RSA_WITH_IDEA_CBC_SHA
,
1048 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1049 SSL_RSA_WITH_DES_CBC_SHA
,
1050 SSL_RSA_WITH_3DES_EDE_CBC_SHA
,
1051 SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1052 SSL_DH_DSS_WITH_DES_CBC_SHA
,
1053 SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA
,
1054 SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1055 SSL_DH_RSA_WITH_DES_CBC_SHA
,
1056 SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA
,
1057 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
,
1058 SSL_DHE_DSS_WITH_DES_CBC_SHA
,
1059 SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
1060 SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
,
1061 SSL_DHE_RSA_WITH_DES_CBC_SHA
,
1062 SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1063 SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA
,
1064 SSL_DH_anon_WITH_DES_CBC_SHA
,
1065 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA
,
1066 SSL_FORTEZZA_DMS_WITH_NULL_SHA
,
1067 SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA
,
1068 TLS_RSA_WITH_AES_128_CBC_SHA
,
1069 TLS_DH_DSS_WITH_AES_128_CBC_SHA
,
1070 TLS_DH_RSA_WITH_AES_128_CBC_SHA
,
1071 TLS_DHE_DSS_WITH_AES_128_CBC_SHA
,
1072 TLS_DHE_RSA_WITH_AES_128_CBC_SHA
,
1073 TLS_DH_anon_WITH_AES_128_CBC_SHA
,
1074 TLS_RSA_WITH_AES_256_CBC_SHA
,
1075 TLS_DH_DSS_WITH_AES_256_CBC_SHA
,
1076 TLS_DH_RSA_WITH_AES_256_CBC_SHA
,
1077 TLS_DHE_DSS_WITH_AES_256_CBC_SHA
,
1078 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
,
1079 TLS_DH_anon_WITH_AES_256_CBC_SHA
,
1080 SSL_NO_SUCH_CIPHERSUITE
1082 const SSLCipherSuite suites_MD5
[] = {
1083 SSL_RSA_EXPORT_WITH_RC4_40_MD5
,
1084 SSL_RSA_WITH_RC4_128_MD5
,
1085 SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
1086 SSL_DH_anon_EXPORT_WITH_RC4_40_MD5
,
1087 SSL_DH_anon_WITH_RC4_128_MD5
,
1088 SSL_NO_SUCH_CIPHERSUITE
1090 const SSLCipherSuite suites_NULL
[] = {
1091 SSL_RSA_WITH_NULL_MD5
,
1092 SSL_NO_SUCH_CIPHERSUITE
1095 const SSLCipherSuite suites_ECDHE
[] = {
1096 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
,
1097 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
,
1098 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
,
1099 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
,
1100 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
,
1101 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
,
1102 TLS_ECDHE_RSA_WITH_RC4_128_SHA
,
1103 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
,
1104 SSL_NO_SUCH_CIPHERSUITE
1107 const SSLCipherSuite suites_ECDH
[] = {
1108 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
,
1109 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
,
1110 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
1111 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
,
1112 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
,
1113 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
,
1114 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
1115 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
,
1116 SSL_NO_SUCH_CIPHERSUITE
1120 * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1121 * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1122 * supports and do a SSLSetEnabledCiphers() specifying those.
1124 OSStatus
sslSetEnabledCiphers(
1126 const SSLCipherSuite
*ciphers
)
1128 size_t numSupported
;
1130 SSLCipherSuite
*supported
= NULL
;
1131 SSLCipherSuite
*enabled
= NULL
;
1132 unsigned enabledDex
= 0; // index into enabled
1133 unsigned supportedDex
= 0; // index into supported
1134 unsigned inDex
= 0; // index into ciphers
1136 /* first get all the supported ciphers */
1137 ortn
= SSLGetNumberSupportedCiphers(ctx
, &numSupported
);
1139 printSslErrStr("SSLGetNumberSupportedCiphers", ortn
);
1142 supported
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1143 ortn
= SSLGetSupportedCiphers(ctx
, supported
, &numSupported
);
1145 printSslErrStr("SSLGetSupportedCiphers", ortn
);
1150 * Malloc an array we'll use for SSLGetEnabledCiphers - this will be
1151 * bigger than the number of suites we actually specify
1153 enabled
= (SSLCipherSuite
*)malloc(numSupported
* sizeof(SSLCipherSuite
));
1156 * For each valid suite in ciphers, see if it's in the list of
1157 * supported ciphers. If it is, add it to the list of ciphers to be
1160 for(inDex
=0; ciphers
[inDex
] != SSL_NO_SUCH_CIPHERSUITE
; inDex
++) {
1161 for(supportedDex
=0; supportedDex
<numSupported
; supportedDex
++) {
1162 if(ciphers
[inDex
] == supported
[supportedDex
]) {
1163 enabled
[enabledDex
++] = ciphers
[inDex
];
1169 /* send it on down. */
1170 ortn
= SSLSetEnabledCiphers(ctx
, enabled
, enabledDex
);
1172 printSslErrStr("SSLSetEnabledCiphers", ortn
);
1180 * Specify a restricted set of cipherspecs.
1182 OSStatus
sslSetCipherRestrictions(
1184 char cipherRestrict
)
1188 if(cipherRestrict
== '\0') {
1189 return errSecSuccess
; // actually should not have been called
1191 switch(cipherRestrict
) {
1193 ortn
= sslSetEnabledCiphers(ctx
, suites40
);
1196 ortn
= sslSetEnabledCiphers(ctx
, suitesDES
);
1199 ortn
= sslSetEnabledCiphers(ctx
, suitesDES40
);
1202 ortn
= sslSetEnabledCiphers(ctx
, suites3DES
);
1205 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4
);
1208 ortn
= sslSetEnabledCiphers(ctx
, suitesRC4_40
);
1211 ortn
= sslSetEnabledCiphers(ctx
, suitesRC2
);
1214 ortn
= sslSetEnabledCiphers(ctx
, suitesAES128
);
1217 ortn
= sslSetEnabledCiphers(ctx
, suitesAES256
);
1220 ortn
= sslSetEnabledCiphers(ctx
, suitesDH
);
1223 ortn
= sslSetEnabledCiphers(ctx
, suitesDHAnon
);
1226 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_RSA
);
1229 ortn
= sslSetEnabledCiphers(ctx
, suitesDH_DSS
);
1232 ortn
= sslSetEnabledCiphers(ctx
, suites_NULL
);
1235 ortn
= sslSetEnabledCiphers(ctx
, suites_ECDHE
);
1238 ortn
= sslSetEnabledCiphers(ctx
, suites_ECDH
);
1241 printf("***bad cipherSpec***\n");
1248 int sslVerifyClientCertState(
1249 const char *whichSide
, // "client" or "server"
1250 SSLClientCertificateState expectState
,
1251 SSLClientCertificateState gotState
)
1253 if(expectState
== SSL_CLIENT_CERT_IGNORE
) {
1254 /* app says "don't bother checking" */
1257 if(expectState
== gotState
) {
1260 printf("***%s: Expected clientCertState %s; got %s\n", whichSide
,
1261 sslGetClientCertStateString(expectState
),
1262 sslGetClientCertStateString(gotState
));
1267 char *whichSide
, // "client" or "server"
1271 if(expectRtn
== gotRtn
) {
1274 printf("***%s: Expected return %s; got %s\n", whichSide
,
1275 sslGetSSLErrString(expectRtn
),
1276 sslGetSSLErrString(gotRtn
));
1280 int sslVerifyProtVers(
1281 char *whichSide
, // "client" or "server"
1282 SSLProtocol expectProt
,
1283 SSLProtocol gotProt
)
1285 if(expectProt
== SSL_PROTOCOL_IGNORE
) {
1286 /* app says "don't bopther checking" */
1289 if(expectProt
== gotProt
) {
1292 printf("***%s: Expected return %s; got %s\n", whichSide
,
1293 sslGetProtocolVersionString(expectProt
),
1294 sslGetProtocolVersionString(gotProt
));
1298 int sslVerifyCipher(
1299 char *whichSide
, // "client" or "server"
1300 SSLCipherSuite expectCipher
,
1301 SSLCipherSuite gotCipher
)
1303 if(expectCipher
== SSL_CIPHER_IGNORE
) {
1304 /* app says "don't bopther checking" */
1307 if(expectCipher
== gotCipher
) {
1310 printf("***%s: Expected return %s; got %s\n", whichSide
,
1311 sslGetCipherSuiteString(expectCipher
),
1312 sslGetCipherSuiteString(gotCipher
));
1317 OSStatus
sslSetProtocols(
1319 const char *acceptedProts
,
1320 SSLProtocol tryVersion
) // only used if acceptedProts NULL
1325 ortn
= SSLSetProtocolVersionEnabled(ctx
, kSSLProtocolAll
, false);
1327 printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn
);
1330 for(const char *cp
= acceptedProts
; *cp
; cp
++) {
1334 prot
= kSSLProtocol2
;
1337 prot
= kSSLProtocol3
;
1340 prot
= kTLSProtocol1
;
1343 printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts
);
1346 ortn
= SSLSetProtocolVersionEnabled(ctx
, prot
, true);
1348 printSslErrStr("SSLSetProtocolVersionEnabled", ortn
);
1354 ortn
= SSLSetProtocolVersion(ctx
, tryVersion
);
1356 printSslErrStr("SSLSetProtocolVersion", ortn
);
1360 return errSecSuccess
;
1364 const char *whichSide
, // "client" or "server"
1365 SslAppTestParams
*params
)
1367 printf("%s status:\n", whichSide
);
1368 if(params
->acceptedProts
) {
1369 printf(" Allowed SSL versions : %s\n", params
->acceptedProts
);
1372 printf(" Attempted SSL version : %s\n",
1373 sslGetProtocolVersionString(params
->tryVersion
));
1375 printf(" Result : %s\n", sslGetSSLErrString(params
->ortn
));
1376 printf(" Negotiated SSL version : %s\n",
1377 sslGetProtocolVersionString(params
->negVersion
));
1378 printf(" Negotiated CipherSuite : %s\n",
1379 sslGetCipherSuiteString(params
->negCipher
));
1380 if(params
->certState
!= kSSLClientCertNone
) {
1381 printf(" Client Cert State : %s\n",
1382 sslGetClientCertStateString(params
->certState
));
1387 /* print a '.' every few seconds to keep UI alive while connecting */
1388 static CFAbsoluteTime lastTime
= (CFAbsoluteTime
)0.0;
1389 #define TIME_INTERVAL 3.0
1393 CFAbsoluteTime thisTime
= CFAbsoluteTimeGetCurrent();
1395 if(lastTime
== 0.0) {
1396 /* avoid printing first time thru */
1397 lastTime
= thisTime
;
1400 if((thisTime
- lastTime
) >= TIME_INTERVAL
) {
1401 printf("."); fflush(stdout
);
1402 lastTime
= thisTime
;
1407 /* main server pthread body */
1408 static void *sslServerThread(void *arg
)
1410 SslAppTestParams
*testParams
= (SslAppTestParams
*)arg
;
1413 status
= sslAppServe(testParams
);
1414 pthread_exit((void*)status
);
1416 return (void *)status
;
1420 * Run one session, with the server in a separate thread.
1421 * On entry, serverParams->port is the port we attempt to run on;
1422 * the server thread may overwrite that with a different port if it's
1423 * unable to open the port we specify. Whatever is left in
1424 * serverParams->port is what's used for the client side.
1426 #define CLIENT_WAIT_SECONDS 1
1428 SslAppTestParams
*serverParams
,
1429 SslAppTestParams
*clientParams
,
1430 const char *testDesc
)
1432 pthread_t serverPthread
;
1436 if(testDesc
&& !clientParams
->quiet
) {
1437 printf("===== %s =====\n", testDesc
);
1440 if(pthread_mutex_init(&serverParams
->pthreadMutex
, NULL
)) {
1441 printf("***Error initializing mutex; aborting.\n");
1444 if(pthread_cond_init(&serverParams
->pthreadCond
, NULL
)) {
1445 printf("***Error initializing pthreadCond; aborting.\n");
1448 serverParams
->serverReady
= false; // server sets true
1450 int result
= pthread_create(&serverPthread
, NULL
,
1451 sslServerThread
, serverParams
);
1453 printf("***Error starting up server thread; aborting.\n");
1457 /* wait for server to set up a socket we can connect to */
1458 if(pthread_mutex_lock(&serverParams
->pthreadMutex
)) {
1459 printf("***Error acquiring server lock; aborting.\n");
1462 while(!serverParams
->serverReady
) {
1463 if(pthread_cond_wait(&serverParams
->pthreadCond
, &serverParams
->pthreadMutex
)) {
1464 printf("***Error waiting server thread; aborting.\n");
1468 pthread_mutex_unlock(&serverParams
->pthreadMutex
);
1469 pthread_cond_destroy(&serverParams
->pthreadCond
);
1470 pthread_mutex_destroy(&serverParams
->pthreadMutex
);
1472 clientParams
->port
= serverParams
->port
;
1473 clientRtn
= sslAppClient(clientParams
);
1474 /* server doesn't shut down its socket until it sees this */
1475 serverParams
->clientDone
= 1;
1476 result
= pthread_join(serverPthread
, &serverRtn
);
1478 printf("***pthread_join returned %d, aborting\n", result
);
1482 if(serverParams
->verbose
) {
1483 sslShowResult("server", serverParams
);
1485 if(clientParams
->verbose
) {
1486 sslShowResult("client", clientParams
);
1489 /* verify results */
1491 ourRtn
+= sslVerifyRtn("server", serverParams
->expectRtn
, serverParams
->ortn
);
1492 ourRtn
+= sslVerifyRtn("client", clientParams
->expectRtn
, clientParams
->ortn
);
1493 ourRtn
+= sslVerifyProtVers("server", serverParams
->expectVersion
,
1494 serverParams
->negVersion
);
1495 ourRtn
+= sslVerifyProtVers("client", clientParams
->expectVersion
,
1496 clientParams
->negVersion
);
1497 ourRtn
+= sslVerifyClientCertState("server", serverParams
->expectCertState
,
1498 serverParams
->certState
);
1499 ourRtn
+= sslVerifyClientCertState("client", clientParams
->expectCertState
,
1500 clientParams
->certState
);
1501 if(serverParams
->ortn
== errSecSuccess
) {
1502 ourRtn
+= sslVerifyCipher("server", serverParams
->expectCipher
,
1503 serverParams
->negCipher
);
1505 if(clientParams
->ortn
== errSecSuccess
) {
1506 ourRtn
+= sslVerifyCipher("client", clientParams
->expectCipher
,
1507 clientParams
->negCipher
);
1513 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1515 OSStatus
sslAddTrustedRoots(
1517 SecKeychainRef keychain
,
1518 bool *foundOne
) // RETURNED, true if we found
1519 // at least one root cert
1522 SecCertificateRef secCert
;
1523 SecKeychainSearchRef srch
;
1526 ortn
= SecKeychainSearchCreateFromAttributes(keychain
,
1527 kSecCertificateItemClass
,
1531 printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn
);
1536 * Only use root certs. Not an error if we don't find any.
1539 ortn
= SecKeychainSearchCopyNext(srch
,
1540 (SecKeychainItemRef
*)&secCert
);
1545 /* see if it's a root */
1546 if(!isCertRoot(secCert
)) {
1550 /* Tell Secure Transport to trust this one. */
1551 ortn
= addTrustedSecCert(ctx
, secCert
, false);
1554 printSslErrStr("addTrustedSecCert", ortn
);
1559 } while(ortn
== errSecSuccess
);
1561 return errSecSuccess
;
1565 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1567 OSStatus
sslIdentityPicker(
1568 SecKeychainRef kcRef
, // NULL means use default list
1569 const char *trustedAnchor
, // optional additional trusted anchor
1570 bool includeRoot
, // true --> root is appended to outArray
1571 // false --> root not included
1572 CFArrayRef
*outArray
) // created and RETURNED
1574 SecCertificateRef trustedCert
= NULL
;
1578 ortn
= sslReadAnchor(trustedAnchor
, &trustedCert
);
1580 printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1585 ortn
= sslIdentPicker(kcRef
, trustedCert
, includeRoot
, outArray
);
1587 CFRelease(trustedCert
);
1593 * Given a keychain name, convert it into a full path using the "SSL regression
1594 * test suite algorithm". The Sec layer by default locates root root's keychains
1595 * in different places depending on whether we're actually logged in as root
1596 * or running via e.g. cron, so we force the location of root keychains to
1597 * a hard-coded path. User keychain names we leave alone.
1599 void sslKeychainPath(
1601 char *kcPath
) // allocd by caller, MAXPATHLEN
1603 if(kcName
[0] == '\0') {
1606 else if(geteuid() == 0) {
1608 sprintf(kcPath
, "/Library/Keychains/%s", kcName
);
1611 /* user, leave alone */
1612 strcpy(kcPath
, kcName
);
1616 /* Verify presence of required file. Returns nonzero if not found. */
1617 int sslCheckFile(const char *path
)
1621 if(stat(path
, &sb
)) {
1622 printf("***Can't find file %s.\n", path
);
1623 printf(" Try running in the build directory, perhaps after running the\n"
1624 " makeLocalCert script.\n");
1632 /* Stringify a SSL_ECDSA_NamedCurve */
1633 extern const char *sslCurveString(
1634 SSL_ECDSA_NamedCurve namedCurve
)
1636 static char unk
[100];
1638 switch(namedCurve
) {
1639 case SSL_Curve_None
: return "Curve_None";
1640 case SSL_Curve_secp256r1
: return "secp256r1";
1641 case SSL_Curve_secp384r1
: return "secp384r1";
1642 case SSL_Curve_secp521r1
: return "secp521r1";
1644 sprintf(unk
, "Unknown <%d>", (int)namedCurve
);