]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_smime/lib/cryptohi.c
Security-59306.101.1.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / cryptohi.c
1 /*
2 * crypto.h - public data structures and prototypes for the crypto library
3 *
4 * The contents of this file are subject to the Mozilla Public
5 * License Version 1.1 (the "License"); you may not use this file
6 * except in compliance with the License. You may obtain a copy of
7 * the License at http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS
10 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11 * implied. See the License for the specific language governing
12 * rights and limitations under the License.
13 *
14 * The Original Code is the Netscape security libraries.
15 *
16 * The Initial Developer of the Original Code is Netscape
17 * Communications Corporation. Portions created by Netscape are
18 * Copyright (C) 1994-2000 Netscape Communications Corporation. All
19 * Rights Reserved.
20 *
21 * Contributor(s):
22 *
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU General Public License Version 2 or later (the
25 * "GPL"), in which case the provisions of the GPL are applicable
26 * instead of those above. If you wish to allow use of your
27 * version of this file only under the terms of the GPL and not to
28 * allow others to use your version of this file under the MPL,
29 * indicate your decision by deleting the provisions above and
30 * replace them with the notice and other provisions required by
31 * the GPL. If you do not delete the provisions above, a recipient
32 * may use your version of this file under either the MPL or the
33 * GPL.
34 */
35
36 #include "cryptohi.h"
37
38 #include "secoid.h"
39 #include "cmspriv.h"
40 #include <security_asn1/secerr.h>
41 #include <Security/cssmapi.h>
42 #include <Security/cssmapi.h>
43 #include <Security/SecKeyPriv.h>
44 #include <Security/cssmapple.h>
45
46 #if !USE_CDSA_CRYPTO
47 #include <Security/SecItem.h>
48 #endif
49
50 #ifdef NDEBUG
51 #define CSSM_PERROR(f, r)
52 #define dprintf(args...)
53 #else
54 #define CSSM_PERROR(f, r) cssmPerror(f, r)
55 #define dprintf(args...) fprintf(stderr, args)
56 #endif
57
58 static CSSM_CSP_HANDLE gCsp = 0;
59 static char gCssmInitialized = 0;
60
61 /* @@@ Ugly hack casting, but the extra argument at the end will be ignored. */
62 static CSSM_API_MEMORY_FUNCS memFuncs =
63 {
64 (CSSM_MALLOC)malloc,
65 (CSSM_FREE)free,
66 (CSSM_REALLOC)realloc,
67 (CSSM_CALLOC)calloc,
68 NULL
69 };
70
71 /*
72 *
73 * SecCspHandleForAlgorithm
74 * @@@ This function should get more parameters like keysize and operation required and use mds.
75 *
76 */
77 CSSM_CSP_HANDLE
78 SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm)
79 {
80
81 if (!gCsp)
82 {
83 CSSM_VERSION version = { 2, 0 };
84 CSSM_RETURN rv;
85
86 if (!gCssmInitialized)
87 {
88 CSSM_GUID myGuid = { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
89 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
90
91 rv = CSSM_Init (&version, CSSM_PRIVILEGE_SCOPE_NONE, &myGuid, CSSM_KEY_HIERARCHY_NONE, &pvcPolicy, NULL);
92 if (rv)
93 goto loser;
94 gCssmInitialized = 1;
95 }
96
97 rv = CSSM_ModuleLoad(&gGuidAppleCSP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
98 if (rv)
99 goto loser;
100 rv = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &memFuncs, 0, CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &gCsp);
101 }
102
103 loser:
104 return gCsp;
105 }
106
107 OSStatus cmsNullWrapKey(SecKeyRef refKey,
108 CSSM_KEY_PTR rawKey)
109 {
110 CSSM_DATA descData = {0, 0};
111 CSSM_RETURN crtn;
112 CSSM_CC_HANDLE ccHand;
113 CSSM_ACCESS_CREDENTIALS creds;
114 CSSM_CSP_HANDLE refCspHand = CSSM_INVALID_HANDLE;
115 const CSSM_KEY *cssmKey = NULL;
116 uint32 keyAttr;
117
118 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
119 memset(rawKey, 0, sizeof(CSSM_KEY));
120
121 crtn = SecKeyGetCSSMKey(refKey, &cssmKey);
122 if(crtn) {
123 CSSM_PERROR("SecKeyGetCSSMKey", crtn);
124 goto loser;
125 }
126 crtn = SecKeyGetCSPHandle(refKey, &refCspHand);
127 if(crtn) {
128 CSSM_PERROR("SecKeyGetCSPHandle", crtn);
129 goto loser;
130 }
131
132 crtn = CSSM_CSP_CreateSymmetricContext(refCspHand,
133 CSSM_ALGID_NONE,
134 CSSM_ALGMODE_NONE,
135 &creds,
136 NULL, // unwrappingKey
137 NULL, // initVector
138 CSSM_PADDING_NONE,
139 0, // Params
140 &ccHand);
141 if(crtn) {
142 CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn);
143 return crtn;
144 }
145
146 keyAttr = rawKey->KeyHeader.KeyAttr;
147 keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE |
148 CSSM_KEYATTR_MODIFIABLE);
149 keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
150 crtn = CSSM_WrapKey(ccHand,
151 &creds,
152 cssmKey,
153 &descData,
154 rawKey);
155 if(crtn != CSSM_OK) {
156 CSSM_PERROR("CSSM_WrapKey", crtn);
157 }
158 CSSM_DeleteContext(ccHand);
159
160 loser:
161 return crtn;
162 }
163
164 CSSM_ALGORITHMS
165 SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag)
166 {
167 const SECOidData *oidData = SECOID_FindOIDByTag(algTag);
168 return oidData ? oidData->cssmAlgorithm : CSSM_ALGID_NONE;
169 }
170
171
172 static void SEC_PrintCFError(CFErrorRef CF_RELEASES_ARGUMENT error) {
173 if (error) {
174 CFStringRef errorDesc = CFErrorCopyDescription(error);
175 dprintf("SecKey API returned: %ld, %s", CFErrorGetCode(error),
176 errorDesc ? CFStringGetCStringPtr(errorDesc, kCFStringEncodingUTF8) : "");
177 CFRelease(error);
178 if (errorDesc) { CFRelease(errorDesc); }
179 }
180
181 }
182
183 /* The new SecKey API has made this very painful */
184 static SecKeyAlgorithm SECOID_FindSecKeyAlgorithmByTags(SECOidTag sigAlgTag, SECOidTag digAlgTag, bool isDigest) {
185 switch(sigAlgTag) {
186 case(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION):
187 if (digAlgTag == SEC_OID_MD5) {
188 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 :
189 kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5);
190 }
191 break;
192 case(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION):
193 if (digAlgTag == SEC_OID_SHA1) {
194 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
195 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1);
196 }
197 break;
198 case(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION):
199 if (digAlgTag == SEC_OID_SHA256) {
200 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
201 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256);
202 }
203 break;
204 case(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION):
205 if (digAlgTag == SEC_OID_SHA384) {
206 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
207 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384);
208 }
209 break;
210 case(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION):
211 if (digAlgTag == SEC_OID_SHA512) {
212 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
213 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512);
214 }
215 break;
216 case(SEC_OID_PKCS1_RSA_ENCRYPTION):
217 switch (digAlgTag) {
218 case (SEC_OID_MD5):
219 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5 :
220 kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5);
221 case(SEC_OID_SHA1):
222 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
223 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1);
224 case(SEC_OID_SHA256):
225 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
226 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256);
227 case(SEC_OID_SHA384):
228 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
229 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384);
230 case(SEC_OID_SHA512):
231 return ((isDigest) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
232 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512);
233 default:
234 return NULL;
235 }
236 case(SEC_OID_ECDSA_WithSHA1):
237 if (digAlgTag == SEC_OID_SHA1) {
238 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
239 : kSecKeyAlgorithmECDSASignatureMessageX962SHA1);
240 }
241 break;
242 case(SEC_OID_ECDSA_WITH_SHA256):
243 if (digAlgTag == SEC_OID_SHA256) {
244 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
245 : kSecKeyAlgorithmECDSASignatureMessageX962SHA256);
246 }
247 break;
248 case(SEC_OID_ECDSA_WITH_SHA384):
249 if (digAlgTag == SEC_OID_SHA384) {
250 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
251 : kSecKeyAlgorithmECDSASignatureMessageX962SHA384);
252 }
253 break;
254 case(SEC_OID_ECDSA_WITH_SHA512):
255 if (digAlgTag == SEC_OID_SHA512) {
256 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
257 : kSecKeyAlgorithmECDSASignatureMessageX962SHA512);
258 }
259 break;
260 case(SEC_OID_EC_PUBLIC_KEY):
261 case(SEC_OID_SECP_256_R1):
262 case(SEC_OID_SECP_384_R1):
263 case(SEC_OID_SECP_521_R1):
264 switch (digAlgTag) {
265 case(SEC_OID_SHA1):
266 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
267 : kSecKeyAlgorithmECDSASignatureMessageX962SHA1);
268 case(SEC_OID_SHA256):
269 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
270 : kSecKeyAlgorithmECDSASignatureMessageX962SHA256);
271 case(SEC_OID_SHA384):
272 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
273 : kSecKeyAlgorithmECDSASignatureMessageX962SHA384);
274 case(SEC_OID_SHA512):
275 return ((isDigest) ? kSecKeyAlgorithmECDSASignatureDigestX962
276 : kSecKeyAlgorithmECDSASignatureMessageX962SHA512);
277 default:
278 return NULL;
279 }
280 default:
281 return NULL;
282 }
283 return NULL;
284 }
285
286 CFStringRef SECOID_CopyKeyTypeByTag(SECOidTag tag) {
287 CFStringRef keyType = NULL;
288
289 switch(tag) {
290 case(SEC_OID_RC2_CBC):
291 case(SEC_OID_CMS_RC2_KEY_WRAP):
292 keyType = kSecAttrKeyTypeRC2;
293 break;
294 case(SEC_OID_RC4):
295 keyType = kSecAttrKeyTypeRC4;
296 break;
297 case(SEC_OID_DES_ECB):
298 case(SEC_OID_DES_CBC):
299 case(SEC_OID_DES_OFB):
300 case(SEC_OID_DES_CFB):
301 keyType = kSecAttrKeyTypeDES;
302 break;
303 case(SEC_OID_DES_EDE):
304 case(SEC_OID_DES_EDE3_CBC):
305 case(SEC_OID_CMS_3DES_KEY_WRAP):
306 keyType = kSecAttrKeyType3DES;
307 break;
308 case(SEC_OID_AES_128_ECB):
309 case(SEC_OID_AES_128_CBC):
310 case(SEC_OID_AES_192_ECB):
311 case(SEC_OID_AES_192_CBC):
312 case(SEC_OID_AES_256_ECB):
313 case(SEC_OID_AES_256_CBC):
314 case(SEC_OID_AES_128_KEY_WRAP):
315 case(SEC_OID_AES_192_KEY_WRAP):
316 case(SEC_OID_AES_256_KEY_WRAP):
317 keyType = kSecAttrKeyTypeAES;
318 break;
319 default:
320 keyType = NULL;
321 }
322
323 return keyType;
324 }
325
326 static SECStatus SGN_SignAll(uint8_t *buf, size_t len,
327 SecPrivateKeyRef pk, SECItem *resultSignature,
328 SECOidTag digAlgTag, SECOidTag sigAlgTag,
329 bool isDigest) {
330 OSStatus rv = SECFailure;
331 CFDataRef signature = NULL, dataToSign = NULL;
332 CFErrorRef error = NULL;
333 SecKeyAlgorithm keyAlg = NULL;
334
335 keyAlg = SECOID_FindSecKeyAlgorithmByTags(sigAlgTag, digAlgTag, isDigest);
336
337 /* we no longer support signing with MD5 */
338 if (keyAlg == kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5 ||
339 keyAlg == kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5) {
340 dprintf("CMS signature failed: MD5 algorithm is disallowed for generating signatures.");
341 rv = SEC_ERROR_INVALID_ALGORITHM;
342 goto out;
343 }
344
345 if (keyAlg == NULL) {
346 rv = SEC_ERROR_INVALID_ALGORITHM;
347 goto out;
348 }
349
350 dataToSign = CFDataCreate(NULL, buf, len);
351 if (!dataToSign) {
352 goto out;
353 }
354
355 signature = SecKeyCreateSignature(pk, keyAlg, dataToSign, &error);
356 if (!signature) {
357 goto out;
358 }
359
360 CFIndex signatureLength = CFDataGetLength(signature);
361 if (signatureLength < 0 || signatureLength > 1024) {
362 goto out;
363 }
364 resultSignature->Data = (uint8_t *)malloc(signatureLength);
365 if (!resultSignature->Data) {
366 goto out;
367 }
368
369 memcpy(resultSignature->Data, CFDataGetBytePtr(signature), signatureLength);
370 resultSignature->Length = signatureLength;
371 rv = SECSuccess;
372
373 out:
374 if (signature) { CFRelease(signature); }
375 if (dataToSign) {CFRelease(dataToSign); }
376 SEC_PrintCFError(error);
377 if (rv) {
378 PORT_SetError(rv);
379 }
380 return rv;
381 }
382
383 SECStatus
384 SEC_SignData(SECItem *result, unsigned char *buf, int len,
385 SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag)
386 {
387 return SGN_SignAll(buf, len, pk, result, digAlgTag, sigAlgTag, false);
388 }
389
390 SECStatus
391 SGN_Digest(SecPrivateKeyRef pk, SECOidTag digAlgTag, SECOidTag sigAlgTag, SECItem *result, SECItem *digest)
392 {
393 return SGN_SignAll(digest->Data, digest->Length, pk, result, digAlgTag, sigAlgTag, true);
394 }
395
396 static SECStatus VFY_VerifyAll(uint8_t *buf, size_t len,
397 SecPublicKeyRef pk, SECItem *sig,
398 SECOidTag digAlgTag, SECOidTag sigAlgTag,
399 bool isDigest) {
400 OSStatus rv = SECFailure;
401 CFDataRef signature = NULL, data = NULL;
402 CFErrorRef error = NULL;
403 SecKeyAlgorithm keyAlg = NULL;
404
405 signature = CFDataCreate(NULL, sig->Data, sig->Length);
406 data = CFDataCreate(NULL, buf, len);
407 if (!signature || !data) {
408 goto out;
409 }
410
411 keyAlg = SECOID_FindSecKeyAlgorithmByTags(sigAlgTag, digAlgTag, isDigest);
412 if (keyAlg == NULL) {
413 rv = SEC_ERROR_INVALID_ALGORITHM;
414 goto out;
415 }
416
417 if(SecKeyVerifySignature(pk, keyAlg, data, signature, &error)) {
418 rv = SECSuccess;
419 }
420
421 out:
422 if (signature) { CFRelease(signature); }
423 if (data) { CFRelease(data); }
424 SEC_PrintCFError(error);
425 if (rv) {
426 PORT_SetError(rv);
427 }
428 return rv;
429 }
430
431 SECStatus
432 VFY_VerifyData(unsigned char *buf, int len,
433 SecPublicKeyRef pk, SECItem *sig,
434 SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx)
435 {
436 return VFY_VerifyAll(buf, len, pk, sig,
437 digAlgTag, sigAlgTag, false);
438 }
439
440 SECStatus
441 VFY_VerifyDigest(SECItem *digest, SecPublicKeyRef pk,
442 SECItem *sig, SECOidTag digAlgTag, SECOidTag sigAlgTag, void *wincx)
443 {
444 return VFY_VerifyAll(digest->Data, digest->Length, pk, sig,
445 digAlgTag, sigAlgTag, true);
446 }
447
448 SECStatus
449 WRAP_PubWrapSymKey(SecPublicKeyRef publickey,
450 SecSymmetricKeyRef bulkkey,
451 CSSM_DATA_PTR encKey)
452 {
453 OSStatus rv;
454 CSSM_KEY bk;
455
456 rv = cmsNullWrapKey(bulkkey, &bk);
457 if (rv) {
458 return rv;
459 }
460
461 return SecKeyEncrypt(publickey, kSecPaddingPKCS1,
462 bk.KeyData.Data, bk.KeyData.Length,
463 encKey->Data, &encKey->Length);
464 }
465
466
467 SecSymmetricKeyRef
468 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag)
469 {
470 CFDataRef encryptedKey = NULL, bulkkey = NULL;
471 CFMutableDictionaryRef keyparams = NULL;
472 CFStringRef keyType = NULL;
473 CFErrorRef error = NULL;
474 SecSymmetricKeyRef bk = NULL;
475
476 /* decrypt the key */
477 encryptedKey = CFDataCreate(NULL, encKey->Data, encKey->Length);
478 if (!encryptedKey) {
479 goto out;
480 }
481
482 bulkkey = SecKeyCreateDecryptedData(privkey, kSecKeyAlgorithmRSAEncryptionPKCS1, encryptedKey, &error);
483 if (!bulkkey) {
484 goto out;
485 }
486
487 /* create the SecSymmetricKeyRef */
488 keyType = SECOID_CopyKeyTypeByTag(bulkalgtag);
489 if (!keyType) {
490 goto out;
491 }
492
493 keyparams = CFDictionaryCreateMutable(NULL, 1,
494 &kCFTypeDictionaryKeyCallBacks,
495 &kCFTypeDictionaryValueCallBacks);
496 if (!keyparams) {
497 goto out;
498 }
499
500 CFDictionaryAddValue(keyparams, kSecAttrKeyType, keyType);
501 bk = SecKeyCreateFromData(keyparams, bulkkey, NULL);
502
503 out:
504 if (encryptedKey) { CFRelease(encryptedKey); }
505 if (bulkkey) { CFRelease(bulkkey); }
506 if (keyparams) { CFRelease(keyparams); }
507 if (keyType) { CFRelease(keyType); }
508 SEC_PrintCFError(error);
509 return bk;
510 }