1/*
2 * Copyright (c) 1999-2001,2005-2008,2010-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25 * sslKeychain.c - Apple Keychain routines
26 */
27
28#include "ssl.h"
29#include "sslContext.h"
30#include "sslMemory.h"
31
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"
40
41#include "sslDebug.h"
42#include "sslKeychain.h"
43#include "sslUtils.h"
44#include <string.h>
45#include <assert.h>
46
47
48#include <Security/Security.h>
49#include <Security/SecKeyPriv.h>
50#include <AssertMacros.h>
51#include <tls_handshake.h>
52
53#if TARGET_OS_IPHONE
54#include <Security/oidsalg.h>
55#endif
56
57/* Private Key operations */
58static
59SecAsn1Oid oidForSSLHash(SSL_HashAlgorithm hash)
60{
61    switch (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;
68        default:
69            break;
70    }
71    // Internal error
72    assert(0);
73    // This guarantee failure down the line
74    return CSSMOID_MD5WithRSA;
75}
76
77static
78int mySSLPrivKeyRSA_sign(void *key, tls_hash_algorithm hash, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen)
79{
80    SecKeyRef keyRef = key;
81
82    if(hash == tls_hash_algorithm_None) {
83        return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen);
84    } else {
85        SecAsn1AlgId  algId;
86        algId.algorithm = oidForSSLHash(hash);
87        return SecKeySignDigest(keyRef, &algId, plaintext, plaintextLen, sig, sigLen);
88    }
89}
90
91static
92int mySSLPrivKeyRSA_decrypt(void *key, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen)
93{
94    SecKeyRef keyRef = key;
95
96    return SecKeyDecrypt(keyRef, kSecPaddingPKCS1, ciphertext, ciphertextLen, plaintext, plaintextLen);
97}
98
99void sslFreePrivKey(tls_private_key_t *sslPrivKey)
100{
101    assert(sslPrivKey);
102
103    if(*sslPrivKey) {
104        CFReleaseSafe(tls_private_key_get_context(*sslPrivKey));
105        tls_private_key_destroy(*sslPrivKey);
106        *sslPrivKey = NULL;
107    }
108}
109
110OSStatus
111parseIncomingCerts(
112	SSLContext			*ctx,
113	CFArrayRef			certs,
114	SSLCertificate		**destCertChain, /* &ctx->{localCertChain,encryptCertChain} */
115	tls_private_key_t   *sslPrivKey)	 /* &ctx->signingPrivKeyRef, etc. */
116{
117	OSStatus			ortn;
118	CFIndex				ix, numCerts;
119	SecIdentityRef 		identity;
120	SSLCertificate      *certChain = NULL;	/* Retained */
121	SecCertificateRef	leafCert = NULL;	/* Retained */
122	SecKeyRef           privKey = NULL;	/* Retained */
123
124	assert(ctx != NULL);
125	assert(destCertChain != NULL);		/* though its referent may be NULL */
126	assert(sslPrivKey != NULL);
127
128	if (certs == NULL) {
129		sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
130		ortn = errSSLBadCert;
131		goto errOut;
132	}
133	numCerts = CFArrayGetCount(certs);
134	if (numCerts == 0) {
135		sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
136		ortn = errSSLBadCert;
137		goto errOut;
138	}
139
140    certChain=sslMalloc(numCerts*sizeof(SSLCertificate));
141    if (!certChain) {
142        ortn = errSecAllocate;
143        goto errOut;
144    }
145
146	/*
147	 * Certs[0] is an SecIdentityRef from which we extract subject cert,
148	 * privKey, pubKey.
149	 *
150	 * 1. ensure the first element is a SecIdentityRef.
151	 */
152	identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0);
153	if (identity == NULL) {
154		sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
155		ortn = errSecParam;
156		goto errOut;
157	}
158	if (CFGetTypeID(identity) != SecIdentityGetTypeID()) {
159		sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
160		ortn = errSecParam;
161		goto errOut;
162	}
163
164	/*
165	 * 2. Extract cert, keys and convert to local format.
166	 */
167	ortn = SecIdentityCopyCertificate(identity, &leafCert);
168	if (ortn) {
169		sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
170		goto errOut;
171	}
172
173	/* Fetch private key from identity */
174	ortn = SecIdentityCopyPrivateKey(identity, &privKey);
175	if (ortn) {
176		sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
177			(int)ortn);
178		goto errOut;
179	}
180
181    /* Convert the input array of SecIdentityRef at the start to an array of
182     all certificates. */
183
184    certChain[0].derCert.data = (uint8_t *)SecCertificateGetBytePtr(leafCert);
185    certChain[0].derCert.length = SecCertificateGetLength(leafCert);
186    certChain[0].next = NULL;
187
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");
193			ortn = errSecParam;
194			goto errOut;
195		}
196		if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) {
197			sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
198			ortn = errSecParam;
199			goto errOut;
200		}
201
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];
206
207	}
208
209    if(sslPrivKeyGetAlgorithmID(privKey)!=kSecRSAAlgorithmID) {
210        ortn = errSecParam;
211        goto errOut;
212    }
213
214    sslFreePrivKey(sslPrivKey);
215    *sslPrivKey = tls_private_key_rsa_create(privKey, SecKeyGetBlockSize(privKey), mySSLPrivKeyRSA_sign, mySSLPrivKeyRSA_decrypt);
216    if(*sslPrivKey)
217        ortn = errSecSuccess;
218    else
219        ortn = errSecAllocate;
220
221	/* SUCCESS */
222errOut:
223	CFReleaseSafe(leafCert);
224
225    sslFree(*destCertChain);
226
227	if (ortn) {
228		free(certChain);
229		CFReleaseSafe(privKey);
230		*destCertChain = NULL;
231	} else {
232		*destCertChain = certChain;
233	}
234
235	return ortn;
236}
237