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"
48 #include <Security/Security.h>
49 #include <Security/SecKeyPriv.h>
50 #include <AssertMacros.h>
51 #include <tls_handshake.h>
54 #include <Security/oidsalg.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
);
99 void sslFreePrivKey(tls_private_key_t
*sslPrivKey
)
104 CFReleaseSafe(tls_private_key_get_context(*sslPrivKey
));
105 tls_private_key_destroy(*sslPrivKey
);
114 SSLCertificate
**destCertChain
, /* &ctx->{localCertChain,encryptCertChain} */
115 tls_private_key_t
*sslPrivKey
) /* &ctx->signingPrivKeyRef, etc. */
118 CFIndex ix
, numCerts
;
119 SecIdentityRef identity
;
120 SSLCertificate
*certChain
= NULL
; /* Retained */
121 SecCertificateRef leafCert
= NULL
; /* Retained */
122 SecKeyRef privKey
= NULL
; /* Retained */
125 assert(destCertChain
!= NULL
); /* though its referent may be NULL */
126 assert(sslPrivKey
!= NULL
);
129 sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
130 ortn
= errSSLBadCert
;
133 numCerts
= CFArrayGetCount(certs
);
135 sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
136 ortn
= errSSLBadCert
;
140 certChain
=sslMalloc(numCerts
*sizeof(SSLCertificate
));
142 ortn
= errSecAllocate
;
147 * Certs[0] is an SecIdentityRef from which we extract subject cert,
150 * 1. ensure the first element is a SecIdentityRef.
152 identity
= (SecIdentityRef
)CFArrayGetValueAtIndex(certs
, 0);
153 if (identity
== NULL
) {
154 sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
158 if (CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
159 sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
165 * 2. Extract cert, keys and convert to local format.
167 ortn
= SecIdentityCopyCertificate(identity
, &leafCert
);
169 sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
173 /* Fetch private key from identity */
174 ortn
= SecIdentityCopyPrivateKey(identity
, &privKey
);
176 sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
181 /* Convert the input array of SecIdentityRef at the start to an array of
184 certChain
[0].derCert
.data
= (uint8_t *)SecCertificateGetBytePtr(leafCert
);
185 certChain
[0].derCert
.length
= SecCertificateGetLength(leafCert
);
186 certChain
[0].next
= NULL
;
188 for (ix
= 1; ix
< numCerts
; ++ix
) {
189 SecCertificateRef intermediate
=
190 (SecCertificateRef
)CFArrayGetValueAtIndex(certs
, ix
);
191 if (intermediate
== NULL
) {
192 sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
196 if (CFGetTypeID(intermediate
) != SecCertificateGetTypeID()) {
197 sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
202 certChain
[ix
].derCert
.data
= (uint8_t *)SecCertificateGetBytePtr(intermediate
);
203 certChain
[ix
].derCert
.length
= SecCertificateGetLength(intermediate
);
204 certChain
[ix
].next
= NULL
;
205 certChain
[ix
-1].next
= &certChain
[ix
];
209 if(sslPrivKeyGetAlgorithmID(privKey
)!=kSecRSAAlgorithmID
) {
214 sslFreePrivKey(sslPrivKey
);
215 *sslPrivKey
= tls_private_key_rsa_create(privKey
, SecKeyGetBlockSize(privKey
), mySSLPrivKeyRSA_sign
, mySSLPrivKeyRSA_decrypt
);
217 ortn
= errSecSuccess
;
219 ortn
= errSecAllocate
;
223 CFReleaseSafe(leafCert
);
225 sslFree(*destCertChain
);
229 CFReleaseSafe(privKey
);
230 *destCertChain
= NULL
;
232 *destCertChain
= certChain
;