2 * Copyright (c) 2006-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * sslCrypto.c - interface between SSL and crypto libraries
28 #include "sslCrypto.h"
30 #include "CipherSuite.h"
32 #include "sslContext.h"
33 #include "sslMemory.h"
36 #include <libDER/DER_CertCrl.h>
37 #include <libDER/DER_Keys.h>
38 #include <CoreFoundation/CFString.h>
39 #include <Security/SecKey.h>
40 #include <Security/SecKeyPriv.h>
41 #include <corecrypto/ccdh.h>
42 #include <corecrypto/ccec.h>
43 #include <corecrypto/ccrng.h>
44 #include <Security/SecCertificate.h>
45 #include <Security/SecPolicy.h>
46 #include <Security/SecTrust.h>
47 #include <AssertMacros.h>
48 #include "utilities/SecCFRelease.h"
51 #include <Security/SecKeyInternal.h>
52 #include <Security/SecRSAKey.h>
53 #include <Security/SecECKey.h>
56 #ifndef _SSL_KEYCHAIN_H_
57 #include "sslKeychain.h"
61 #include <libDER/libDER.h>
62 #include <libDER/DER_Keys.h>
63 #include <libDER/DER_Encode.h>
64 #include <libDER/asn1Types.h>
65 #include <Security/SecRandom.h>
73 #define CCRNGSTATE ccrng_seckey
75 /* extern struct ccrng_state *ccDRBGGetRngState(); */
76 #include <CommonCrypto/CommonRandomSPI.h>
77 #define CCRNGSTATE ccDRBGGetRngState()
82 * Free a pubKey object.
84 extern OSStatus
sslFreePubKey(SSLPubKey
**pubKey
)
86 if (pubKey
&& *pubKey
) {
87 CFReleaseNull(SECKEYREF(*pubKey
));
93 * Free a privKey object.
95 extern OSStatus
sslFreePrivKey(SSLPrivKey
**privKey
)
97 if (privKey
&& *privKey
) {
98 CFReleaseNull(SECKEYREF(*privKey
));
100 return errSecSuccess
;
104 * Get algorithm id for a SSLPubKey object.
106 CFIndex
sslPubKeyGetAlgorithmID(SSLPubKey
*pubKey
)
109 return SecKeyGetAlgorithmID(SECKEYREF(pubKey
));
111 return SecKeyGetAlgorithmId(SECKEYREF(pubKey
));
116 * Get algorithm id for a SSLPrivKey object.
118 CFIndex
sslPrivKeyGetAlgorithmID(SSLPrivKey
*privKey
)
121 return SecKeyGetAlgorithmID(SECKEYREF(privKey
));
123 return SecKeyGetAlgorithmId(SECKEYREF(privKey
));
128 * Raw RSA/DSA sign/verify.
133 const uint8_t *plainText
,
135 uint8_t *sig
, // mallocd by caller; RETURNED
136 size_t sigLen
, // available
137 size_t *actualBytes
) // RETURNED
141 #if RSA_SIG_SHARE_GIANT
142 RSASignBuffer
*signBuffer
= (RSASignBuffer
*)sig
;
143 assert(sigLen
>= sizeof(RSASignBuffer
));
145 assert(actualBytes
!= NULL
);
147 /* @@@ Shouldn't need to init giSigLen according to libgRSA docs. */
148 gi_uint16 giSigLen
= sigLen
;
150 rsaStatus
= RSA_Sign(&privKey
->rsaKey
,
154 #if RSA_SIG_SHARE_GIANT
160 *actualBytes
= giSigLen
;
162 return rsaStatus
? rsaStatusToSSL(rsaStatus
) : errSecSuccess
;
165 size_t inOutSigLen
= sigLen
;
167 assert(actualBytes
!= NULL
);
169 OSStatus status
= SecKeyRawSign(SECKEYREF(privKey
), kSecPaddingPKCS1
,
170 plainText
, plainTextLen
, sig
, &inOutSigLen
);
173 sslErrorLog("sslRawSign: SecKeyRawSign failed (error %d)\n", (int)status
);
176 /* Since the KeyExchange already allocated modulus size bytes we'll
177 use all of them. SecureTransport has always sent that many bytes,
178 so we're not going to deviate, to avoid interoperability issues. */
179 if (!status
&& (inOutSigLen
< sigLen
)) {
180 size_t offset
= sigLen
- inOutSigLen
;
181 memmove(sig
+ offset
, sig
, inOutSigLen
);
182 memset(sig
, 0, offset
);
183 inOutSigLen
= sigLen
;
187 *actualBytes
= inOutSigLen
;
192 /* TLS 1.2 RSA signature */
196 const SecAsn1AlgId
*algId
,
197 const uint8_t *plainText
,
199 uint8_t *sig
, // mallocd by caller; RETURNED
200 size_t sigLen
, // available
201 size_t *actualBytes
) // RETURNED
203 size_t inOutSigLen
= sigLen
;
205 assert(actualBytes
!= NULL
);
207 OSStatus status
= SecKeySignDigest(SECKEYREF(privKey
), algId
,
208 plainText
, plainTextLen
, sig
, &inOutSigLen
);
211 sslErrorLog("sslRsaSign: SecKeySignDigest failed (error %d)\n", (int) status
);
214 /* Since the KeyExchange already allocated modulus size bytes we'll
215 use all of them. SecureTransport has always sent that many bytes,
216 so we're not going to deviate, to avoid interoperability issues. */
217 if (!status
&& (inOutSigLen
< sigLen
)) {
218 size_t offset
= sigLen
- inOutSigLen
;
219 memmove(sig
+ offset
, sig
, inOutSigLen
);
220 memset(sig
, 0, offset
);
221 inOutSigLen
= sigLen
;
224 *actualBytes
= inOutSigLen
;
228 OSStatus
sslRawVerify(
231 const uint8_t *plainText
,
234 size_t sigLen
) // available
239 rsaStatus
= RSA_SigVerify(&pubKey
->rsaKey
,
246 return rsaStatus
? rsaStatusToSSL(rsaStatus
) : errSecSuccess
;
248 OSStatus status
= SecKeyRawVerify(SECKEYREF(pubKey
), kSecPaddingPKCS1
,
249 plainText
, plainTextLen
, sig
, sigLen
);
252 sslErrorLog("sslRawVerify: SecKeyRawVerify failed (error %d)\n", (int) status
);
259 /* TLS 1.2 RSA verify */
260 OSStatus
sslRsaVerify(
263 const SecAsn1AlgId
*algId
,
264 const uint8_t *plainText
,
267 size_t sigLen
) // available
269 OSStatus status
= SecKeyVerifyDigest(SECKEYREF(pubKey
), algId
,
270 plainText
, plainTextLen
, sig
, sigLen
);
273 sslErrorLog("sslRsaVerify: SecKeyVerifyDigest failed (error %d)\n", (int) status
);
282 OSStatus
sslRsaEncrypt(
285 const uint32_t padding
,
286 const uint8_t *plainText
,
288 uint8_t *cipherText
, // mallocd by caller; RETURNED
289 size_t cipherTextLen
, // available
290 size_t *actualBytes
) // RETURNED
293 gi_uint16 giCipherTextLen
= cipherTextLen
;
296 assert(actualBytes
!= NULL
);
298 rsaStatus
= RSA_Encrypt(&pubKey
->rsaKey
,
305 *actualBytes
= giCipherTextLen
;
307 return rsaStatus
? rsaStatusToSSL(rsaStatus
) : errSecSuccess
;
309 size_t ctlen
= cipherTextLen
;
311 assert(actualBytes
!= NULL
);
313 #if RSA_PUB_KEY_USAGE_HACK
314 /* Force key usage to allow encryption with public key */
315 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
316 CSSM_KEY
*cssmKey
= NULL
;
317 if (SecKeyGetCSSMKey(SECKEYREF(pubKey
), (const CSSM_KEY
**)&cssmKey
)==errSecSuccess
&& cssmKey
)
318 cssmKey
->KeyHeader
.KeyUsage
|= CSSM_KEYUSE_ENCRYPT
;
322 OSStatus status
= SecKeyEncrypt(SECKEYREF(pubKey
), padding
,
323 plainText
, plainTextLen
, cipherText
, &ctlen
);
326 sslErrorLog("sslRsaEncrypt: SecKeyEncrypt failed (error %d)\n", (int)status
);
329 /* Since the KeyExchange already allocated modulus size bytes we'll
330 use all of them. SecureTransport has always sent that many bytes,
331 so we're not going to deviate, to avoid interoperability issues. */
332 if (!status
&& (ctlen
< cipherTextLen
)) {
333 size_t offset
= cipherTextLen
- ctlen
;
334 memmove(cipherText
+ offset
, cipherText
, ctlen
);
335 memset(cipherText
, 0, offset
);
336 ctlen
= cipherTextLen
;
340 *actualBytes
= ctlen
;
343 sslErrorLog("***sslRsaEncrypt: error %d\n", (int)status
);
349 OSStatus
sslRsaDecrypt(
352 const uint32_t padding
,
353 const uint8_t *cipherText
,
354 size_t cipherTextLen
,
355 uint8_t *plainText
, // mallocd by caller; RETURNED
356 size_t plainTextLen
, // available
357 size_t *actualBytes
) // RETURNED
360 gi_uint16 giPlainTextLen
= plainTextLen
;
363 assert(actualBytes
!= NULL
);
365 rsaStatus
= RSA_Decrypt(&privKey
->rsaKey
,
371 *actualBytes
= giPlainTextLen
;
373 return rsaStatus
? rsaStatusToSSL(rsaStatus
) : errSecSuccess
;
375 size_t ptlen
= plainTextLen
;
377 assert(actualBytes
!= NULL
);
379 OSStatus status
= SecKeyDecrypt(SECKEYREF(privKey
), padding
,
380 cipherText
, cipherTextLen
, plainText
, &ptlen
);
381 *actualBytes
= ptlen
;
384 sslErrorLog("sslRsaDecrypt: SecKeyDecrypt failed (error %d)\n", (int)status
);
392 * Obtain size of the modulus of privKey in bytes.
394 size_t sslPrivKeyLengthInBytes(SSLPrivKey
*privKey
)
397 /* Get the length of p + q (which is the size of the modulus) in bits. */
398 gi_uint16 bitLen
= bitlen(&privKey
->rsaKey
.p
.g
) +
399 bitlen(&privKey
->rsaKey
.q
.g
);
400 /* Convert it to bytes. */
401 return (bitLen
+ 7) / 8;
403 return SecKeyGetBlockSize(SECKEYREF(privKey
));
408 * Obtain size of the modulus of pubKey in bytes.
410 size_t sslPubKeyLengthInBytes(SSLPubKey
*pubKey
)
413 /* Get the length of the modulus in bytes. */
414 return giantNumBytes(&pubKey
->rsaKey
.n
.g
);
416 return SecKeyGetBlockSize(SECKEYREF(pubKey
));
422 * Obtain maximum size of signature in bytes. A bit of a kludge; we could
423 * ask the CSP to do this but that would be kind of expensive.
425 OSStatus
sslGetMaxSigSize(
429 assert(maxSigSize
!= NULL
);
432 #if RSA_SIG_SHARE_GIANT
433 *maxSigSize
= sizeof(RSASignBuffer
);
435 *maxSigSize
= MAX_PRIME_SIZE_BYTES
;
438 *maxSigSize
= SecKeyGetBlockSize(SECKEYREF(privKey
));
441 return errSecSuccess
;
445 static OSStatus
sslGiantToBuffer(
446 SSLContext
*ctx
, // Currently unused.
456 ioLen
= serializeGiantBytes(g
);
457 status
= SSLAllocBuffer(buffer
, ioLen
);
460 chars
= buffer
->data
;
462 /* Serialize the giant g into chars. */
463 giReturn
= serializeGiant(g
, chars
, &ioLen
);
465 SSLFreeBuffer(buffer
);
466 return giReturnToSSL(giReturn
);
469 /* Trim off leading zeroes (but leave one zero if that's all there is). */
470 for (zeroCount
= 0; zeroCount
< (ioLen
- 1); ++zeroCount
)
471 if (chars
[zeroCount
])
475 buffer
->length
= ioLen
- zeroCount
;
476 memmove(chars
, chars
+ zeroCount
, buffer
->length
);
483 * Get raw key bits from an RSA public key.
485 OSStatus
sslGetPubKeyBits(
486 SSLContext
*ctx
, // Currently unused.
488 SSLBuffer
*modulus
, // data mallocd and RETURNED
489 SSLBuffer
*exponent
) // data mallocd and RETURNED
493 status
= sslGiantToBuffer(ctx
, &pubKey
->rsaKey
.n
.g
, modulus
);
497 status
= sslGiantToBuffer(ctx
, &pubKey
->rsaKey
.e
.g
, exponent
);
499 SSLFreeBuffer(modulus
);
508 * Given raw RSA key bits, cook up a SSLPubKey. Used in
509 * Server-initiated key exchange.
511 OSStatus
sslGetPubKeyFromBits(
513 const SSLBuffer
*modulus
,
514 const SSLBuffer
*exponent
,
515 SSLPubKey
**pubKey
) // mallocd and RETURNED
523 modulus
->data
, modulus
->length
,
525 exponent
->data
, exponent
->length
528 key
= sslMalloc(sizeof(*key
));
529 rsaStatus
= rsaInitPubGKey(&apiKey
, &key
->rsaKey
);
532 return rsaStatusToSSL(rsaStatus
);
536 return errSecSuccess
;
539 SecRSAPublicKeyParams params
= {
540 modulus
->data
, modulus
->length
,
541 exponent
->data
, exponent
->length
544 sslDebugLog("Creating RSA pub key from modulus=%p len=%lu exponent=%p len=%lu\n",
545 modulus
->data
, modulus
->length
,
546 exponent
->data
, exponent
->length
);
548 SecKeyRef key
= SecKeyCreateRSAPublicKey(NULL
, (const uint8_t *)¶ms
,
549 sizeof(params
), kSecKeyEncodingRSAPublicParams
);
551 sslErrorLog("sslGetPubKeyFromBits: SecKeyCreateRSAPublicKey failed\n");
555 sslDebugLog("sslGetPubKeyFromBits: RSA pub key block size=%lu\n", SecKeyGetBlockSize(key
));
557 *pubKey
= (SSLPubKey
*)key
;
558 return errSecSuccess
;
563 // MARK: Public Certificate Functions
565 #ifdef USE_SSLCERTIFICATE
568 * Given a SSLCertificate cert, obtain its public key as a SSLPubKey.
569 * Caller must sslFreePubKey and free the SSLPubKey itself.
571 OSStatus
sslPubKeyFromCert(
573 const SSLCertificate
*cert
,
574 SSLPubKey
**pubKey
) // RETURNED
577 DERSignedCertCrl signedCert
;
579 DERSubjPubKeyInfo pubKeyInfo
;
587 assert(pubKey
!= NULL
);
589 der
.data
= cert
->derCert
.data
;
590 der
.length
= cert
->derCert
.length
;
592 /* top level decode */
593 drtn
= DERParseSequence(&der
, DERNumSignedCertCrlItemSpecs
,
594 DERSignedCertCrlItemSpecs
, &signedCert
, sizeof(signedCert
));
596 return errSSLBadCert
;
598 /* decode the TBSCert - it was saved in full DER form */
599 drtn
= DERParseSequence(&signedCert
.tbs
,
600 DERNumTBSCertItemSpecs
, DERTBSCertItemSpecs
,
601 &tbsCert
, sizeof(tbsCert
));
603 return errSSLBadCert
;
605 /* sequence we're given: encoded DERSubjPubKeyInfo */
606 drtn
= DERParseSequenceContent(&tbsCert
.subjectPubKey
,
607 DERNumSubjPubKeyInfoItemSpecs
, DERSubjPubKeyInfoItemSpecs
,
608 &pubKeyInfo
, sizeof(pubKeyInfo
));
610 return errSSLBadCert
;
612 /* @@@ verify that this is an RSA key by decoding the AlgId */
615 * The contents of pubKeyInfo.pubKey is a bit string whose contents
616 * are a PKCS1 format RSA key.
618 drtn
= DERParseBitString(&pubKeyInfo
.pubKey
, &pubKeyPkcs1
, &numUnused
);
620 return errSSLBadCert
;
623 /* Now we have the public key in pkcs1 format. Let's make a public key
625 key
= sslMalloc(sizeof(*key
));
626 rsaStatus
= RSA_DecodePubKey(pubKeyPkcs1
.data
, pubKeyPkcs1
.length
,
632 SecKeyRef rsaPubKeyRef
= SecKeyCreateRSAPublicKey(NULL
,
633 pubKeyPkcs1
.data
, pubKeyPkcs1
.length
,
634 kSecKeyEncodingRSAPublicParams
);
635 rsaStatus
= (rsaPubKeyRef
) ? 0 : 1;
636 key
= (SSLPubKey
*)rsaPubKeyRef
;
639 return rsaStatusToSSL(rsaStatus
);
643 return errSecSuccess
;
647 * Verify a chain of DER-encoded certs.
648 * First cert in a chain is root; this must also be present
649 * in ctx->trustedCerts.
651 * If arePeerCerts is true, host name verification is enabled and we
652 * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise
653 * we're just validating our own certs; no host name checking and
654 * peerSecTrust is transient.
656 OSStatus
sslVerifyCertChain(
658 const SSLCertificate
*certChain
,
661 OSStatus ortn
= errSecSuccess
;
665 /* No point checking our own certs, our clients can do that. */
667 return errSecSuccess
;
669 CertVerifyReturn cvrtn
;
670 /* @@@ Add real cert checking. */
671 if (certChain
->next
) {
672 DERItem subject
, issuer
;
674 issuer
.data
= certChain
->derCert
.data
;
675 issuer
.length
= certChain
->derCert
.length
;
676 subject
.data
= certChain
->next
->derCert
.data
;
677 subject
.length
= certChain
->next
->derCert
.length
;
678 cvrtn
= certVerify(&subject
, &issuer
);
679 if (cvrtn
!= CVR_Success
)
680 ortn
= errSSLBadCert
;
684 sslErrorLog("***sslVerifyCertChain: only one cert in chain\n");
689 #else /* !USE_SSLCERTIFICATE */
694 CFArrayRef certChain
,
696 SecTrustRef
*pTrust
) /* RETURNED */
698 OSStatus status
= errSecAllocate
;
699 CFStringRef peerDomainName
= NULL
;
700 CFTypeRef policies
= NULL
;
701 SecTrustRef trust
= NULL
;
703 if (CFArrayGetCount(certChain
) == 0) {
704 status
= errSSLBadCert
;
709 if (ctx
->peerDomainNameLen
&& ctx
->peerDomainName
) {
710 CFIndex len
= ctx
->peerDomainNameLen
;
711 if (ctx
->peerDomainName
[len
- 1] == 0) {
713 //secwarning("peerDomainName is zero terminated!");
715 /* @@@ Double check that this is the correct encoding. */
716 require(peerDomainName
= CFStringCreateWithBytes(kCFAllocatorDefault
,
717 (const UInt8
*)ctx
->peerDomainName
, len
,
718 kCFStringEncodingUTF8
, false), errOut
);
721 /* If we are the client, our peer certificates must satisfy the
722 ssl server policy. */
723 bool server
= ctx
->protocolSide
== kSSLClientSide
;
724 require(policies
= SecPolicyCreateSSL(server
, peerDomainName
), errOut
);
726 require_noerr(status
= SecTrustCreateWithCertificates(certChain
, policies
,
729 /* If we have trustedAnchors we set them here. */
730 if (ctx
->trustedCerts
) {
731 require_noerr(status
= SecTrustSetAnchorCertificates(trust
,
732 ctx
->trustedCerts
), errOut
);
733 require_noerr(status
= SecTrustSetAnchorCertificatesOnly(trust
,
734 ctx
->trustedCertsOnly
), errOut
);
737 status
= errSecSuccess
;
740 CFReleaseSafe(peerDomainName
);
741 CFReleaseSafe(policies
);
748 /* Return the first certificate reference from the supplied array
749 * whose data matches the given certificate, or NULL if none match.
753 sslGetMatchingCertInArray(
754 SecCertificateRef certRef
,
755 CFArrayRef certArray
)
757 SecCertificateRef matchedCert
= NULL
;
759 if (certRef
== NULL
|| certArray
== NULL
) {
763 CFDataRef certData
= SecCertificateCopyData(certRef
);
765 CFIndex idx
, count
= CFArrayGetCount(certArray
);
766 for(idx
=0; idx
<count
; idx
++) {
767 SecCertificateRef aCert
= (SecCertificateRef
)CFArrayGetValueAtIndex(certArray
, idx
);
768 CFDataRef aData
= SecCertificateCopyData(aCert
);
769 if (aData
&& CFEqual(aData
, certData
)) {
772 CFReleaseSafe(aData
);
776 CFReleaseSafe(certData
);
783 * Verify a chain of DER-encoded certs.
784 * Last cert in a chain is the leaf; this must also be present
785 * in ctx->trustedCerts.
787 * If arePeerCerts is true, host name verification is enabled and we
788 * save the resulting SecTrustRef in ctx->peerSecTrust. Otherwise
789 * we're just validating our own certs; no host name checking and
790 * peerSecTrust is transient.
792 extern OSStatus
sslVerifyCertChain(
794 CFArrayRef certChain
,
798 SecTrustRef trust
= NULL
;
803 /* renegotiate - start with a new SecTrustRef */
804 CFReleaseNull(ctx
->peerSecTrust
);
807 status
= sslCreateSecTrust(ctx
, certChain
, arePeerCerts
, &trust
);
809 if (!ctx
->enableCertVerify
) {
810 /* trivial case, this is caller's responsibility */
811 status
= errSecSuccess
;
815 SecTrustResultType secTrustResult
;
816 require_noerr(status
= SecTrustEvaluate(trust
, &secTrustResult
), errOut
);
817 switch (secTrustResult
) {
818 case kSecTrustResultUnspecified
:
819 /* cert chain valid, no special UserTrust assignments */
820 case kSecTrustResultProceed
:
821 /* cert chain valid AND user explicitly trusts this */
822 status
= errSecSuccess
;
824 case kSecTrustResultDeny
:
825 case kSecTrustResultConfirm
:
826 case kSecTrustResultRecoverableTrustFailure
:
828 if(ctx
->allowAnyRoot
) {
829 sslErrorLog("***Warning: accepting unverified cert chain\n");
830 status
= errSecSuccess
;
834 * If the caller provided a list of trusted leaf certs, check them here
836 if(ctx
->trustedLeafCerts
) {
837 if (sslGetMatchingCertInArray((SecCertificateRef
)CFArrayGetValueAtIndex(certChain
, 0),
838 ctx
->trustedLeafCerts
)) {
839 status
= errSecSuccess
;
843 status
= errSSLXCertChainInvalid
;
845 /* Do we really need to return things like:
847 errSSLUnknownRootCert
849 errSSLCertNotYetValid
850 errSSLHostNameMismatch
851 for our client to see what went wrong, or should we just always
853 errSSLXCertChainInvalid
854 when something is wrong? */
860 ctx
->peerSecTrust
= trust
;
862 CFReleaseSafe(trust
);
868 * Given a SecCertificateRef cert, obtain its public key as a SSLPubKey.
869 * Caller must sslFreePubKey and free the SSLPubKey itself.
871 extern OSStatus
sslCopyPeerPubKey(
876 check(ctx
->peerSecTrust
);
878 #if !TARGET_OS_IPHONE
879 /* This is not required on iOS, but still required on osx */
880 if (!ctx
->enableCertVerify
) {
882 SecTrustResultType result
;
883 verify_noerr_action(status
= SecTrustEvaluate(ctx
->peerSecTrust
, &result
),
888 SecKeyRef key
= SecTrustCopyPublicKey(ctx
->peerSecTrust
);
890 sslErrorLog("sslCopyPeerPubKey: %s, ctx->peerSecTrust=%p\n",
891 "SecTrustCopyPublicKey failed", ctx
->peerSecTrust
);
892 return errSSLBadCert
;
894 *pubKey
= (SSLPubKey
*)key
;
896 return errSecSuccess
;
899 #endif /* !USE_SSLCERTIFICATE */
902 void stPrintCdsaError(const char *op
, OSStatus crtn
)
909 * After ciphersuite negotiation is complete, verify that we have
910 * the capability of actually performing the selected cipher.
911 * Currently we just verify that we have a cert and private signing
912 * key, if needed, and that the signing key's algorithm matches the
913 * expected key exchange method.
915 * This is currently called from FindCipherSpec(), after it sets
916 * ctx->selectedCipherSpec to a (supposedly) valid value, and from
917 * sslBuildCipherSpecArray(), in server mode (pre-negotiation) only.
919 OSStatus
sslVerifySelectedCipher(SSLContext
*ctx
)
921 if(ctx
->protocolSide
== kSSLClientSide
) {
922 return errSecSuccess
;
924 #if SSL_PAC_SERVER_ENABLE
925 if((ctx
->masterSecretCallback
!= NULL
) &&
926 (ctx
->sessionTicket
.data
!= NULL
)) {
927 /* EAP via PAC resumption; we can do it */
928 return errSecSuccess
;
930 #endif /* SSL_PAC_SERVER_ENABLE */
933 switch (ctx
->selectedCipherSpecParams
.keyExchangeMethod
) {
937 case SSL_DH_RSA_EXPORT
:
939 case SSL_DHE_RSA_EXPORT
:
940 requireAlg
= kSecRSAAlgorithmID
;
943 case SSL_DHE_DSS_EXPORT
:
945 case SSL_DH_DSS_EXPORT
:
946 requireAlg
= kSecDSAAlgorithmID
;
949 case SSL_DH_anon_EXPORT
:
951 requireAlg
= kSecNullAlgorithmID
; /* no signing key */
954 * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side,
955 * we'll need to add some logic here...
958 case SSL_ECDHE_ECDSA
:
963 requireAlg
= kSecECDSAAlgorithmID
;
968 /* needs update per cipherSpecs.c */
970 sslErrorLog("sslVerifySelectedCipher: unknown key exchange method\n");
971 return errSSLInternal
;
974 if(requireAlg
== kSecNullAlgorithmID
) {
975 return errSecSuccess
;
978 /* private signing key required */
979 if(ctx
->signingPrivKeyRef
== NULL
) {
980 sslErrorLog("sslVerifySelectedCipher: no signing key\n");
981 return errSSLBadConfiguration
;
984 /* Check the alg of our signing key. */
985 CFIndex keyAlg
= sslPrivKeyGetAlgorithmID(ctx
->signingPrivKeyRef
);
986 if (requireAlg
!= keyAlg
) {
987 sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n");
988 return errSSLBadConfiguration
;
991 return errSecSuccess
;
996 /* FIXME: This is duplicated in SecDH */
1003 static const DERItemSpec DER_DHParamsItemSpecs
[] =
1005 { DER_OFFSET(DER_DHParams
, p
),
1007 DER_DEC_NO_OPTS
| DER_ENC_SIGNED_INT
},
1008 { DER_OFFSET(DER_DHParams
, g
),
1010 DER_DEC_NO_OPTS
| DER_ENC_SIGNED_INT
},
1011 { DER_OFFSET(DER_DHParams
, l
),
1013 DER_DEC_OPTIONAL
| DER_ENC_SIGNED_INT
},
1015 static const DERSize DER_NumDHParamsItemSpecs
=
1016 sizeof(DER_DHParamsItemSpecs
) / sizeof(DERItemSpec
);
1018 /* Max encoded size for standard (PKCS3) parameters */
1019 #define DH_ENCODED_PARAM_SIZE(primeSizeInBytes) \
1020 DER_MAX_ENCODED_SIZE( \
1021 DER_MAX_ENCODED_SIZE(primeSizeInBytes) + /* g */ \
1022 DER_MAX_ENCODED_SIZE(primeSizeInBytes) + /* p */ \
1023 DER_MAX_ENCODED_SIZE(4)) /* l */
1026 OSStatus
sslDecodeDhParams(
1027 const SSLBuffer
*blob
, /* Input - PKCS-3 encoded */
1028 SSLBuffer
*prime
, /* Output - wire format */
1029 SSLBuffer
*generator
) /* Output - wire format */
1031 OSStatus ortn
= errSecSuccess
;
1033 DERItem paramItem
= {(DERByte
*)blob
->data
, blob
->length
};
1034 DER_DHParams decodedParams
;
1036 drtn
= DERParseSequence(¶mItem
,
1037 DER_NumDHParamsItemSpecs
, DER_DHParamsItemSpecs
,
1038 &decodedParams
, sizeof(decodedParams
));
1042 prime
->data
= decodedParams
.p
.data
;
1043 prime
->length
= decodedParams
.p
.length
;
1045 generator
->data
= decodedParams
.g
.data
;
1046 generator
->length
= decodedParams
.g
.length
;
1052 OSStatus
sslEncodeDhParams(SSLBuffer
*blob
, /* data mallocd and RETURNED PKCS-3 encoded */
1053 const SSLBuffer
*prime
, /* Wire format */
1054 const SSLBuffer
*generator
) /* Wire format */
1056 OSStatus ortn
= errSecSuccess
;
1057 DER_DHParams derParams
=
1060 .length
= prime
->length
,
1061 .data
= prime
->data
,
1064 .length
= generator
->length
,
1065 .data
= generator
->data
,
1073 DERSize ioLen
= DH_ENCODED_PARAM_SIZE(derParams
.p
.length
);
1074 DERByte
*der
= sslMalloc(ioLen
);
1075 // FIXME: What if this fails - we should probably not have a malloc here ?
1077 ortn
= (OSStatus
)DEREncodeSequence(ASN1_CONSTR_SEQUENCE
,
1079 DER_NumDHParamsItemSpecs
, DER_DHParamsItemSpecs
,
1082 // This should never fail
1090 OSStatus
sslDhCreateKey(SSLContext
*ctx
)
1092 if (ctx
->secDHContext
) {
1093 SecDHDestroy(ctx
->secDHContext
);
1094 ctx
->secDHContext
= NULL
;
1097 /* Server params are set using encoded dh params */
1098 if (!(ctx
->dhParamsEncoded
.length
&& ctx
->dhParamsEncoded
.data
))
1099 return errSSLInternal
;
1101 if (SecDHCreateFromParameters(ctx
->dhParamsEncoded
.data
,
1102 ctx
->dhParamsEncoded
.length
, &ctx
->secDHContext
))
1103 return errSSLCrypto
;
1105 return errSecSuccess
;
1108 OSStatus
sslDhGenerateKeyPair(SSLContext
*ctx
)
1110 OSStatus ortn
= errSecSuccess
;
1112 require_noerr(ortn
= SSLAllocBuffer(&ctx
->dhExchangePublic
,
1113 SecDHGetMaxKeyLength(ctx
->secDHContext
)), out
);
1114 require_noerr(ortn
= SecDHGenerateKeypair(ctx
->secDHContext
,
1115 ctx
->dhExchangePublic
.data
, &ctx
->dhExchangePublic
.length
), out
);
1122 OSStatus
sslDhKeyExchange(SSLContext
*ctx
)
1124 OSStatus ortn
= errSecSuccess
;
1127 ctx
->secDHContext
== NULL
||
1128 ctx
->dhPeerPublic
.length
== 0) {
1129 /* comes from peer, don't panic */
1130 sslErrorLog("sslDhKeyExchange: null peer public key\n");
1131 return errSSLProtocol
;
1134 require_noerr(ortn
= SSLAllocBuffer(&ctx
->preMasterSecret
,
1135 SecDHGetMaxKeyLength(ctx
->secDHContext
)), out
);
1136 require_noerr(ortn
= SecDHComputeKey(ctx
->secDHContext
,
1137 ctx
->dhPeerPublic
.data
, ctx
->dhPeerPublic
.length
,
1138 ctx
->preMasterSecret
.data
, &ctx
->preMasterSecret
.length
), out
);
1142 sslErrorLog("sslDhKeyExchange: failed to compute key (error %d)\n", (int)ortn
);
1146 #endif /* APPLE_DH */
1149 * Given an ECDSA key in SecKey format, extract the SSL_ECDSA_NamedCurve
1150 * from its algorithm parameters.
1152 OSStatus
sslEcdsaPeerCurve(
1154 SSL_ECDSA_NamedCurve
*namedCurve
)
1156 /* Cast is safe because enums are kept in sync. */
1157 *namedCurve
= (SSL_ECDSA_NamedCurve
)SecECKeyGetNamedCurve(SECKEYREF(pubKey
));
1158 if (*namedCurve
== kSecECCurveNone
) {
1159 sslErrorLog("sslEcdsaPeerCurve: no named curve for public key\n");
1160 return errSSLProtocol
;
1162 return errSecSuccess
;
1166 * Generate ECDH key pair with the given SSL_ECDSA_NamedCurve.
1167 * Private key, in ref form, is placed in ctx->ecdhPrivate.
1168 * Public key, in ECPoint form - which can NOT be used as
1169 * a key in any CSP ops - is placed in ecdhExchangePublic.
1171 OSStatus
sslEcdhGenerateKeyPair(
1173 SSL_ECDSA_NamedCurve namedCurve
)
1175 OSStatus ortn
= errSecSuccess
;
1178 switch (namedCurve
) {
1179 case SSL_Curve_secp256r1
:
1182 case SSL_Curve_secp384r1
:
1185 case SSL_Curve_secp521r1
:
1189 /* should not have gotten this far */
1190 sslErrorLog("sslEcdhGenerateKeyPair: bad namedCurve (%u)\n",
1191 (unsigned)namedCurve
);
1192 return errSSLInternal
;
1195 ccec_generate_key(cp
, CCRNGSTATE
, ctx
->ecdhContext
);
1196 size_t pub_size
= ccec_export_pub_size(ctx
->ecdhContext
);
1197 SSLFreeBuffer(&ctx
->ecdhExchangePublic
);
1198 require_noerr(ortn
= SSLAllocBuffer(&ctx
->ecdhExchangePublic
,
1200 ccec_export_pub(ctx
->ecdhContext
, ctx
->ecdhExchangePublic
.data
);
1202 sslDebugLog("sslEcdhGenerateKeyPair: pub key size=%ld, data=%p\n",
1203 pub_size
, ctx
->ecdhExchangePublic
.data
);
1210 * Perform ECDH key exchange. Obtained key material is the same
1211 * size as our private key.
1213 * On entry, ecdhPrivate is our private key. The peer's public key
1214 * is either ctx->ecdhPeerPublic for ECDHE exchange, or
1215 * ctx->peerPubKey for ECDH exchange.
1217 OSStatus
sslEcdhKeyExchange(
1219 SSLBuffer
*exchanged
)
1221 OSStatus ortn
= errSecSuccess
;
1222 CFDataRef pubKeyData
= NULL
;
1223 const unsigned char *pubKeyBits
;
1224 unsigned long pubKeyLen
;
1226 switch(ctx
->selectedCipherSpecParams
.keyExchangeMethod
) {
1227 case SSL_ECDHE_ECDSA
:
1229 /* public key passed in as CSSM_DATA *Param */
1230 if(ctx
->ecdhPeerPublic
.length
== 0) {
1231 /* comes from peer, don't panic */
1232 sslErrorLog("sslEcdhKeyExchange: null peer public key\n");
1233 ortn
= errSSLProtocol
;
1236 pubKeyBits
= ctx
->ecdhPeerPublic
.data
;
1237 pubKeyLen
= ctx
->ecdhPeerPublic
.length
;
1239 case SSL_ECDH_ECDSA
:
1241 /* Use the public key provided by the peer. */
1242 if(ctx
->peerPubKey
== NULL
) {
1243 sslErrorLog("sslEcdhKeyExchange: no peer key\n");
1244 ortn
= errSSLInternal
;
1248 pubKeyData
= SecECKeyCopyPublicBits(SECKEYREF(ctx
->peerPubKey
));
1250 sslErrorLog("sslEcdhKeyExchange: SecECKeyCopyPublicBits failed\n");
1251 ortn
= errSSLProtocol
;
1254 pubKeyBits
= CFDataGetBytePtr(pubKeyData
);
1255 pubKeyLen
= CFDataGetLength(pubKeyData
);
1258 /* shouldn't be here */
1259 sslErrorLog("sslEcdhKeyExchange: unknown keyExchangeMethod (%d)\n",
1260 ctx
->selectedCipherSpecParams
.keyExchangeMethod
);
1262 ortn
= errSSLInternal
;
1266 ccec_const_cp_t cp
= ccec_ctx_cp(ctx
->ecdhContext
);
1267 ccec_pub_ctx_decl(ccn_sizeof(521), pubKey
);
1268 ccec_import_pub(cp
, pubKeyLen
, pubKeyBits
, pubKey
);
1269 size_t len
= 1 + 2 * ccec_ccn_size(cp
);
1270 require_noerr(ortn
= SSLAllocBuffer(exchanged
, len
), errOut
);
1271 require_noerr(ccec_compute_key(ctx
->ecdhContext
, pubKey
, &exchanged
->length
, exchanged
->data
), errOut
);
1273 sslDebugLog("sslEcdhKeyExchange: exchanged key length=%ld, data=%p\n",
1274 exchanged
->length
, exchanged
->data
);
1277 CFReleaseSafe(pubKeyData
);