2 * Copyright (c) 1999-2001,2005-2008,2010-2014 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 * sslKeychain.c - Apple Keychain routines
29 #include "sslContext.h"
30 #include "sslMemory.h"
32 #include "sslCrypto.h"
33 #include <Security/SecBase.h>
34 #include <Security/SecCertificate.h>
35 #include <Security/SecCertificatePriv.h>
36 #include <Security/SecIdentity.h>
37 #include <Security/SecPolicy.h>
38 #include <Security/SecTrust.h>
39 #include "utilities/SecCFRelease.h"
42 #include "sslKeychain.h"
47 #include <Security/Security.h>
48 #include <Security/SecKeyPriv.h>
49 #include <AssertMacros.h>
50 #include <tls_handshake.h>
53 #include <Security/oidsalg.h>
54 #include <Security/SecECKey.h>
57 /* Private Key operations */
59 SecAsn1Oid
oidForSSLHash(SSL_HashAlgorithm hash
)
62 case tls_hash_algorithm_SHA1
:
63 return CSSMOID_SHA1WithRSA
;
64 case tls_hash_algorithm_SHA256
:
65 return CSSMOID_SHA256WithRSA
;
66 case tls_hash_algorithm_SHA384
:
67 return CSSMOID_SHA384WithRSA
;
73 // This guarantee failure down the line
74 return CSSMOID_MD5WithRSA
;
78 int mySSLPrivKeyRSA_sign(void *key
, tls_hash_algorithm hash
, const uint8_t *plaintext
, size_t plaintextLen
, uint8_t *sig
, size_t *sigLen
)
80 SecKeyRef keyRef
= key
;
82 if(hash
== tls_hash_algorithm_None
) {
83 return SecKeyRawSign(keyRef
, kSecPaddingPKCS1
, plaintext
, plaintextLen
, sig
, sigLen
);
86 algId
.algorithm
= oidForSSLHash(hash
);
87 return SecKeySignDigest(keyRef
, &algId
, plaintext
, plaintextLen
, sig
, sigLen
);
92 int mySSLPrivKeyRSA_decrypt(void *key
, const uint8_t *ciphertext
, size_t ciphertextLen
, uint8_t *plaintext
, size_t *plaintextLen
)
94 SecKeyRef keyRef
= key
;
96 return SecKeyDecrypt(keyRef
, kSecPaddingPKCS1
, ciphertext
, ciphertextLen
, plaintext
, plaintextLen
);
100 int mySSLPrivKeyECDSA_sign(void *key
, const uint8_t *plaintext
, size_t plaintextLen
, uint8_t *sig
, size_t *sigLen
)
102 SecKeyRef keyRef
= key
;
104 return SecKeyRawSign(keyRef
, kSecPaddingPKCS1
, plaintext
, plaintextLen
, sig
, sigLen
);
107 void sslFreePrivKey(tls_private_key_t
*sslPrivKey
)
112 CFReleaseSafe(tls_private_key_get_context(*sslPrivKey
));
113 tls_private_key_destroy(*sslPrivKey
);
122 SSLCertificate
**destCertChain
, /* &ctx->{localCertChain,encryptCertChain} */
123 tls_private_key_t
*sslPrivKey
) /* &ctx->signingPrivKeyRef, etc. */
126 CFIndex ix
, numCerts
;
127 SecIdentityRef identity
;
128 SSLCertificate
*certChain
= NULL
; /* Retained */
129 SecCertificateRef leafCert
= NULL
; /* Retained */
130 SecKeyRef privKey
= NULL
; /* Retained */
133 assert(destCertChain
!= NULL
); /* though its referent may be NULL */
134 assert(sslPrivKey
!= NULL
);
137 sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
138 ortn
= errSSLBadCert
;
141 numCerts
= CFArrayGetCount(certs
);
143 sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
144 ortn
= errSSLBadCert
;
148 certChain
=sslMalloc(numCerts
*sizeof(SSLCertificate
));
150 ortn
= errSecAllocate
;
155 * Certs[0] is an SecIdentityRef from which we extract subject cert,
158 * 1. ensure the first element is a SecIdentityRef.
160 identity
= (SecIdentityRef
)CFArrayGetValueAtIndex(certs
, 0);
161 if (identity
== NULL
) {
162 sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
166 if (CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
167 sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
173 * 2. Extract cert, keys and convert to local format.
175 ortn
= SecIdentityCopyCertificate(identity
, &leafCert
);
177 sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
181 /* Fetch private key from identity */
182 ortn
= SecIdentityCopyPrivateKey(identity
, &privKey
);
184 sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
189 /* Convert the input array of SecIdentityRef at the start to an array of
191 SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert
), SecCertificateGetLength(leafCert
), &certChain
[0].derCert
);
192 certChain
[0].next
= NULL
;
194 for (ix
= 1; ix
< numCerts
; ++ix
) {
195 SecCertificateRef intermediate
=
196 (SecCertificateRef
)CFArrayGetValueAtIndex(certs
, ix
);
197 if (intermediate
== NULL
) {
198 sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
202 if (CFGetTypeID(intermediate
) != SecCertificateGetTypeID()) {
203 sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
208 SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate
), SecCertificateGetLength(intermediate
), &certChain
[ix
].derCert
);
209 certChain
[ix
].next
= NULL
;
210 certChain
[ix
-1].next
= &certChain
[ix
];
214 sslFreePrivKey(sslPrivKey
);
215 size_t size
= SecKeyGetBlockSize(privKey
);
216 if(sslPrivKeyGetAlgorithmID(privKey
) == kSecRSAAlgorithmID
) {
217 *sslPrivKey
= tls_private_key_rsa_create(privKey
, SecKeyGetBlockSize(privKey
), mySSLPrivKeyRSA_sign
, mySSLPrivKeyRSA_decrypt
);
218 } else if (sslPrivKeyGetAlgorithmID(privKey
) == kSecECDSAAlgorithmID
) {
220 /* Compute signature size from key size */
221 size_t sigSize
= 8+2*size
;
223 size_t sigSize
= size
;
225 *sslPrivKey
= tls_private_key_ecdsa_create(privKey
, sigSize
, SecECKeyGetNamedCurve(privKey
), mySSLPrivKeyECDSA_sign
);
231 ortn
= errSecSuccess
;
233 ortn
= errSecAllocate
;
237 CFReleaseSafe(leafCert
);
239 sslFree(*destCertChain
);
243 CFReleaseSafe(privKey
);
244 *destCertChain
= NULL
;
246 *destCertChain
= certChain
;