]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/lib/sslKeychain.c
Security-59306.11.20.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / lib / sslKeychain.c
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 <string.h>
44 #include <assert.h>
45
46
47 #include <Security/Security.h>
48 #include <Security/SecKeyPriv.h>
49 #if SEC_OS_IPHONE
50 #include <Security/SecECKey.h>
51 #endif
52 #include <AssertMacros.h>
53 #include <tls_handshake.h>
54
55 #if TARGET_OS_IPHONE
56 #include <Security/oidsalg.h>
57 #include <Security/SecECKey.h>
58 #endif
59
60 /* Private Key operations */
61 static
62 SecAsn1Oid oidForSSLHash(SSL_HashAlgorithm hash)
63 {
64 switch (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;
71 default:
72 break;
73 }
74 // Internal error
75 assert(0);
76 // This guarantee failure down the line
77 return CSSMOID_MD5WithRSA;
78 }
79
80 static
81 int mySSLPrivKeyRSA_sign(void *key, tls_hash_algorithm hash, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen)
82 {
83 SecKeyRef keyRef = key;
84
85 if(hash == tls_hash_algorithm_None) {
86 return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen);
87 } else {
88 SecAsn1AlgId algId;
89 algId.algorithm = oidForSSLHash(hash);
90 return SecKeySignDigest(keyRef, &algId, plaintext, plaintextLen, sig, sigLen);
91 }
92 }
93
94 static
95 int mySSLPrivKeyRSA_decrypt(void *key, const uint8_t *ciphertext, size_t ciphertextLen, uint8_t *plaintext, size_t *plaintextLen)
96 {
97 SecKeyRef keyRef = key;
98
99 return SecKeyDecrypt(keyRef, kSecPaddingPKCS1, ciphertext, ciphertextLen, plaintext, plaintextLen);
100 }
101
102 static
103 int mySSLPrivKeyECDSA_sign(void *key, const uint8_t *plaintext, size_t plaintextLen, uint8_t *sig, size_t *sigLen)
104 {
105 SecKeyRef keyRef = key;
106
107 return SecKeyRawSign(keyRef, kSecPaddingPKCS1, plaintext, plaintextLen, sig, sigLen);
108 }
109
110 void sslFreePrivKey(tls_private_key_t *sslPrivKey)
111 {
112 assert(sslPrivKey);
113
114 if(*sslPrivKey) {
115 CFReleaseSafe(tls_private_key_get_context(*sslPrivKey));
116 tls_private_key_destroy(*sslPrivKey);
117 *sslPrivKey = NULL;
118 }
119 }
120
121 OSStatus
122 parseIncomingCerts(
123 SSLContext *ctx,
124 CFArrayRef certs,
125 SSLCertificate **destCertChain, /* &ctx->{localCertChain,encryptCertChain} */
126 tls_private_key_t *sslPrivKey) /* &ctx->signingPrivKeyRef, etc. */
127 {
128 OSStatus ortn;
129 CFIndex ix, numCerts;
130 SecIdentityRef identity;
131 SSLCertificate *certChain = NULL; /* Retained */
132 SecCertificateRef leafCert = NULL; /* Retained */
133 SecKeyRef privKey = NULL; /* Retained */
134
135 assert(ctx != NULL);
136 assert(destCertChain != NULL); /* though its referent may be NULL */
137 assert(sslPrivKey != NULL);
138
139 if (certs == NULL) {
140 sslErrorLog("parseIncomingCerts: NULL incoming cert array\n");
141 ortn = errSSLBadCert;
142 goto errOut;
143 }
144 numCerts = CFArrayGetCount(certs);
145 if (numCerts == 0) {
146 sslErrorLog("parseIncomingCerts: empty incoming cert array\n");
147 ortn = errSSLBadCert;
148 goto errOut;
149 }
150
151 certChain=sslMalloc(numCerts*sizeof(SSLCertificate));
152 if (!certChain) {
153 ortn = errSecAllocate;
154 goto errOut;
155 }
156
157 /*
158 * Certs[0] is an SecIdentityRef from which we extract subject cert,
159 * privKey, pubKey.
160 *
161 * 1. ensure the first element is a SecIdentityRef.
162 */
163 identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0);
164 if (identity == NULL) {
165 sslErrorLog("parseIncomingCerts: bad cert array (1)\n");
166 ortn = errSecParam;
167 goto errOut;
168 }
169 if (CFGetTypeID(identity) != SecIdentityGetTypeID()) {
170 sslErrorLog("parseIncomingCerts: bad cert array (2)\n");
171 ortn = errSecParam;
172 goto errOut;
173 }
174
175 /*
176 * 2. Extract cert, keys and convert to local format.
177 */
178 ortn = SecIdentityCopyCertificate(identity, &leafCert);
179 if (ortn) {
180 sslErrorLog("parseIncomingCerts: bad cert array (3)\n");
181 goto errOut;
182 }
183
184 /* Fetch private key from identity */
185 ortn = SecIdentityCopyPrivateKey(identity, &privKey);
186 if (ortn) {
187 sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n",
188 (int)ortn);
189 goto errOut;
190 }
191
192 /* Convert the input array of SecIdentityRef at the start to an array of
193 all certificates. */
194 SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert), SecCertificateGetLength(leafCert), &certChain[0].derCert);
195 certChain[0].next = NULL;
196
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");
202 ortn = errSecParam;
203 goto errOut;
204 }
205 if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) {
206 sslErrorLog("parseIncomingCerts: bad cert array (6)\n");
207 ortn = errSecParam;
208 goto errOut;
209 }
210
211 SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate), SecCertificateGetLength(intermediate), &certChain[ix].derCert);
212 certChain[ix].next = NULL;
213 certChain[ix-1].next = &certChain[ix];
214
215 }
216
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) {
222 #if TARGET_OS_IPHONE
223 /* Compute signature size from key size */
224 size_t sigSize = 8+2*size;
225 #else
226 size_t sigSize = size;
227 #endif
228 *sslPrivKey = tls_private_key_ecdsa_create(privKey, sigSize, SecECKeyGetNamedCurve(privKey), mySSLPrivKeyECDSA_sign);
229 } else {
230 ortn = errSecParam;
231 goto errOut;
232 }
233 if(*sslPrivKey)
234 ortn = errSecSuccess;
235 else
236 ortn = errSecAllocate;
237
238 /* SUCCESS */
239 errOut:
240 CFReleaseSafe(leafCert);
241
242 sslFree(*destCertChain);
243
244 if (ortn) {
245 free(certChain);
246 CFReleaseSafe(privKey);
247 *destCertChain = NULL;
248 } else {
249 *destCertChain = certChain;
250 }
251
252 return ortn;
253 }