/* * Given raw RSA key bits, cook up a SSLPubKey. Used in * Server-initiated key exchange. */ OSStatus sslGetPubKeyFromBits( SSLContext *ctx, const SSLBuffer *modulus, const SSLBuffer *exponent, SSLPubKey **pubKey) // mallocd and RETURNED { if (!pubKey) return paramErr; #if 0 SSLPubKey *key; RSAStatus rsaStatus; RSAPubKey apiKey = { modulus->data, modulus->length, NULL, 0, exponent->data, exponent->length }; key = sslMalloc(sizeof(*key)); rsaStatus = rsaInitPubGKey(&apiKey, &key->rsaKey); if (rsaStatus) { sslFree(key); return rsaStatusToSSL(rsaStatus); } *pubKey = key; return noErr; #else check(pubKey); SecRSAPublicKeyParams params = { modulus->data, modulus->length, exponent->data, exponent->length }; #if SSL_DEBUG sslDebugLog("Creating RSA pub key from modulus=%p len=%lu exponent=%p len=%lu\n", (uintptr_t)modulus->data, modulus->length, (uintptr_t)exponent->data, exponent->length); #endif SecKeyRef key = SecKeyCreateRSAPublicKey(NULL, (const uint8_t *)¶ms, sizeof(params), kSecKeyEncodingRSAPublicParams); if (!key) { sslErrorLog("sslGetPubKeyFromBits: SecKeyCreateRSAPublicKey failed\n"); return errSSLCrypto; } #if SSL_DEBUG size_t blocksize = SecKeyGetBlockSize(key); sslDebugLog("sslGetPubKeyFromBits: RSA pub key block size=%lu\n", blocksize); #endif *pubKey = (SSLPubKey*)key; return noErr; #endif }
static int tls_handshake_advance_read_cipher_callback(tls_handshake_ctx_t ctx) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p\n", myCtx); return myCtx->recFuncs->advanceReadCipher(myCtx->recCtx); }
static int tls_handshake_rollback_write_callback(tls_handshake_ctx_t ctx) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p\n", myCtx); return myCtx->recFuncs->rollbackWriteCipher(myCtx->recCtx); }
static int tls_handshake_advance_write_callback(tls_handshake_ctx_t ctx) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p\n", myCtx); //FIXME: need to filter on cipher too - require missing coretls ciphersuite header */ bool split = (myCtx->oneByteRecordEnable && (myCtx->negProtocolVersion<=TLS_Version_1_0)); myCtx->recFuncs->setOption(myCtx->recCtx, kSSLRecordOptionSendOneByteRecord, split); return myCtx->recFuncs->advanceWriteCipher(myCtx->recCtx); }
static int tls_handshake_init_pending_cipher_callback(tls_handshake_ctx_t ctx, uint16_t selectedCipher, bool server, SSLBuffer key) { sslDebugLog("%p, cipher=%04x, server=%d\n", ctx, selectedCipher, server); SSLContext *myCtx = (SSLContext *)ctx; return myCtx->recFuncs->initPendingCiphers(myCtx->recCtx, selectedCipher, server, key); }
static int tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p\n", ctx); if(myCtx->cache) { tls_cache_empty(myCtx->cache); } return 0; }
static int tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey) { int err = errSSLSessionNotFound; SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p, key len=%zd k[0]=%02x\n", ctx, sessionKey.length, sessionKey.data[0]); if(myCtx->cache) { err = tls_cache_delete_session_data(myCtx->cache, &sessionKey); } return err; }
static int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p (rec.len=%zd, ct=%d, d[0]=%d)\n", myCtx, data.length, content_type, data.data[0]); SSLRecord rec; rec.contents=data; rec.contentType=content_type; return myCtx->recFuncs->write(myCtx->recCtx,rec); }
static int tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer sessionData) { int err = errSSLSessionNotFound; SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%s: %p, key len=%zd, k[0]=%02x, data len=%zd\n", __FUNCTION__, myCtx, sessionKey.length, sessionKey.data[0], sessionData.length); if(myCtx->cache) { err = tls_cache_save_session_data(myCtx->cache, &sessionKey, &sessionData, myCtx->sessionCacheTimeout); } return err; }
static int tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx, int attempt) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p attempt=%d\n", ctx, attempt); if(attempt) { myCtx->timeout_deadline = CFAbsoluteTimeGetCurrent()+((1<<(attempt-1))*myCtx->timeout_duration); } else { myCtx->timeout_deadline = 0; // cancel the timeout } return 0; }
static int tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer *sessionData) { SSLContext *myCtx = (SSLContext *)ctx; int err = errSSLSessionNotFound; SSLFreeBuffer(&myCtx->resumableSession); if(myCtx->cache) { err = tls_cache_load_session_data(myCtx->cache, &sessionKey, &myCtx->resumableSession); } sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx, sessionKey.length, sessionData->length, err); *sessionData = myCtx->resumableSession; return err; }
static void tls_handshake_ready_callback(tls_handshake_ctx_t ctx, bool write, bool ready) { SSLContext *myCtx = (SSLContext *)ctx; sslDebugLog("%p %s ready=%d\n", myCtx, write?"write":"read", ready); if(write) { myCtx->writeCipher_ready=ready?1:0; } else { myCtx->readCipher_ready=ready?1:0; if(ready) { SSLChangeHdskState(myCtx, SSL_HdskStateReady); } else { SSLChangeHdskState(myCtx, SSL_HdskStatePending); } } }
int tls_handshake_request_renegotiation(tls_handshake_t filter) { int err; if (filter->state != SSL_HdskStateServerReady) { sslDebugLog("Requesting renegotiation while handshake in progress..."); return errSSLIllegalParam; // TODO: better error code for this case. } require_noerr((err=SSLResetFlight(filter)), errOut); filter->hdskMessageSeq=0; require_noerr((err=SSLPrepareAndQueueMessage(SSLEncodeServerHelloRequest, tls_record_type_Handshake, filter)), errOut); require_noerr((err=SSLSendFlight(filter)), errOut); errOut: return err; }
/* (re)handshake */ int tls_handshake_negotiate(tls_handshake_t filter, tls_buffer *peerID) { assert(!filter->isServer); if ((filter->state != SSL_HdskStateClientReady) && (filter->state != SSL_HdskStateClientUninit)) { sslDebugLog("Requesting renegotiation while handshake in progress..."); return errSSLIllegalParam; // TODO: better error code for this case. } if(peerID) { check(filter->peerID.data==NULL); // Note sure that's illegal, but it's fishy filter->callbacks->load_session_data(filter->callback_ctx, *peerID, &filter->resumableSession); SSLFreeBuffer(&filter->peerID); SSLCopyBuffer(peerID, &filter->peerID); } else { SSLFreeBuffer(&filter->peerID); } return SSLAdvanceHandshake(SSL_HdskHelloRequest, filter); }
static int tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t event) { SSLContext *myCtx = (SSLContext *)ctx; const tls_buffer *npn_data; const tls_buffer *alpn_data; int err = 0; sslDebugLog("%p, message = %d\n", ctx, event); switch(event) { case tls_handshake_message_certificate_request: assert(myCtx->protocolSide == kSSLClientSide); // Need to call this here, in case SetCertificate was already called. myCtx->clientCertState = kSSLClientCertRequested; myCtx->clientAuthTypes = tls_handshake_get_peer_acceptable_client_auth_type(myCtx->hdsk, &myCtx->numAuthTypes); if (myCtx->breakOnCertRequest && (myCtx->localCertArray==NULL)) { myCtx->signalCertRequest = true; err = errSSLClientCertRequested; } break; case tls_handshake_message_client_hello: myCtx->peerSigAlgs = tls_handshake_get_peer_signature_algorithms(myCtx->hdsk, &myCtx->numPeerSigAlgs); if (myCtx->breakOnClientHello) { err = errSSLClientHelloReceived; } break; case tls_handshake_message_server_hello: myCtx->serverHelloReceived = true; alpn_data = tls_handshake_get_peer_alpn_data(myCtx->hdsk); if(alpn_data) { myCtx->alpnFunc(myCtx, myCtx->alpnFuncInfo, alpn_data->data, alpn_data->length); } else { npn_data = tls_handshake_get_peer_npn_data(myCtx->hdsk); if(npn_data) { myCtx->npnFunc(myCtx, myCtx->npnFuncInfo, npn_data->data, npn_data->length); } } myCtx->peerSigAlgs = tls_handshake_get_peer_signature_algorithms(myCtx->hdsk, &myCtx->numPeerSigAlgs); break; case tls_handshake_message_certificate: /* For clients, we only check the cert when we receive the ServerHelloDone message. For servers, we check the client's cert right here. For both we set the public key */ err = tls_helper_set_peer_pubkey(myCtx->hdsk); if(!err && (myCtx->protocolSide == kSSLServerSide)) { err = tls_verify_peer_cert(myCtx); } break; case tls_handshake_message_server_hello_done: err = tls_verify_peer_cert(myCtx); break; case tls_handshake_message_NPN_encrypted_extension: npn_data = tls_handshake_get_peer_npn_data(myCtx->hdsk); if(npn_data) myCtx->npnFunc(myCtx, myCtx->npnFuncInfo, npn_data->data, npn_data->length); break; case tls_handshake_message_certificate_status: break; default: break; } return err; }