/* * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved. * * The contents of this file constitute Original Code as defined in and are * subject to the Apple Public Source License Version 1.2 (the 'License'). * You may not use this file except in compliance with the License. Please obtain * a copy of the License at http://www.apple.com/publicsource and read it before * using this file. * * This Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the * specific language governing rights and limitations under the License. */ /* File: SecureTransport.h Contains: Public API for Apple SSL 3.0 Implementation Written by: Doug Mitchell Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved. */ #ifndef _SECURE_TRANSPORT_H_ #define _SECURE_TRANSPORT_H_ /* * Initial X port: no keychain storage of certs; no server mode, no * client-side authentication. */ #define ST_KEYCHAIN_ENABLE 0 #define ST_SERVER_MODE_ENABLE 0 #define ST_CLIENT_AUTHENTICATION 0 /* * This file describes the public API for an implementation of the * Secure Socket Layer, V. 3.0. This implementation is based on Netscape's * SSLRef 3.0, modified for Apple use. (Appropriate copyrights and * acknowledgements are found elsewhere, and in all files containing * Netscape code.) * * As in SSLRef 3.0, there no transport layer dependencies in this library; * it can be used with sockets, Open Transport, etc. Applications using * this library provide callback functions which do the actual I/O * on underlying network connections. Applications are also responsible * for setting up raw network connections; the application passes in * an opaque reference to the underlying (connected) entity at the * start of an SSL session. * * Some terminology: * * A "client" is the initiator of an SSL Session. The canonical example * of a client is a web browser, when it's talking to an https URL. * * A "server" is an entity which accepts requests for SSL sessions made * by clients. E.g., a secure web server. * An "SSL Session", or "session", is bounded by calls to SSLHandshake() * and SSLClose(). An "Active session" is in some state between these * two calls, inclusive. * * An SSL Session Context, or SSLContextRef, is an opaque reference in this * library to the state associated with one session. */ #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h> //#include <CoreServices/CoreServices.h> #include <CoreFoundation/CFData.h> #include <CoreFoundation/CFArray.h> #include <Security/CipherSuite.h> #if ST_KEYCHAIN_ENABLE #include <Keychain.h> #endif /* ST_KEYCHAIN_ENABLE */ #ifdef __cplusplus extern "C" { #endif /*********************** *** Common typedefs *** ***********************/ /* Opaque reference to an SSL session context */ struct SSLContext; typedef struct SSLContext *SSLContextRef; /* Opaque reference to an I/O conection (socket, Endpoint, etc.) */ typedef const void * SSLConnectionRef; /* SSL Protocol version */ typedef enum { kSSLProtocolUnknown, /* no protocol negotiated/specified */ kSSLProtocol2, /* SSL 2.0 only */ kSSLProtocol3, /* SSL 3.0 preferred, 2.0 OK if peer requires */ kSSLProtocol3Only /* use SSL 3.0 only, fail if peer tries to * negotiate 2.0 */ } SSLProtocol; /* State of an SSLSession */ typedef enum { kSSLIdle, /* no I/O performed yet */ kSSLHandshake, /* SSL handshake in progress */ kSSLConnected, /* Handshake complete, ready for normal I/O */ kSSLClosed, /* connection closed normally */ kSSLAborted /* connection aborted */ } SSLSessionState; /* * R/W functions. The application using this library provides * these functions via SSLSetIOFuncs(). * * Data's memory is allocated by caller; on entry to these two functions * the *length argument indicates both the size of the available data and the * requested byte count. Number of bytes actually transferred is returned in * *length. * * The application may configure the underlying connection to operate * in a non-blocking manner; in such a case, a read operation may * well return SSLWouldBlockErr, indicating "I transferred less data than * you requested (maybe even zero bytes), nothing is wrong, except * requested I/O hasn't completed". This will be returned back up to * the application as a return from SSLRead(), SSLWrite(), SSLHandshake(), * etc. */ typedef OSStatus (*SSLReadFunc) (SSLConnectionRef connection, void *data, /* owned by * caller, data * RETURNED */ UInt32 *dataLength); /* IN/OUT */ typedef OSStatus (*SSLWriteFunc) (SSLConnectionRef connection, const void *data, UInt32 *dataLength); /* IN/OUT */ /************************************************* *** OSStatus values unique to SecureTransport *** *************************************************/ enum { errSSLProtocol = -9800, /* SSL protocol error */ errSSLNegotiation = -9801, /* Cipher Suite negotiation failure */ errSSLFatalAlert = -9802, /* Fatal alert */ errSSLWouldBlock = -9803, /* I/O would block (not fatal) */ errSSLSessionNotFound = -9804, /* attempt to restore an unknown * session */ errSSLClosedGraceful = -9805, /* connection closed gracefully */ errSSLClosedAbort = -9806, /* connection closed via error */ errSSLXCertChainInvalid = -9807, /* Invalid certificate chain */ errSSLBadCert = -9808, /* bad certificate format */ errSSLCrypto = -9809, /* underlying cryptographic error */ errSSLInternal = -9810, /* Internal error */ errSSLModuleAttach = -9811, /* module attach failure */ errSSLUnknownRootCert = -9812, /* valid cert chain, untrusted root */ errSSLNoRootCert = -9813, /* cert chain not verified by root */ errSSLCertExpired = -9814, /* chain had an expired cert */ errSSLCertNotYetValid = -9815, /* chain had a cert not yet valid */ errSSLClosedNoNotify = -9816, /* server closed session with no * notification */ errSSLBufferOverflow = -9817, /* insufficient buffer provided */ errSSLBadCipherSuite = -9818, /* bad SSLCipherSuite */ errSSLLast = -9849 /* end of range, to be deleted */ }; /****************** *** Public API *** ******************/ /* * Create a new session context. */ OSStatus SSLNewContext (Boolean isServer, SSLContextRef *contextPtr); /* RETURNED */ /* * Dispose of an SSLContextRef. */ OSStatus SSLDisposeContext (SSLContextRef context); /* * Determine the state of an SSL session. */ OSStatus SSLGetSessionState (SSLContextRef context, SSLSessionState *state); /* RETURNED */ /******************************************************************** *** Session context configuration, common to client and servers. *** ********************************************************************/ /* * Specify functions which do the network I/O. Must be called prior * to SSLHandshake(); subsequently can not be called while a session is * active. */ OSStatus SSLSetIOFuncs (SSLContextRef context, SSLReadFunc read, SSLWriteFunc write); /* * Get/set SSL protocol version; optional. Default for client is is * kSSLProtocolUnknown (which works with whatever the server prefers); * default for server side is kSSLProtocol3 (which prefers SSL3 but * works with SSL2-only clients). * * SSLSetProtocolVersion can not be called when a session is active. */ OSStatus SSLSetProtocolVersion (SSLContextRef context, SSLProtocol version); OSStatus SSLGetProtocolVersion (SSLContextRef context, SSLProtocol *protocol); /* RETURNED */ #if (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION) /* * Specify this connection's certificate(s). This is mandatory for * server connections, optional for clients. Specifying a certificate * for a client enables SSL client-side authentication. The end-entity * cert is in certRef[0]. Specifying a root cert is optional; if it's * not specified, the root cert which verifies the cert chain specified * here must have been specified in SSLSetTrustedRootCertKC(). * * The certRefs argument is a CFArray containing KCItemRefs. * * Can only be called when no session is active. * * SecureTransport assumes the following: * * -- The certRef references remains valid for the lifetime of the * session. * -- The specified certRef[0] is capable of signing. * -- In order for a server connection to work with SSL3 protocol, * the private key associated with certRef[0] must ALSO be * capable of decryption. This is a workaround for a known * Netscape bug. */ OSStatus SSLSetCertificate (SSLContextRef context, CFArrayRef certRefs); #endif /* (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION) */ #if ST_KEYCHAIN_ENABLE /* * Specify a Keychain containing trusted root certificates. * Optional; the Keychain's root certs either are appended to or * replace the existing SSLContextRef's root certs, which are initialized * to a system-wide set of trusted roots at SSLContextAlloc(). * * Can not be called while a session is active. */ OSStatus SSLSetTrustedRootCertKC (SSLContextRef context, KCRef keyChainRef, Boolean deleteExisting); /* * Specify a Keychain (and access credentials for the keychain) * to which newly encountered root certs are attempted to be * added. This may or may not result in user interaction, depending * on the configuration of the keychain and of the specified * accesssCreds. * * Can not be called while a session is active and can only be * called a maximum of one time per SSLContextRef. */ OSStatus SSLSetNewRootKC (SSLContextRef context, KCRef keyChainRef, void *accessCreds); #endif /* ST_KEYCHAIN_ENABLE */ /* * Specify I/O connection - a socket, endpoint, etc., which is * managed by caller. On the client side, it's assumed that communication * has been established with the desired server on this connection. * On the server side, it's assumed that an incoming client request * has been established. * * Must be called prior to SSLHandshake(); subsequently can only be * called when no session is active. */ OSStatus SSLSetConnection (SSLContextRef context, SSLConnectionRef connection); /* * Obtain the actual negotiated protocol version of the active * session, which may be different that the value specified in * SSLSetProtocolVersion(). Returns kSSLProtocolUnknown if no * SSL session is in progress. */ OSStatus SSLGetNegotiatedProtocolVersion (SSLContextRef context, SSLProtocol *protocol); /* RETURNED */ /* * Determine number and values of all of the SSLCipherSuites we support. * Caller allocates output buffer for SSLGetSupportedCiphers() and passes in * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow * will be returned. */ OSStatus SSLGetNumberSupportedCiphers (SSLContextRef context, UInt32 *numCiphers); OSStatus SSLGetSupportedCiphers (SSLContextRef context, SSLCipherSuite *ciphers, /* RETURNED */ UInt32 *numCiphers); /* IN/OUT */ /* * Specify a (typlically) restricted set of SSLCipherSuites to be enabled by * the current SSLContext. Can only be called when no session is active. Default * set of enabled SSLCipherSuites is the same as the complete set of supported * SSLCipherSuites as obtained by SSLGetSupportedCiphers(). */ OSStatus SSLSetEnabledCiphers (SSLContextRef context, const SSLCipherSuite *ciphers, UInt32 numCiphers); /* * Determine number and values of all of the SSLCipherSuites currently enabled. * Caller allocates output buffer for SSLGetEnabledCiphers() and passes in * its size in *numCiphers. If supplied buffer is too small, errSSLBufferOverflow * will be returned. */ OSStatus SSLGetNumberEnabledCiphers (SSLContextRef context, UInt32 *numCiphers); OSStatus SSLGetEnabledCiphers (SSLContextRef context, SSLCipherSuite *ciphers, /* RETURNED */ UInt32 *numCiphers); /* IN/OUT */ /* * Specify the option of ignoring certificates' "expired" times. * This is a common failure in the real SSL world. Default for * this flag is false, meaning expired certs result in a * errSSLCertExpired error. */ OSStatus SSLSetAllowExpiredCerts (SSLContextRef context, Boolean allowExpired); /* * Obtain the current value of an SSLContext's "allowExpiredCerts" flag. */ OSStatus SSLGetAllowExpiredCerts (SSLContextRef context, Boolean *allowExpired); /* RETURNED */ /* * Specify option of allowing for an unknown root cert, i.e., one which * this software can not verify as one of a list of known good root certs. * Default for this flag is false, in which case one of the following two * errors may occur: * -- The peer returns a cert chain with a root cert, and the chain * verifies to that root, but the root is not one of our trusted * roots. This results in errSSLUnknownRootCert on handshake. * -- The peer returns a cert chain which does not contain a root cert, * and we can't verify the chain to one of our trusted roots. This * results in errSSLNoRootCert on handshake. * * Both of these error conditions are ignored when the AllowAnyRoot flag is true, * allowing connection to a totally untrusted peer. */ OSStatus SSLSetAllowAnyRoot (SSLContextRef context, Boolean anyRoot); /* * Obtain the current value of an SSLContext's "allow any root" flag. */ OSStatus SSLGetAllowAnyRoot (SSLContextRef context, Boolean *anyRoot); /* RETURNED */ /* * Request peer certificates. Valid anytime, subsequent to * a handshake attempt. * * The certs argument is a CFArray containing CFDataRefs, each * of which is one DER-encoded cert. The entire array is mallocd * by the SecureTransport library. The cert at the end of the * returned array is the subject (end entity) cert; the root cert * (or the closest cert to it) is in index 0 of the returned array. */ OSStatus SSLGetPeerCertificates (SSLContextRef context, CFArrayRef *certs); /* RETURNED */ /* * Specify some data, opaque to this library, which is sufficient * to uniquely identify the peer of the current session. An example * would be IP address and port, stored in some caller-private manner. * To be optionally called prior to SSLHandshake for the current * session. This is mandatory if this session is to be resumable. */ OSStatus SSLSetPeerID (SSLContextRef context, CFDataRef peerID); /* * Obtain the SSLCipherSuite (e.g., SSL_RSA_WITH_DES_CBC_SHA) negotiated * for this session. Only valid when a session is active. */ OSStatus SSLGetNegotiatedCipher (SSLContextRef context, SSLCipherSuite *cipherSuite); /******************************************************** *** Session context configuration, server side only. *** ********************************************************/ #if ST_SERVER_MODE_ENABLE /* * Specify this connection's encryption certificate(s). This is * used in one of the following cases: * * -- The end-entity certificate specified in SSLSetCertificate() is * not capable of encryption. (THIS REQUIREMENT IS OBSOLETE due * due a workaround for a Netscape bug.) * * -- The end-entity certificate specified in SSLSetCertificate() * contains a key which is too large (i.e., too strong) for legal * encryption in this session. In this case a weaker cert is * specified here and is used for server-initiated key exchange. * * -- Servers which establsh an SSL level 2 connection require * encryption certs. (SSL2 does not perform signing and verification, * only asymmetric encryption and decryption.) * * The encryptionCertRef argument is a CFArray containing * KCItemRefs. * * The following assumptions are made: * * -- The encryptionCertRef references remains valid for the lifetime of the * connection. * -- The specified encryptionCertRef[0] is capable of encryption. * * Can only be called when no session is active. * * Notes: * ------ * * -- SSL servers which enforce the SSL3 spec to the letter will * not accept encryption certs with key sizes larger than 512 * bits for exportable ciphers. Apps which wish to use encryption * certs with key sizes larger than 512 bits should disable the * use of exportable ciphers via the SSLSetExportEnable() call. */ OSStatus SSLSetEncryptionCertificate (SSLContextRef context, CFArrayRef certRefs); /* * Specify requirements for client-side authentication. * Optional; Default is kNeverAuthenticate, unless SSLSetTrustedRootCertKC * has been called, in which case the default is kTryAuthenticate. * * Can only be called when no session is active. */ typedef enum { kNeverAuthenticate, /* skip client authentication */ kAlwaysAuthenticate, /* require it */ kTryAuthenticate /* try to authenticate, but not an error * if client doesn't have a cert */ } SSLAuthenticate; OSStatus SSLSetClientSideAuthenticate (SSLContextRef context, SSLAuthenticate auth); #endif /* ST_SERVER_MODE_ENABLE */ /******************************* ******** I/O Functions ******** *******************************/ /* * Note: depending on the configuration of the underlying I/O * connection, all SSL I/O functions can return SSLWouldBlockErr, * indicating "not complete, nothing is wrong, except required * I/O hasn't completed". Caller may need to repeat I/Os as necessary * if the underlying connection has been configured to behave in * a non-blocking manner. */ /* * Perform the SSL handshake. On successful return, session is * ready for normal secure application I/O via SSLWrite and SSLRead. * * Interesting error returns: * * errSSLUnknownRootCert: Peer had a valid cert chain, but the root of * the chain is unknown. * * errSSLNoRootCert: Peer had a cert chain which was not verifiable * to a root cert. Handshake was aborted; peer's cert chain * available via SSLGetPeerCertificates(). * * errSSLCertExpired: Peer's cert chain had one or more expired certs. * * errSSLXCertChainInvalid: Peer had an invalid cert chain (i.e., * signature verification within the chain failed, or no certs * were found). * * In all of the above errors, the handshake was aborted; peer's * cert chain available via SSLGetPeerCertificates(). * * A return value of errSSLWouldBlock indicates that SSLHandshake has to be called * again (and again and again until something else is returned). */ OSStatus SSLHandshake (SSLContextRef context); /* * Normal application-level read/write. On both of these, a errSSLWouldBlock * return and a partially completed transfer - or even zero bytes transferred - * are NOT mutually exclusive. */ OSStatus SSLWrite (SSLContextRef context, const void * data, UInt32 dataLength, UInt32 *processed); /* RETURNED */ /* * data is mallocd by caller; available size specified in * dataLength; actual number of bytes read returned in * *processed. */ OSStatus SSLRead (SSLContextRef context, void * data, /* RETURNED */ UInt32 dataLength, UInt32 *processed); /* RETURNED */ /* * Terminate current SSL session. */ OSStatus SSLClose (SSLContextRef context); #ifdef __cplusplus } #endif #endif /* _SECURE_TRANSPORT_H_ */