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