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