X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_ssl/lib/sslCert.c diff --git a/libsecurity_ssl/lib/sslCert.c b/libsecurity_ssl/lib/sslCert.c deleted file mode 100644 index 4aee2efb..00000000 --- a/libsecurity_ssl/lib/sslCert.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The 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. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * sslCert.c - certificate request/verify messages - */ - -#include "ssl.h" -#include "sslContext.h" -#include "sslHandshake.h" -#include "sslMemory.h" -#include "sslAlertMessage.h" -#include "sslDebug.h" -#include "sslUtils.h" -#include "sslDigests.h" -#include "sslCrypto.h" - -#include -#include -#include -#include -#include -#include -#include "utilities/SecCFRelease.h" - - -OSStatus -SSLEncodeCertificate(SSLRecord *certificate, SSLContext *ctx) -{ OSStatus err; - size_t totalLength; - UInt8 *charPtr; - CFIndex i, certCount; -#ifdef USE_SSLCERTIFICATE - int j; - SSLCertificate *cert; -#else - CFArrayRef certChain; -#endif - int head; - - /* - * TBD: for client side, match Match DER-encoded acceptable DN list - * (ctx->acceptableDNList) to one of our certs. For now we just send - * what we have since we don't support multiple certs. - * - * Note this can be called with localCert==0 for client side in TLS1+ and DTLS; - * in that case we send an empty cert msg. - */ - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - assert((ctx->localCert != NULL) || (ctx->negProtocolVersion >= TLS_Version_1_0)); - totalLength = 0; - -#ifdef USE_SSLCERTIFICATE - certCount = 0; - cert = ctx->localCert; - while (cert) - { totalLength += 3 + cert->derCert.length; /* 3 for encoded length field */ - ++certCount; - cert = cert->next; - } -#else - certChain = ctx->localCert; - certCount = certChain ? CFArrayGetCount(certChain) : 0; - for (i = 0; i < certCount; ++i) { - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i); - totalLength += 3 + SecCertificateGetLength(cert); /* 3 for encoded length field */ - } -#endif - certificate->contentType = SSL_RecordTypeHandshake; - certificate->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(certificate); - if ((err = SSLAllocBuffer(&certificate->contents, totalLength + head + 3))) - return err; - - charPtr = SSLEncodeHandshakeHeader(ctx, certificate, SSL_HdskCert, totalLength+3); - - charPtr = SSLEncodeSize(charPtr, totalLength, 3); /* Vector length */ - -#ifdef USE_SSLCERTIFICATE - /* Root cert is first in the linked list, but has to go last, - * so walk list backwards */ - for (i = 0; i < certCount; ++i) - { cert = ctx->localCert; - for (j = i+1; j < certCount; ++j) - cert = cert->next; - charPtr = SSLEncodeSize(charPtr, cert->derCert.length, 3); - memcpy(charPtr, cert->derCert.data, cert->derCert.length); - charPtr += cert->derCert.length; - } -#else - /* Root cert is last in the array, and has to go last, - * so walk list forwards */ - for (i = 0; i < certCount; ++i) { - SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, i); - CFIndex certLength = SecCertificateGetLength(cert); - charPtr = SSLEncodeSize(charPtr, certLength, 3); - memcpy(charPtr, SecCertificateGetBytePtr(cert), certLength); - charPtr += certLength; - } -#endif - - assert(charPtr == certificate->contents.data + certificate->contents.length); - - if ((ctx->protocolSide == kSSLClientSide) && (ctx->localCert)) { - /* this tells us to send a CertificateVerify msg after the - * client key exchange. We skip the cert vfy if we just - * sent an empty cert msg (i.e., we were asked for a cert - * but we don't have one). */ - ctx->certSent = 1; - assert(ctx->clientCertState == kSSLClientCertRequested); - assert(ctx->certRequested); - ctx->clientCertState = kSSLClientCertSent; - } - if(certCount == 0) { - sslCertDebug("...sending empty cert msg"); - } - return errSecSuccess; -} - -OSStatus -SSLProcessCertificate(SSLBuffer message, SSLContext *ctx) -{ - size_t listLen, certLen; - UInt8 *p; - OSStatus err; - CFMutableArrayRef certChain = NULL; - SecCertificateRef cert; - - p = message.data; - listLen = SSLDecodeInt(p,3); - p += 3; - if (listLen + 3 != message.length) { - sslErrorLog("SSLProcessCertificate: length decode error 1\n"); - return errSSLProtocol; - } - - while (listLen > 0) - { - if (listLen < 3) { - sslErrorLog("SSLProcessCertificate: length decode error 2\n"); - return errSSLProtocol; - } - certLen = SSLDecodeInt(p,3); - p += 3; - if (listLen < certLen + 3) { - sslErrorLog("SSLProcessCertificate: length decode error 3\n"); - return errSSLProtocol; - } - if (!certChain) { - certChain = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - if (certChain == NULL) { - return errSecAllocate; - } - } - cert = SecCertificateCreateWithBytes(NULL, p, certLen); - #if SSL_DEBUG && !TARGET_OS_IPHONE - { - /* print cert name when debugging; leave disabled otherwise */ - CFStringRef certName = NULL; - OSStatus status = SecCertificateInferLabel(cert, &certName); - char buf[1024]; - if (status || !certName || !CFStringGetCString(certName, buf, 1024-1, kCFStringEncodingUTF8)) { buf[0]=0; } - sslDebugLog("SSLProcessCertificate: err=%d, received \"%s\" (%ld bytes)\n",(int) status, buf, certLen); - CFReleaseSafe(certName); - } - #endif - if (cert == NULL) { - sslErrorLog("SSLProcessCertificate: unable to create cert ref from data\n"); - return errSecAllocate; - } - p += certLen; - /* Insert forwards; root cert will be last in linked list */ - CFArrayAppendValue(certChain, cert); - CFRelease(cert); - listLen -= 3+certLen; - } - assert(p == message.data + message.length && listLen == 0); - - if (ctx->protocolSide == kSSLClientSide && ctx->peerCert && !ctx->allowServerIdentityChange) { - // Do not accept a different server cert during renegotiation unless allowed. - if((certChain!=NULL) && !CFEqual(ctx->peerCert, certChain)) - { - CFRelease(certChain); - sslErrorLog("Illegal server identity change during renegotiation\n"); - return errSSLProtocol; - } - } - - // Replace old cert with new cert. - if (ctx->peerCert) { - sslDebugLog("SSLProcessCertificate: releasing existing cert chain\n"); - CFRelease(ctx->peerCert); - } - - ctx->peerCert = certChain; - - if (!ctx->peerCert) { - /* this *might* be OK... */ - if((ctx->protocolSide == kSSLServerSide) && - (ctx->clientAuth != kAlwaysAuthenticate)) { - /* - * we tried to authenticate, client doesn't have a cert, and - * app doesn't require it. OK. - */ - return errSecSuccess; - } - else { - AlertDescription desc; - if(ctx->negProtocolVersion == SSL_Version_3_0) { - /* this one's for SSL3 only */ - desc = SSL_AlertBadCert; - } - else { - desc = SSL_AlertCertUnknown; - } - SSLFatalSessionAlert(desc, ctx); - return errSSLXCertChainInvalid; - } - } - - - - if((err = sslVerifyCertChain(ctx, ctx->peerCert, true)) != 0) { - AlertDescription desc; - switch(err) { - case errSSLUnknownRootCert: - case errSSLNoRootCert: - desc = SSL_AlertUnknownCA; - break; - case errSSLCertExpired: - case errSSLCertNotYetValid: - desc = SSL_AlertCertExpired; - break; - case errSSLXCertChainInvalid: - default: - desc = SSL_AlertCertUnknown; - break; - } - SSLFatalSessionAlert(desc, ctx); - } - - if (err == errSecSuccess) { - if(ctx->peerPubKey != NULL) { - /* renegotiating - free old key first */ - sslFreePubKey(&ctx->peerPubKey); - } - err = sslCopyPeerPubKey(ctx, &ctx->peerPubKey); - } - - /* Now that cert verification is done, update context state */ - /* (this code was formerly in SSLProcessHandshakeMessage, */ - /* directly after the return from SSLProcessCertificate) */ - if(ctx->protocolSide == kSSLServerSide) { - if(err) { - /* - * Error could be from no cert (when we require one) - * or invalid cert - */ - if(ctx->peerCert != NULL) { - ctx->clientCertState = kSSLClientCertRejected; - } - } else if(ctx->peerCert != NULL) { - /* - * This still might change if cert verify msg - * fails. Note we avoid going to state - * if we get en empty cert message which is - * otherwise valid. - */ - ctx->clientCertState = kSSLClientCertSent; - } - - /* - * Schedule return to the caller to verify the client's identity. - * Note that an error during processing will cause early - * termination of the handshake. - */ - if (ctx->breakOnClientAuth) { - ctx->signalClientAuth = true; - } - } else { - /* - * Schedule return to the caller to verify the server's identity. - * Note that an error during processing will cause early - * termination of the handshake. - */ - if (ctx->breakOnServerAuth) { - ctx->signalServerAuth = true; - } - } - - return err; -} - -OSStatus -SSLEncodeCertificateRequest(SSLRecord *request, SSLContext *ctx) -{ - OSStatus err; - size_t shListLen = 0, dnListLen, msgLen; - UInt8 *charPtr; - DNListElem *dn; - int head; - - assert(ctx->protocolSide == kSSLServerSide); - if (sslVersionIsLikeTls12(ctx)) { - shListLen = 2 + 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here. - } - - dnListLen = 0; - dn = ctx->acceptableDNList; - while (dn) - { dnListLen += 2 + dn->derDN.length; - dn = dn->next; - } - msgLen = 1 + // number of cert types - 2 + // cert types - shListLen + // SignatureAlgorithms - 2 + // length of DN list - dnListLen; - - request->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - - request->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(request); - if ((err = SSLAllocBuffer(&request->contents, msgLen + head))) - return err; - - charPtr = SSLEncodeHandshakeHeader(ctx, request, SSL_HdskCertRequest, msgLen); - - *charPtr++ = 2; /* two cert types */ - *charPtr++ = SSLClientAuth_RSASign; - *charPtr++ = SSLClientAuth_ECDSASign; - - if (shListLen) { - /* Encode the supported_signature_algorithms added in TLS1.2 */ - /* We dont support SHA512 or SHA224 because we didnot implement the digest abstraction for those - and we dont keep a running hash for those. - We dont support SHA384/ECDSA because corecrypto ec does not support it with 256 bits curves */ - charPtr = SSLEncodeSize(charPtr, shListLen - 2, 2); - // *charPtr++ = SSL_HashAlgorithmSHA512; - // *charPtr++ = SSL_SignatureAlgorithmRSA; - *charPtr++ = SSL_HashAlgorithmSHA384; - *charPtr++ = SSL_SignatureAlgorithmRSA; - *charPtr++ = SSL_HashAlgorithmSHA256; - *charPtr++ = SSL_SignatureAlgorithmRSA; - // *charPtr++ = SSL_HashAlgorithmSHA224; - // *charPtr++ = SSL_SignatureAlgorithmRSA; - *charPtr++ = SSL_HashAlgorithmSHA1; - *charPtr++ = SSL_SignatureAlgorithmRSA; - if (ctx->ecdsaEnable) { - // *charPtr++ = SSL_HashAlgorithmSHA512; - // *charPtr++ = SSL_SignatureAlgorithmECDSA; - // *charPtr++ = SSL_HashAlgorithmSHA384; - // *charPtr++ = SSL_SignatureAlgorithmECDSA; - *charPtr++ = SSL_HashAlgorithmSHA256; - *charPtr++ = SSL_SignatureAlgorithmECDSA; - // *charPtr++ = SSL_HashAlgorithmSHA224; - // *charPtr++ = SSL_SignatureAlgorithmECDSA; - *charPtr++ = SSL_HashAlgorithmSHA1; - *charPtr++ = SSL_SignatureAlgorithmECDSA; - } - } - - charPtr = SSLEncodeSize(charPtr, dnListLen, 2); - dn = ctx->acceptableDNList; - while (dn) - { charPtr = SSLEncodeSize(charPtr, dn->derDN.length, 2); - memcpy(charPtr, dn->derDN.data, dn->derDN.length); - charPtr += dn->derDN.length; - dn = dn->next; - } - - assert(charPtr == request->contents.data + request->contents.length); - return errSecSuccess; -} - -#define SSL_ENABLE_ECDSA_SIGN_AUTH 0 -#define SSL_ENABLE_RSA_FIXED_ECDH_AUTH 0 -#define SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH 0 - -OSStatus -SSLProcessCertificateRequest(SSLBuffer message, SSLContext *ctx) -{ - unsigned i; - unsigned typeCount; - unsigned shListLen = 0; - UInt8 *charPtr; - unsigned dnListLen; - unsigned dnLen; - SSLBuffer dnBuf; - DNListElem *dn; - OSStatus err; - - /* - * Cert request only happens in during client authentication. - * We'll send a client cert if we have an appropriate one, but - * we don't do any DNList compare. - */ - unsigned minLen = (sslVersionIsLikeTls12(ctx)) ? 5 : 3; - if (message.length < minLen) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 1\n"); - return errSSLProtocol; - } - charPtr = message.data; - typeCount = *charPtr++; - if (typeCount < 1 || message.length < minLen + typeCount) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 2\n"); - return errSSLProtocol; - } - if(typeCount != 0) { - /* Store server-specified auth types */ - if(ctx->clientAuthTypes != NULL) { - sslFree(ctx->clientAuthTypes); - } - ctx->clientAuthTypes = (SSLClientAuthenticationType *) - sslMalloc(typeCount * sizeof(SSLClientAuthenticationType)); - for(i=0; iclientAuthTypes[i] = (SSLClientAuthenticationType)(*charPtr++); - } - ctx->numAuthTypes = typeCount; - } - - if (sslVersionIsLikeTls12(ctx)) { - /* Parse the supported_signature_algorithms field added in TLS1.2 */ - shListLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (message.length < minLen + typeCount + shListLen) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); - return errSSLProtocol; - } - - if (shListLen & 1) { - sslErrorLog("SSLProcessCertificateRequest: signAlg len odd\n"); - return errSSLProtocol; - } - ctx->numServerSigAlgs = shListLen / 2; - if(ctx->serverSigAlgs != NULL) { - sslFree(ctx->serverSigAlgs); - } - ctx->serverSigAlgs = (SSLSignatureAndHashAlgorithm *) - sslMalloc((ctx->numServerSigAlgs) * sizeof(SSLSignatureAndHashAlgorithm)); - for(i=0; inumServerSigAlgs; i++) { - /* TODO: Validate hash and signature fields. */ - ctx->serverSigAlgs[i].hash = *charPtr++; - ctx->serverSigAlgs[i].signature = *charPtr++; - sslLogNegotiateDebug("===Server specifies sigAlg %d %d", - ctx->serverSigAlgs[i].hash, - ctx->serverSigAlgs[i].signature); - } - } - - /* if a client cert is set, it must match a server-specified auth type */ - err = SSLUpdateNegotiatedClientAuthType(ctx); - - /* obtain server's DNList */ - dnListLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (message.length != minLen + typeCount + shListLen + dnListLen) { - sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); - return errSSLProtocol; - } - while (dnListLen > 0) - { if (dnListLen < 2) { - sslErrorLog("SSLProcessCertificateRequest: dnListLen error 1\n"); - return errSSLProtocol; - } - dnLen = SSLDecodeInt(charPtr, 2); - charPtr += 2; - if (dnListLen < 2 + dnLen) { - sslErrorLog("SSLProcessCertificateRequest: dnListLen error 2\n"); - return errSSLProtocol; - } - if ((err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem)))) - return err; - dn = (DNListElem*)dnBuf.data; - if ((err = SSLAllocBuffer(&dn->derDN, dnLen))) - { SSLFreeBuffer(&dnBuf); - return err; - } - memcpy(dn->derDN.data, charPtr, dnLen); - charPtr += dnLen; - dn->next = ctx->acceptableDNList; - ctx->acceptableDNList = dn; - dnListLen -= 2 + dnLen; - } - - assert(charPtr == message.data + message.length); - - return errSecSuccess; -} - - -/* TODO: this should be refactored with FindSigAlg in sslKeyExchange.c */ -static -OSStatus FindCertSigAlg(SSLContext *ctx, - SSLSignatureAndHashAlgorithm *alg) -{ - unsigned i; - - assert(ctx->protocolSide == kSSLClientSide); - assert(ctx->negProtocolVersion >= TLS_Version_1_2); - assert(!ctx->isDTLS); - - if((ctx->numServerSigAlgs==0) ||(ctx->serverSigAlgs==NULL)) - return errSSLInternal; - - for(i=0; inumServerSigAlgs; i++) { - alg->hash = ctx->serverSigAlgs[i].hash; - alg->signature = ctx->serverSigAlgs[i].signature; - // We only support RSA cert for our own certs. - if(ctx->serverSigAlgs[i].signature != SSL_SignatureAlgorithmRSA) - continue; - - //Let's only support SHA1 and SHA256. SHA384 does not work with 512 bits RSA keys - // We should actually test against what the client cert can do. - if((alg->hash==SSL_HashAlgorithmSHA1) || (alg->hash==SSL_HashAlgorithmSHA256)) { - return errSecSuccess; - } - } - // We could not find a supported signature and hash algorithm - return errSSLProtocol; -} - -OSStatus -SSLEncodeCertificateVerify(SSLRecord *certVerify, SSLContext *ctx) -{ OSStatus err; - UInt8 hashData[SSL_MAX_DIGEST_LEN]; - SSLBuffer hashDataBuf; - size_t len; - size_t outputLen; - UInt8 *charPtr; - int head; - size_t maxSigLen; - bool isRSA = false; - - certVerify->contents.data = 0; - hashDataBuf.data = hashData; - hashDataBuf.length = SSL_MAX_DIGEST_LEN; - - - assert(ctx->signingPrivKeyRef != NULL); - err = sslGetMaxSigSize(ctx->signingPrivKeyRef, &maxSigLen); - if(err) { - goto fail; - } - - switch(ctx->negAuthType) { - case SSLClientAuth_RSASign: - isRSA = true; - break; -#if SSL_ENABLE_ECDSA_SIGN_AUTH - case SSLClientAuth_ECDSASign: - break; -#endif - default: - /* shouldn't be here */ - assert(0); - return errSSLInternal; - } - - certVerify->contentType = SSL_RecordTypeHandshake; - assert(ctx->negProtocolVersion >= SSL_Version_3_0); - certVerify->protocolVersion = ctx->negProtocolVersion; - head = SSLHandshakeHeaderSize(certVerify); - - outputLen = maxSigLen + head + 2; - - SSLSignatureAndHashAlgorithm sigAlg; - - if (sslVersionIsLikeTls12(ctx)) { - err=FindCertSigAlg(ctx, &sigAlg); - if(err) - goto fail; - outputLen += 2; - } - - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->computeCertVfyMac(ctx, &hashDataBuf, sigAlg.hash)) != 0) - goto fail; - - if ((err = SSLAllocBuffer(&certVerify->contents, outputLen)) != 0) - goto fail; - - /* Sign now to get the actual length */ - charPtr = certVerify->contents.data+head; - - if (sslVersionIsLikeTls12(ctx)) - { - *charPtr++ = sigAlg.hash; - *charPtr++ = sigAlg.signature; - - /* We don't support anything but RSA for client side auth yet */ - assert(isRSA); - SecAsn1AlgId algId; - switch (sigAlg.hash) { - case SSL_HashAlgorithmSHA384: - algId.algorithm = CSSMOID_SHA384WithRSA; - break; - case SSL_HashAlgorithmSHA256: - algId.algorithm = CSSMOID_SHA256WithRSA; - break; - case SSL_HashAlgorithmSHA1: - algId.algorithm = CSSMOID_SHA1WithRSA; - break; - default: - sslErrorLog("SSLEncodeCertificateVerify: unsupported signature hash algorithm (%d)\n", - sigAlg.hash); - assert(0); // if you get here, something is wrong in FindCertSigAlg - err=errSSLInternal; - goto fail; - } - - err = sslRsaSign(ctx, - ctx->signingPrivKeyRef, - &algId, - hashData, - hashDataBuf.length, - charPtr+2, - maxSigLen, - &outputLen); - len=outputLen+2+2; - } else { - err = sslRawSign(ctx, - ctx->signingPrivKeyRef, - hashData, // data to sign - hashDataBuf.length, // Data to sign size - charPtr+2, // signature destination - maxSigLen, // we mallocd len+head+2 - &outputLen); - len = outputLen+2; - } - if(err) { - sslErrorLog("SSLEncodeCertificateVerify: unable to sign data (error %d)\n", (int)err); - goto fail; - } - // At this point: - // len = message length - // outputlen = sig length - certVerify->contents.length = len + head; - - /* charPtr point at the len field here */ - charPtr = SSLEncodeSize(charPtr, outputLen, 2); - charPtr = SSLEncodeHandshakeHeader(ctx, certVerify, SSL_HdskCertVerify, len); - - assert(charPtr==(certVerify->contents.data+head)); - - err = errSecSuccess; - -fail: - - return err; -} - -OSStatus -SSLProcessCertificateVerify(SSLBuffer message, SSLContext *ctx) -{ OSStatus err; - UInt8 hashData[SSL_MAX_DIGEST_LEN]; - size_t signatureLen; - SSLBuffer hashDataBuf; - size_t publicModulusLen; - uint8_t *charPtr = message.data; - uint8_t *endCp = charPtr + message.length; - - SSLSignatureAndHashAlgorithm sigAlg; - SecAsn1AlgId algId; - - if (ctx->isDTLS - ? ctx->negProtocolVersion < DTLS_Version_1_0 - : ctx->negProtocolVersion >= TLS_Version_1_2) { - /* Parse the algorithm field added in TLS1.2 */ - if((charPtr+2) > endCp) { - sslErrorLog("SSLProcessCertificateVerify: msg len error 1\n"); - return errSSLProtocol; - } - sigAlg.hash = *charPtr++; - sigAlg.signature = *charPtr++; - - switch (sigAlg.hash) { - case SSL_HashAlgorithmSHA256: - algId.algorithm = CSSMOID_SHA256WithRSA; - if(ctx->selectedCipherSpecParams.macAlg == HA_SHA384) { - sslErrorLog("SSLProcessCertificateVerify: inconsistent hash, HA_SHA384\n"); - return errSSLInternal; - } - break; - case SSL_HashAlgorithmSHA384: - algId.algorithm = CSSMOID_SHA384WithRSA; - if(ctx->selectedCipherSpecParams.macAlg != HA_SHA384) { - sslErrorLog("SSLProcessCertificateVerify: inconsistent hash, %d not HA_SHA384\n", ctx->selectedCipherSpecParams.macAlg); - return errSSLInternal; - } - break; - default: - sslErrorLog("SSLProcessCertificateVerify: unsupported hash %d\n", sigAlg.hash); - return errSSLProtocol; - } - } - - if ((charPtr + 2) > endCp) { - sslErrorLog("SSLProcessCertificateVerify: msg len error\n"); - return errSSLProtocol; - } - - signatureLen = SSLDecodeSize(charPtr, 2); - charPtr += 2; - if ((charPtr + signatureLen) > endCp) { - sslErrorLog("SSLProcessCertificateVerify: sig len error 1\n"); - return errSSLProtocol; - } - - publicModulusLen = sslPubKeyLengthInBytes(ctx->peerPubKey); - - #if 0 - if (signatureLen != publicModulusLen) { - sslErrorLog("SSLProcessCertificateVerify: sig len error 2\n"); - return errSSLProtocol; - } - #endif - if (publicModulusLen == 0) { - sslErrorLog("SSLProcessCertificateVerify: pub key modulus is 0\n"); - } - - hashDataBuf.data = hashData; - hashDataBuf.length = SSL_MAX_DIGEST_LEN; - - assert(ctx->sslTslCalls != NULL); - if ((err = ctx->sslTslCalls->computeCertVfyMac(ctx, &hashDataBuf, sigAlg.hash)) != 0) - goto fail; - - if (sslVersionIsLikeTls12(ctx)) - { - if(sigAlg.signature==SSL_SignatureAlgorithmRSA) { - err = sslRsaVerify(ctx, - ctx->peerPubKey, - &algId, - hashData, - hashDataBuf.length, - charPtr, - signatureLen); - } else { - err = sslRawVerify(ctx, - ctx->peerPubKey, - hashData, - hashDataBuf.length, - charPtr, - signatureLen); - } - } else { - /* sslRawVerify does the decrypt & compare for us in one shot. */ - err = sslRawVerify(ctx, - ctx->peerPubKey, - hashData, // data to verify - hashDataBuf.length, - charPtr, // signature - signatureLen); - } - - if(err) { - SSLFatalSessionAlert(SSL_AlertDecryptError, ctx); - goto fail; - } - err = errSecSuccess; - -fail: - return err; -}