]> git.saurik.com Git - apple/security.git/blob - libsecurity_smime/lib/crypto-embedded.c
Security-57336.1.9.tar.gz
[apple/security.git] / libsecurity_smime / lib / crypto-embedded.c
1 /*
2 * crypto-embedded.c
3 * libsecurity_smime
4 *
5 * Created by Conrad Sauerwald on 2/7/08.
6 * Copyright (c) 2008-2011,2013 Apple Inc. All Rights Reserved.
7 *
8 */
9
10 #include <stdio.h>
11
12 #include "cert.h"
13 #include "cryptohi.h"
14
15 #include "cmstpriv.h"
16 #include "secoid.h"
17 #include "cmspriv.h"
18
19 #include <libDER/DER_Decode.h>
20 #include <security_asn1/secerr.h>
21 #include <security_asn1/secport.h>
22
23 #include <Security/SecBase.h>
24
25 #include <CoreFoundation/CFNumber.h>
26 #include <CoreFoundation/CFString.h>
27
28 #include <Security/oidsalg.h>
29 #include <Security/SecPolicy.h>
30 #include <Security/SecItem.h>
31 #include <Security/SecIdentity.h>
32 #include <Security/SecCertificateInternal.h>
33 #include <Security/SecKeyPriv.h>
34
35 #include <CommonCrypto/CommonDigest.h>
36 #include <AssertMacros.h>
37
38 SECStatus
39 CERT_VerifyCert(SecKeychainRef keychainOrArray __unused, CFArrayRef certs,
40 CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
41 {
42 SecTrustRef trust = NULL;
43 OSStatus rv;
44
45 rv = SecTrustCreateWithCertificates(certs, policies, &trust);
46 if (rv)
47 goto loser;
48
49 CFDateRef verifyDate = CFDateCreate(NULL, stime);
50 rv = SecTrustSetVerifyDate(trust, verifyDate);
51 CFRelease(verifyDate);
52 if (rv)
53 goto loser;
54
55 if (trustRef)
56 {
57 *trustRef = trust;
58 }
59 else
60 {
61 SecTrustResultType result;
62 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
63 rv = SecTrustEvaluate(trust, &result);
64 if (rv)
65 goto loser;
66
67 switch (result)
68 {
69 case kSecTrustResultProceed:
70 case kSecTrustResultUnspecified:
71 /* TP Verification succeeded and there was either a UserTurst entry
72 telling us to procceed, or no user trust setting was specified. */
73 CFRelease(trust);
74 break;
75 default:
76 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
77 rv = SECFailure;
78 goto loser;
79 break;
80 }
81 }
82
83 return SECSuccess;
84 loser:
85 if (trust)
86 CFRelease(trust);
87
88 return rv;
89 }
90
91
92 SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray,
93 char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win)
94 {
95 CFStringRef nickname_cfstr = CFStringCreateWithCString(kCFAllocatorDefault, nickname, kCFStringEncodingUTF8);
96 const void *keys[] = { kSecClass, kSecAttrLabel };
97 const void *values[] = { kSecClassCertificate, nickname_cfstr };
98 CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
99 CFTypeRef result = NULL;
100 SecItemCopyMatching(query, &result);
101 CFRelease(query);
102 CFRelease(nickname_cfstr);
103 return (SecCertificateRef)result;
104 }
105
106 CF_RETURNS_RETAINED CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot)
107 {
108 CFMutableArrayRef certs = NULL;
109 SecPolicyRef policy = NULL;
110 SecTrustRef trust = NULL;
111 CFArrayRef wrappedCert = NULL;
112
113 policy = SecPolicyCreateBasicX509();
114 if (!policy)
115 goto out;
116
117 wrappedCert = CERT_CertListFromCert(cert);
118 if (SecTrustCreateWithCertificates(wrappedCert, policy, &trust))
119 goto out;
120
121 SecTrustResultType result;
122 if (SecTrustEvaluate(trust, &result))
123 goto out;
124 CFIndex idx, count = SecTrustGetCertificateCount(trust);
125 certs = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
126 for(idx = 0; idx < count; idx++)
127 CFArrayAppendValue(certs, SecTrustGetCertificateAtIndex(trust, idx));
128
129 out:
130 if (trust) CFRelease(trust);
131 if (policy) CFRelease(policy);
132 if (wrappedCert) CFRelease(wrappedCert);
133
134 return certs;
135 }
136
137 CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
138 {
139 const void *value = cert;
140 return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
141 }
142
143 CFArrayRef CERT_DupCertList(CFArrayRef oldList)
144 {
145 CFRetain(oldList);
146 return oldList;
147 }
148
149 // Extract a public key object from a SubjectPublicKeyInfo
150 SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
151 {
152 return SecCertificateCopyPublicKey(cert);
153 }
154
155 // Extract the issuer and serial number from a certificate
156 SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert)
157 {
158 SecCmsIssuerAndSN *certIssuerAndSN;
159
160 void *mark;
161 mark = PORT_ArenaMark(pl);
162 CFDataRef serial_data = NULL;
163 CFDataRef issuer_data = SecCertificateCopyIssuerSequence(cert);
164 if (!issuer_data)
165 goto loser;
166 serial_data = SecCertificateCopySerialNumber(cert);
167 if (!serial_data)
168 goto loser;
169
170 SecAsn1Item serialNumber = { CFDataGetLength(serial_data),
171 (uint8_t *)CFDataGetBytePtr(serial_data) };
172 SecAsn1Item issuer = { CFDataGetLength(issuer_data),
173 (uint8_t *)CFDataGetBytePtr(issuer_data) };
174
175 /* Allocate the SecCmsIssuerAndSN struct. */
176 certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
177 if (certIssuerAndSN == NULL)
178 goto loser;
179
180 /* Copy the issuer. */
181 certIssuerAndSN->derIssuer.Data = (uint8_t *) PORT_ArenaAlloc(pl, issuer.Length);
182 if (!certIssuerAndSN->derIssuer.Data)
183 goto loser;
184 PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer.Data, issuer.Length);
185 certIssuerAndSN->derIssuer.Length = issuer.Length;
186
187 /* Copy the serialNumber. */
188 certIssuerAndSN->serialNumber.Data = (uint8_t *) PORT_ArenaAlloc(pl, serialNumber.Length);
189 if (!certIssuerAndSN->serialNumber.Data)
190 goto loser;
191 PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber.Data, serialNumber.Length);
192 certIssuerAndSN->serialNumber.Length = serialNumber.Length;
193
194 CFRelease(serial_data);
195 CFRelease(issuer_data);
196
197 PORT_ArenaUnmark(pl, mark);
198
199 return certIssuerAndSN;
200
201 loser:
202 if (serial_data)
203 CFRelease(serial_data);
204 if (issuer_data)
205 CFRelease(issuer_data);
206 PORT_ArenaRelease(pl, mark);
207 PORT_SetError(SEC_INTERNAL_ONLY);
208
209 return NULL;
210 }
211
212 // find the smime symmetric capabilities profile for a given cert
213 SecAsn1Item *CERT_FindSMimeProfile(SecCertificateRef cert)
214 {
215 return NULL;
216 }
217
218 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
219 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
220 static CFTypeRef CERT_FindByIssuerAndSN (CFTypeRef keychainOrArray, CFTypeRef class, const SecCmsIssuerAndSN *issuerAndSN)
221 {
222 CFTypeRef ident = NULL;
223 CFDictionaryRef query = NULL;
224 CFDataRef issuer = NULL;
225 CFDataRef serial = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
226 issuerAndSN->serialNumber.Data, issuerAndSN->serialNumber.Length,
227 kCFAllocatorNull);
228
229 DERItem der_issuer = { issuerAndSN->derIssuer.Data,
230 issuerAndSN->derIssuer.Length };
231 DERDecodedInfo content;
232 require_noerr_quiet(DERDecodeItem(&der_issuer, &content), out);
233 require_quiet(issuer = createNormalizedX501Name(kCFAllocatorDefault,
234 &content.content), out);
235
236 if (keychainOrArray && (CFGetTypeID(keychainOrArray) == CFArrayGetTypeID()) && CFEqual(class, kSecClassCertificate))
237 {
238 CFIndex c, count = CFArrayGetCount((CFArrayRef)keychainOrArray);
239 for (c = 0; c < count; c++) {
240 SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex((CFArrayRef)keychainOrArray, c);
241 CFDataRef nic = (cert) ? SecCertificateGetNormalizedIssuerContent(cert) : NULL;
242 if (nic && CFEqual(nic, issuer)) {
243 CFDataRef cert_serial = SecCertificateCopySerialNumber(cert);
244 if (cert_serial) {
245 bool found = CFEqual(cert_serial, serial);
246 CFRelease(cert_serial);
247 if (found) {
248 CFRetain(cert);
249 ident = cert;
250 goto out;
251 }
252 }
253 }
254 }
255 }
256
257 const void *keys[] = { kSecClass, kSecAttrIssuer, kSecAttrSerialNumber, kSecReturnRef };
258 const void *values[] = { class, issuer, serial, kCFBooleanTrue };
259 query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
260 require_noerr_quiet(SecItemCopyMatching(query, (CFTypeRef*)&ident), out);
261
262 out:
263 if (query)
264 CFRelease(query);
265 if (issuer)
266 CFRelease(issuer);
267 if (serial)
268 CFRelease(serial);
269
270 return ident;
271 }
272
273 SecIdentityRef CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
274 {
275 return (SecIdentityRef)CERT_FindByIssuerAndSN(keychainOrArray, kSecClassIdentity, issuerAndSN);
276 }
277
278 SecCertificateRef CERT_FindCertificateByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
279 {
280 return (SecCertificateRef)CERT_FindByIssuerAndSN(keychainOrArray, kSecClassCertificate, issuerAndSN);
281 }
282
283 SecIdentityRef CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray __unused, const SecAsn1Item *subjKeyID)
284 {
285 SecIdentityRef ident = NULL;
286 CFDictionaryRef query = NULL;
287 CFDataRef subjectkeyid = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, subjKeyID->Data, subjKeyID->Length, kCFAllocatorNull);
288
289 const void *keys[] = { kSecClass, kSecAttrSubjectKeyID, kSecReturnRef };
290 const void *values[] = { kSecClassIdentity, subjectkeyid, kCFBooleanTrue };
291 query = CFDictionaryCreate(kCFAllocatorDefault, keys, values, sizeof(keys)/sizeof(*keys), NULL, NULL);
292 require_noerr_quiet(SecItemCopyMatching(query, (CFTypeRef*)&ident), out);
293
294 out:
295 if (query)
296 CFRelease(query);
297 if (subjectkeyid)
298 CFRelease(subjectkeyid);
299
300 return ident;
301 }
302
303
304
305 SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
306 {
307 CFRetain(pubKey);
308 return pubKey;
309 }
310
311 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey)
312 {
313 CFRelease(pubKey);
314 }
315
316 SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey)
317 {
318 CFRetain(privKey);
319 return privKey;
320 }
321
322 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey)
323 {
324 CFRelease(privKey);
325 }
326
327 void CERT_DestroyCertificate(SecCertificateRef cert)
328 {
329 CFRelease(cert);
330 }
331
332 SecCertificateRef CERT_DupCertificate(SecCertificateRef cert)
333 {
334 CFRetain(cert);
335 return cert;
336 }
337
338 SECStatus
339 WRAP_PubWrapSymKey(SecPublicKeyRef publickey,
340 SecSymmetricKeyRef bulkkey,
341 SecAsn1Item * encKey)
342 {
343 return SecKeyEncrypt(publickey, kSecPaddingPKCS1,
344 CFDataGetBytePtr(bulkkey), CFDataGetLength(bulkkey),
345 encKey->Data, &encKey->Length);
346 }
347
348 SecSymmetricKeyRef
349 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, const SecAsn1Item *encKey, SECOidTag bulkalgtag)
350 {
351 size_t bulkkey_size = encKey->Length;
352 uint8_t bulkkey_buffer[bulkkey_size];
353 if (SecKeyDecrypt(privkey, kSecPaddingPKCS1,
354 encKey->Data, encKey->Length, bulkkey_buffer, &bulkkey_size))
355 return NULL;
356
357 CFDataRef bulkkey = CFDataCreate(kCFAllocatorDefault, bulkkey_buffer, bulkkey_size);
358 return (SecSymmetricKeyRef)bulkkey;
359 }
360
361
362 bool
363 CERT_CheckIssuerAndSerial(SecCertificateRef cert, SecAsn1Item *issuer, SecAsn1Item *serial)
364 {
365 do {
366 CFDataRef cert_issuer = SecCertificateCopyIssuerSequence(cert);
367 if (!cert_issuer)
368 break;
369 if ((issuer->Length != (size_t)CFDataGetLength(cert_issuer)) ||
370 memcmp(issuer->Data, CFDataGetBytePtr(cert_issuer), issuer->Length)) {
371 CFRelease(cert_issuer);
372 break;
373 }
374 CFRelease(cert_issuer);
375 CFDataRef cert_serial = SecCertificateCopySerialNumber(cert);
376 if (!cert_serial)
377 break;
378 if ((serial->Length != (size_t)CFDataGetLength(cert_serial)) ||
379 memcmp(serial->Data, CFDataGetBytePtr(cert_serial), serial->Length)) {
380 CFRelease(cert_serial);
381 break;
382 }
383 CFRelease(cert_serial);
384 return true;
385 } while(0);
386 return false;
387 }