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"
44 #include "utilities/simulatecrash_assert.h"
47 #include <Security/Security.h>
48 #include <Security/SecKeyPriv.h>
50 #include <Security/SecECKey.h>
52 #include <AssertMacros.h>
53 #include <tls_handshake.h>
56 #include <Security/oidsalg.h>
57 #include <Security/SecECKey.h>
60 /* Private Key operations */
62 SecAsn1Oid
oidForSSLHash(SSL_HashAlgorithm hash
)
65 case tls_hash_algorithm_SHA1
:
66 return CSSMOID_SHA1WithRSA
;
67 case tls_hash_algorithm_SHA256
:
68 return CSSMOID_SHA256WithRSA
;
69 case tls_hash_algorithm_SHA384
:
70 return CSSMOID_SHA384WithRSA
;
76 // This guarantee failure down the line
77 return CSSMOID_MD5WithRSA
;
81 int mySSLPrivKeyRSA_sign(void *key
, tls_hash_algorithm hash
, const uint8_t *plaintext
, size_t plaintextLen
, uint8_t *sig
, size_t *sigLen
)
83 SecKeyRef keyRef
= key
;
85 if(hash
== tls_hash_algorithm_None
) {
86 return SecKeyRawSign(keyRef
, kSecPaddingPKCS1
, plaintext
, plaintextLen
, sig
, sigLen
);
89 algId
.algorithm
= oidForSSLHash(hash
);
90 return SecKeySignDigest(keyRef
, &algId
, plaintext
, plaintextLen
, sig
, sigLen
);
95 int mySSLPrivKeyRSA_decrypt(void *key
, const uint8_t *ciphertext
, size_t ciphertextLen
, uint8_t *plaintext
, size_t *plaintextLen
)
97 SecKeyRef keyRef
= key
;
99 return SecKeyDecrypt(keyRef
, kSecPaddingPKCS1
, ciphertext
, ciphertextLen
, plaintext
, plaintextLen
);
103 int mySSLPrivKeyECDSA_sign(void *key
, const uint8_t *plaintext
, size_t plaintextLen
, uint8_t *sig
, size_t *sigLen
)
105 SecKeyRef keyRef
= key
;
107 return SecKeyRawSign(keyRef
, kSecPaddingPKCS1
, plaintext
, plaintextLen
, sig
, sigLen
);
110 void sslFreePrivKey(tls_private_key_t
*sslPrivKey
)
115 CFReleaseSafe(tls_private_key_get_context(*sslPrivKey
));
116 tls_private_key_destroy(*sslPrivKey
);
125 SSLCertificate
**destCertChain
, /* &ctx->{localCertChain,encryptCertChain} */
126 tls_private_key_t
*sslPrivKey
) /* &ctx->signingPrivKeyRef, etc. */
129 CFIndex ix
, numCerts
;
130 SecIdentityRef identity
;
131 SSLCertificate
*certChain
= NULL
; /* Retained */
132 SecCertificateRef leafCert
= NULL
; /* Retained */
133 SecKeyRef privKey
= NULL
; /* Retained */
136 assert(destCertChain
!= NULL
); /* though its referent may be NULL */
137 assert(sslPrivKey
!= NULL
);
140 sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
141 ortn
= errSSLBadCert
;
144 numCerts
= CFArrayGetCount(certs
);
146 sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
147 ortn
= errSSLBadCert
;
151 certChain
=sslMalloc(numCerts
*sizeof(SSLCertificate
));
153 ortn
= errSecAllocate
;
158 * Certs[0] is an SecIdentityRef from which we extract subject cert,
161 * 1. ensure the first element is a SecIdentityRef.
163 identity
= (SecIdentityRef
)CFArrayGetValueAtIndex(certs
, 0);
164 if (identity
== NULL
) {
165 sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
169 if (CFGetTypeID(identity
) != SecIdentityGetTypeID()) {
170 sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
176 * 2. Extract cert, keys and convert to local format.
178 ortn
= SecIdentityCopyCertificate(identity
, &leafCert
);
180 sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
184 /* Fetch private key from identity */
185 ortn
= SecIdentityCopyPrivateKey(identity
, &privKey
);
187 sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
192 /* Convert the input array of SecIdentityRef at the start to an array of
194 SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert
), SecCertificateGetLength(leafCert
), &certChain
[0].derCert
);
195 certChain
[0].next
= NULL
;
197 for (ix
= 1; ix
< numCerts
; ++ix
) {
198 SecCertificateRef intermediate
=
199 (SecCertificateRef
)CFArrayGetValueAtIndex(certs
, ix
);
200 if (intermediate
== NULL
) {
201 sslErrorLog("parseIncomingCerts: bad cert array (5)\n");
205 if (CFGetTypeID(intermediate
) != SecCertificateGetTypeID()) {
206 sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
211 SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate
), SecCertificateGetLength(intermediate
), &certChain
[ix
].derCert
);
212 certChain
[ix
].next
= NULL
;
213 certChain
[ix
-1].next
= &certChain
[ix
];
217 sslFreePrivKey(sslPrivKey
);
218 size_t size
= SecKeyGetBlockSize(privKey
);
219 if(SecKeyGetAlgorithmId(privKey
) == kSecRSAAlgorithmID
) {
220 *sslPrivKey
= tls_private_key_rsa_create(privKey
, SecKeyGetBlockSize(privKey
), mySSLPrivKeyRSA_sign
, mySSLPrivKeyRSA_decrypt
);
221 } else if (SecKeyGetAlgorithmId(privKey
) == kSecECDSAAlgorithmID
) {
223 /* Compute signature size from key size */
224 size_t sigSize
= 8+2*size
;
226 size_t sigSize
= size
;
228 *sslPrivKey
= tls_private_key_ecdsa_create(privKey
, sigSize
, SecECKeyGetNamedCurve(privKey
), mySSLPrivKeyECDSA_sign
);
234 ortn
= errSecSuccess
;
236 ortn
= errSecAllocate
;
240 CFReleaseSafe(leafCert
);
242 sslFree(*destCertChain
);
246 CFReleaseSafe(privKey
);
247 *destCertChain
= NULL
;
249 *destCertChain
= certChain
;