2 * crypto.h - public data structures and prototypes for the crypto library
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/
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.
14 * The Original Code is the Netscape security libraries.
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
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
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>
47 #include <Security/SecItem.h>
51 #define CSSM_PERROR(f, r)
52 #define dprintf(args...)
54 #define CSSM_PERROR(f, r) cssmPerror(f, r)
55 #define dprintf(args...) fprintf(stderr, args)
58 static CSSM_CSP_HANDLE gCsp
= 0;
59 static char gCssmInitialized
= 0;
61 /* @@@ Ugly hack casting, but the extra argument at the end will be ignored. */
62 static CSSM_API_MEMORY_FUNCS memFuncs
=
66 (CSSM_REALLOC
)realloc
,
73 * SecCspHandleForAlgorithm
74 * @@@ This function should get more parameters like keysize and operation required and use mds.
78 SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm
)
83 CSSM_VERSION version
= { 2, 0 };
86 if (!gCssmInitialized
)
88 CSSM_GUID myGuid
= { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
89 CSSM_PVC_MODE pvcPolicy
= CSSM_PVC_NONE
;
91 rv
= CSSM_Init (&version
, CSSM_PRIVILEGE_SCOPE_NONE
, &myGuid
, CSSM_KEY_HIERARCHY_NONE
, &pvcPolicy
, NULL
);
97 rv
= CSSM_ModuleLoad(&gGuidAppleCSP
, CSSM_KEY_HIERARCHY_NONE
, NULL
, NULL
);
100 rv
= CSSM_ModuleAttach(&gGuidAppleCSP
, &version
, &memFuncs
, 0, CSSM_SERVICE_CSP
, 0, CSSM_KEY_HIERARCHY_NONE
, NULL
, 0, NULL
, &gCsp
);
107 OSStatus
cmsNullWrapKey(SecKeyRef refKey
,
110 CSSM_DATA descData
= {0, 0};
112 CSSM_CC_HANDLE ccHand
;
113 CSSM_ACCESS_CREDENTIALS creds
;
114 CSSM_CSP_HANDLE refCspHand
= CSSM_INVALID_HANDLE
;
115 const CSSM_KEY
*cssmKey
= NULL
;
118 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
119 memset(rawKey
, 0, sizeof(CSSM_KEY
));
121 crtn
= SecKeyGetCSSMKey(refKey
, &cssmKey
);
123 CSSM_PERROR("SecKeyGetCSSMKey", crtn
);
126 crtn
= SecKeyGetCSPHandle(refKey
, &refCspHand
);
128 CSSM_PERROR("SecKeyGetCSPHandle", crtn
);
132 crtn
= CSSM_CSP_CreateSymmetricContext(refCspHand
,
136 NULL
, // unwrappingKey
142 CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn
);
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
,
155 if(crtn
!= CSSM_OK
) {
156 CSSM_PERROR("CSSM_WrapKey", crtn
);
158 CSSM_DeleteContext(ccHand
);
165 SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag
)
167 const SECOidData
*oidData
= SECOID_FindOIDByTag(algTag
);
168 return oidData
? oidData
->cssmAlgorithm
: CSSM_ALGID_NONE
;
172 static void SEC_PrintCFError(CFErrorRef CF_RELEASES_ARGUMENT error
) {
174 CFStringRef errorDesc
= CFErrorCopyDescription(error
);
175 fprintf(stderr
, "SecKey API returned: %ld, %s", CFErrorGetCode(error
),
176 errorDesc
? CFStringGetCStringPtr(errorDesc
, kCFStringEncodingUTF8
) : "");
178 if (errorDesc
) { CFRelease(errorDesc
); }
183 /* The new SecKey API has made this very painful */
184 static SecKeyAlgorithm
SECOID_FindSecKeyAlgorithmByTags(SECOidTag sigAlgTag
, SECOidTag digAlgTag
, bool isDigest
) {
186 case(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
):
187 if (digAlgTag
== SEC_OID_MD5
) {
188 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
:
189 kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
);
192 case(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
):
193 if (digAlgTag
== SEC_OID_SHA1
) {
194 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
195 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
);
198 case(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
):
199 if (digAlgTag
== SEC_OID_SHA256
) {
200 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
201 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256
);
204 case(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
):
205 if (digAlgTag
== SEC_OID_SHA384
) {
206 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
207 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384
);
210 case(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
):
211 if (digAlgTag
== SEC_OID_SHA512
) {
212 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
213 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512
);
216 case(SEC_OID_PKCS1_RSA_ENCRYPTION
):
219 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
:
220 kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
);
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
);
236 case(SEC_OID_ECDSA_WithSHA1
):
237 if (digAlgTag
== SEC_OID_SHA1
) {
238 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
239 : kSecKeyAlgorithmECDSASignatureMessageX962SHA1
);
242 case(SEC_OID_ECDSA_WITH_SHA256
):
243 if (digAlgTag
== SEC_OID_SHA256
) {
244 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
245 : kSecKeyAlgorithmECDSASignatureMessageX962SHA256
);
248 case(SEC_OID_ECDSA_WITH_SHA384
):
249 if (digAlgTag
== SEC_OID_SHA384
) {
250 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
251 : kSecKeyAlgorithmECDSASignatureMessageX962SHA384
);
254 case(SEC_OID_ECDSA_WITH_SHA512
):
255 if (digAlgTag
== SEC_OID_SHA512
) {
256 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
257 : kSecKeyAlgorithmECDSASignatureMessageX962SHA512
);
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
):
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
);
286 CFStringRef
SECOID_CopyKeyTypeByTag(SECOidTag tag
) {
287 CFStringRef keyType
= NULL
;
290 case(SEC_OID_RC2_CBC
):
291 case(SEC_OID_CMS_RC2_KEY_WRAP
):
292 keyType
= kSecAttrKeyTypeRC2
;
295 keyType
= kSecAttrKeyTypeRC4
;
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
;
303 case(SEC_OID_DES_EDE
):
304 case(SEC_OID_DES_EDE3_CBC
):
305 case(SEC_OID_CMS_3DES_KEY_WRAP
):
306 keyType
= kSecAttrKeyType3DES
;
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
;
326 static SECStatus
SGN_SignAll(uint8_t *buf
, size_t len
,
327 SecPrivateKeyRef pk
, SECItem
*resultSignature
,
328 SECOidTag digAlgTag
, SECOidTag sigAlgTag
,
330 OSStatus rv
= SECFailure
;
331 CFDataRef signature
= NULL
, dataToSign
= NULL
;
332 CFErrorRef error
= NULL
;
333 SecKeyAlgorithm keyAlg
= NULL
;
335 keyAlg
= SECOID_FindSecKeyAlgorithmByTags(sigAlgTag
, digAlgTag
, isDigest
);
337 /* we no longer support signing with MD5 */
338 if (keyAlg
== kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
||
339 keyAlg
== kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
) {
340 fprintf(stderr
, "CMS signature failed: MD5 algorithm is disallowed for generating signatures.");
341 rv
= SEC_ERROR_INVALID_ALGORITHM
;
345 if (keyAlg
== NULL
) {
346 rv
= SEC_ERROR_INVALID_ALGORITHM
;
350 dataToSign
= CFDataCreate(NULL
, buf
, len
);
355 signature
= SecKeyCreateSignature(pk
, keyAlg
, dataToSign
, &error
);
360 CFIndex signatureLength
= CFDataGetLength(signature
);
361 if (signatureLength
< 0 || signatureLength
> 1024) {
364 resultSignature
->Data
= (uint8_t *)malloc(signatureLength
);
365 if (!resultSignature
->Data
) {
369 memcpy(resultSignature
->Data
, CFDataGetBytePtr(signature
), signatureLength
);
370 resultSignature
->Length
= signatureLength
;
374 if (signature
) { CFRelease(signature
); }
375 if (dataToSign
) {CFRelease(dataToSign
); }
376 SEC_PrintCFError(error
);
384 SEC_SignData(SECItem
*result
, unsigned char *buf
, int len
,
385 SecPrivateKeyRef pk
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
)
387 return SGN_SignAll(buf
, len
, pk
, result
, digAlgTag
, sigAlgTag
, false);
391 SGN_Digest(SecPrivateKeyRef pk
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
, SECItem
*result
, SECItem
*digest
)
393 return SGN_SignAll(digest
->Data
, digest
->Length
, pk
, result
, digAlgTag
, sigAlgTag
, true);
396 static SECStatus
VFY_VerifyAll(uint8_t *buf
, size_t len
,
397 SecPublicKeyRef pk
, SECItem
*sig
,
398 SECOidTag digAlgTag
, SECOidTag sigAlgTag
,
400 OSStatus rv
= SECFailure
;
401 CFDataRef signature
= NULL
, data
= NULL
;
402 CFErrorRef error
= NULL
;
403 SecKeyAlgorithm keyAlg
= NULL
;
405 signature
= CFDataCreate(NULL
, sig
->Data
, sig
->Length
);
406 data
= CFDataCreate(NULL
, buf
, len
);
407 if (!signature
|| !data
) {
411 keyAlg
= SECOID_FindSecKeyAlgorithmByTags(sigAlgTag
, digAlgTag
, isDigest
);
412 if (keyAlg
== NULL
) {
413 rv
= SEC_ERROR_INVALID_ALGORITHM
;
417 if(SecKeyVerifySignature(pk
, keyAlg
, data
, signature
, &error
)) {
422 if (signature
) { CFRelease(signature
); }
423 if (data
) { CFRelease(data
); }
424 SEC_PrintCFError(error
);
432 VFY_VerifyData(unsigned char *buf
, int len
,
433 SecPublicKeyRef pk
, SECItem
*sig
,
434 SECOidTag digAlgTag
, SECOidTag sigAlgTag
, void *wincx
)
436 return VFY_VerifyAll(buf
, len
, pk
, sig
,
437 digAlgTag
, sigAlgTag
, false);
441 VFY_VerifyDigest(SECItem
*digest
, SecPublicKeyRef pk
,
442 SECItem
*sig
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
, void *wincx
)
444 return VFY_VerifyAll(digest
->Data
, digest
->Length
, pk
, sig
,
445 digAlgTag
, sigAlgTag
, true);
449 WRAP_PubWrapSymKey(SecPublicKeyRef publickey
,
450 SecSymmetricKeyRef bulkkey
,
451 CSSM_DATA_PTR encKey
)
456 rv
= cmsNullWrapKey(bulkkey
, &bk
);
461 return SecKeyEncrypt(publickey
, kSecPaddingPKCS1
,
462 bk
.KeyData
.Data
, bk
.KeyData
.Length
,
463 encKey
->Data
, &encKey
->Length
);
468 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey
, CSSM_DATA_PTR encKey
, SECOidTag bulkalgtag
)
470 CFDataRef encryptedKey
= NULL
, bulkkey
= NULL
;
471 CFMutableDictionaryRef keyparams
= NULL
;
472 CFStringRef keyType
= NULL
;
473 CFErrorRef error
= NULL
;
474 SecSymmetricKeyRef bk
= NULL
;
476 /* decrypt the key */
477 encryptedKey
= CFDataCreate(NULL
, encKey
->Data
, encKey
->Length
);
482 bulkkey
= SecKeyCreateDecryptedData(privkey
, kSecKeyAlgorithmRSAEncryptionPKCS1
, encryptedKey
, &error
);
487 /* create the SecSymmetricKeyRef */
488 keyType
= SECOID_CopyKeyTypeByTag(bulkalgtag
);
493 keyparams
= CFDictionaryCreateMutable(NULL
, 1,
494 &kCFTypeDictionaryKeyCallBacks
,
495 &kCFTypeDictionaryValueCallBacks
);
500 CFDictionaryAddValue(keyparams
, kSecAttrKeyType
, keyType
);
501 bk
= SecKeyCreateFromData(keyparams
, bulkkey
, NULL
);
504 if (encryptedKey
) { CFRelease(encryptedKey
); }
505 if (bulkkey
) { CFRelease(bulkkey
); }
506 if (keyparams
) { CFRelease(keyparams
); }
507 if (keyType
) { CFRelease(keyType
); }
508 SEC_PrintCFError(error
);