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>
55 #include <Security/SecECKey.h>
58 /* Private Key operations */
60 SecAsn1Oid
oidForSSLHash(SSL_HashAlgorithm hash
)
63 case tls_hash_algorithm_SHA1
:
64 return CSSMOID_SHA1WithRSA
;
65 case tls_hash_algorithm_SHA256
:
66 return CSSMOID_SHA256WithRSA
;
67 case tls_hash_algorithm_SHA384
:
68 return CSSMOID_SHA384WithRSA
;
74 // This guarantee failure down the line
75 return CSSMOID_MD5WithRSA
;
79 int mySSLPrivKeyRSA_sign(void *key
, tls_hash_algorithm hash
, const uint8_t *plaintext
, size_t plaintextLen
, uint8_t *sig
, size_t *sigLen
)
81 SecKeyRef keyRef
= key
;
83 if(hash
== tls_hash_algorithm_None
) {
84 return SecKeyRawSign(keyRef
, kSecPaddingPKCS1
, plaintext
, plaintextLen
, sig
, sigLen
);
87 algId
.algorithm
= oidForSSLHash(hash
);
88 return SecKeySignDigest(keyRef
, &algId
, plaintext
, plaintextLen
, sig
, sigLen
);
93 int mySSLPrivKeyRSA_decrypt(void *key
, const uint8_t *ciphertext
, size_t ciphertextLen
, uint8_t *plaintext
, size_t *plaintextLen
)
95 SecKeyRef keyRef
= key
;
97 return SecKeyDecrypt(keyRef
, kSecPaddingPKCS1
, ciphertext
, ciphertextLen
, plaintext
, plaintextLen
);
101 int mySSLPrivKeyECDSA_sign(void *key
, const uint8_t *plaintext
, size_t plaintextLen
, uint8_t *sig
, size_t *sigLen
)
103 SecKeyRef keyRef
= key
;
105 return SecKeyRawSign(keyRef
, kSecPaddingPKCS1
, plaintext
, plaintextLen
, sig
, sigLen
);
108 void sslFreePrivKey(tls_private_key_t
*sslPrivKey
)
113 CFReleaseSafe(tls_private_key_get_context(*sslPrivKey
));
114 tls_private_key_destroy(*sslPrivKey
);
123 SSLCertificate
**destCertChain
, /* &ctx->{localCertChain,encryptCertChain} */
124 tls_private_key_t
*sslPrivKey
) /* &ctx->signingPrivKeyRef, etc. */
127 CFIndex ix
, numCerts
;
128 SecIdentityRef identity
;
129 SSLCertificate
*certChain
= NULL
; /* Retained */
130 SecCertificateRef leafCert
= NULL
; /* Retained */
131 SecKeyRef privKey
= NULL
; /* Retained */
134 assert(destCertChain
!= NULL
); /* though its referent may be NULL */
135 assert(sslPrivKey
!= NULL
);
138 sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
139 ortn
= errSSLBadCert
;
142 numCerts
= CFArrayGetCount(certs
);
144 sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
145 ortn
= errSSLBadCert
;
149 certChain
=sslMalloc(numCerts
*sizeof(SSLCertificate
));
151 ortn
= errSecAllocate
;
156 * Certs[0] is an SecIdentityRef from which we extract subject cert,
159 * 1. ensure the first element is a SecIdentityRef.
161 identity
= (SecIdentityRef
)CFArrayGetValueAtIndex(certs
, 0);
162 if (identity
== NULL
) {
163 sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
167 if (CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
168 sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
174 * 2. Extract cert, keys and convert to local format.
176 ortn
= SecIdentityCopyCertificate(identity
, &leafCert
);
178 sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
182 /* Fetch private key from identity */
183 ortn
= SecIdentityCopyPrivateKey(identity
, &privKey
);
185 sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
190 /* Convert the input array of SecIdentityRef at the start to an array of
192 SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert
), SecCertificateGetLength(leafCert
), &certChain
[0].derCert
);
193 certChain
[0].next
= NULL
;
195 for (ix
= 1; ix
< numCerts
; ++ix
) {
196 SecCertificateRef intermediate
=
197 (SecCertificateRef
)CFArrayGetValueAtIndex(certs
, ix
);
198 if (intermediate
== NULL
) {
199 sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
203 if (CFGetTypeID(intermediate
) != SecCertificateGetTypeID()) {
204 sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
209 SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate
), SecCertificateGetLength(intermediate
), &certChain
[ix
].derCert
);
210 certChain
[ix
].next
= NULL
;
211 certChain
[ix
-1].next
= &certChain
[ix
];
215 sslFreePrivKey(sslPrivKey
);
216 size_t size
= SecKeyGetBlockSize(privKey
);
217 if(sslPrivKeyGetAlgorithmID(privKey
) == kSecRSAAlgorithmID
) {
218 *sslPrivKey
= tls_private_key_rsa_create(privKey
, SecKeyGetBlockSize(privKey
), mySSLPrivKeyRSA_sign
, mySSLPrivKeyRSA_decrypt
);
219 } else if (sslPrivKeyGetAlgorithmID(privKey
) == kSecECDSAAlgorithmID
) {
221 /* Compute signature size from key size */
222 size_t sigSize
= 8+2*size
;
224 size_t sigSize
= size
;
226 *sslPrivKey
= tls_private_key_ecdsa_create(privKey
, sigSize
, SecECKeyGetNamedCurve(privKey
), mySSLPrivKeyECDSA_sign
);
232 ortn
= errSecSuccess
;
234 ortn
= errSecAllocate
;
238 CFReleaseSafe(leafCert
);
240 sslFree(*destCertChain
);
244 CFReleaseSafe(privKey
);
245 *destCertChain
= NULL
;
247 *destCertChain
= certChain
;