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>
45 #include <Security/SecItem.h>
48 #define CSSM_PERROR(f, r)
49 #define dprintf(args...)
51 #define CSSM_PERROR(f, r) cssmPerror(f, r)
52 #define dprintf(args...) fprintf(stderr, args)
55 static CSSM_CSP_HANDLE gCsp
= 0;
56 static char gCssmInitialized
= 0;
58 /* @@@ Ugly hack casting, but the extra argument at the end will be ignored. */
59 static CSSM_API_MEMORY_FUNCS memFuncs
=
63 (CSSM_REALLOC
)realloc
,
70 * SecCspHandleForAlgorithm
71 * @@@ This function should get more parameters like keysize and operation required and use mds.
75 SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm
)
80 CSSM_VERSION version
= { 2, 0 };
83 if (!gCssmInitialized
)
85 CSSM_GUID myGuid
= { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
86 CSSM_PVC_MODE pvcPolicy
= CSSM_PVC_NONE
;
88 rv
= CSSM_Init (&version
, CSSM_PRIVILEGE_SCOPE_NONE
, &myGuid
, CSSM_KEY_HIERARCHY_NONE
, &pvcPolicy
, NULL
);
94 rv
= CSSM_ModuleLoad(&gGuidAppleCSP
, CSSM_KEY_HIERARCHY_NONE
, NULL
, NULL
);
97 rv
= CSSM_ModuleAttach(&gGuidAppleCSP
, &version
, &memFuncs
, 0, CSSM_SERVICE_CSP
, 0, CSSM_KEY_HIERARCHY_NONE
, NULL
, 0, NULL
, &gCsp
);
104 OSStatus
cmsNullWrapKey(SecKeyRef refKey
,
107 CSSM_DATA descData
= {0, 0};
109 CSSM_CC_HANDLE ccHand
;
110 CSSM_ACCESS_CREDENTIALS creds
;
111 CSSM_CSP_HANDLE refCspHand
= CSSM_INVALID_HANDLE
;
112 const CSSM_KEY
*cssmKey
= NULL
;
115 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
116 memset(rawKey
, 0, sizeof(CSSM_KEY
));
118 crtn
= SecKeyGetCSSMKey(refKey
, &cssmKey
);
120 CSSM_PERROR("SecKeyGetCSSMKey", crtn
);
123 crtn
= SecKeyGetCSPHandle(refKey
, &refCspHand
);
125 CSSM_PERROR("SecKeyGetCSPHandle", crtn
);
129 crtn
= CSSM_CSP_CreateSymmetricContext(refCspHand
,
133 NULL
, // unwrappingKey
139 CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn
);
143 keyAttr
= rawKey
->KeyHeader
.KeyAttr
;
144 keyAttr
&= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE
| CSSM_KEYATTR_NEVER_EXTRACTABLE
|
145 CSSM_KEYATTR_MODIFIABLE
);
146 keyAttr
|= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
147 crtn
= CSSM_WrapKey(ccHand
,
152 if(crtn
!= CSSM_OK
) {
153 CSSM_PERROR("CSSM_WrapKey", crtn
);
155 CSSM_DeleteContext(ccHand
);
162 SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag
)
164 const SECOidData
*oidData
= SECOID_FindOIDByTag(algTag
);
165 return oidData
? oidData
->cssmAlgorithm
: CSSM_ALGID_NONE
;
169 static void SEC_PrintCFError(CFErrorRef CF_RELEASES_ARGUMENT error
) {
171 CFStringRef errorDesc
= CFErrorCopyDescription(error
);
172 dprintf("SecKey API returned: %ld, %s", CFErrorGetCode(error
),
173 errorDesc
? CFStringGetCStringPtr(errorDesc
, kCFStringEncodingUTF8
) : "");
175 if (errorDesc
) { CFRelease(errorDesc
); }
180 /* The new SecKey API has made this very painful */
181 static SecKeyAlgorithm
SECOID_FindSecKeyAlgorithmByTags(SECOidTag sigAlgTag
, SECOidTag digAlgTag
, bool isDigest
) {
183 case(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION
):
184 if (digAlgTag
== SEC_OID_MD5
) {
185 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
:
186 kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
);
189 case(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION
):
190 if (digAlgTag
== SEC_OID_SHA1
) {
191 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
192 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
);
195 case(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION
):
196 if (digAlgTag
== SEC_OID_SHA256
) {
197 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
198 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256
);
201 case(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION
):
202 if (digAlgTag
== SEC_OID_SHA384
) {
203 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
204 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384
);
207 case(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION
):
208 if (digAlgTag
== SEC_OID_SHA512
) {
209 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
210 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512
);
213 case(SEC_OID_PKCS1_RSA_ENCRYPTION
):
216 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
:
217 kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
);
219 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1
220 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA1
);
221 case(SEC_OID_SHA256
):
222 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256
223 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256
);
224 case(SEC_OID_SHA384
):
225 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384
226 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA384
);
227 case(SEC_OID_SHA512
):
228 return ((isDigest
) ? kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512
229 : kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512
);
233 case(SEC_OID_ECDSA_WithSHA1
):
234 if (digAlgTag
== SEC_OID_SHA1
) {
235 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
236 : kSecKeyAlgorithmECDSASignatureMessageX962SHA1
);
239 case(SEC_OID_ECDSA_WITH_SHA256
):
240 if (digAlgTag
== SEC_OID_SHA256
) {
241 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
242 : kSecKeyAlgorithmECDSASignatureMessageX962SHA256
);
245 case(SEC_OID_ECDSA_WITH_SHA384
):
246 if (digAlgTag
== SEC_OID_SHA384
) {
247 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
248 : kSecKeyAlgorithmECDSASignatureMessageX962SHA384
);
251 case(SEC_OID_ECDSA_WITH_SHA512
):
252 if (digAlgTag
== SEC_OID_SHA512
) {
253 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
254 : kSecKeyAlgorithmECDSASignatureMessageX962SHA512
);
257 case(SEC_OID_EC_PUBLIC_KEY
):
258 case(SEC_OID_SECP_256_R1
):
259 case(SEC_OID_SECP_384_R1
):
260 case(SEC_OID_SECP_521_R1
):
263 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
264 : kSecKeyAlgorithmECDSASignatureMessageX962SHA1
);
265 case(SEC_OID_SHA256
):
266 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
267 : kSecKeyAlgorithmECDSASignatureMessageX962SHA256
);
268 case(SEC_OID_SHA384
):
269 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
270 : kSecKeyAlgorithmECDSASignatureMessageX962SHA384
);
271 case(SEC_OID_SHA512
):
272 return ((isDigest
) ? kSecKeyAlgorithmECDSASignatureDigestX962
273 : kSecKeyAlgorithmECDSASignatureMessageX962SHA512
);
283 CFStringRef
SECOID_CopyKeyTypeByTag(SECOidTag tag
) {
284 CFStringRef keyType
= NULL
;
287 case(SEC_OID_RC2_CBC
):
288 case(SEC_OID_CMS_RC2_KEY_WRAP
):
289 keyType
= kSecAttrKeyTypeRC2
;
292 keyType
= kSecAttrKeyTypeRC4
;
294 case(SEC_OID_DES_ECB
):
295 case(SEC_OID_DES_CBC
):
296 case(SEC_OID_DES_OFB
):
297 case(SEC_OID_DES_CFB
):
298 keyType
= kSecAttrKeyTypeDES
;
300 case(SEC_OID_DES_EDE
):
301 case(SEC_OID_DES_EDE3_CBC
):
302 case(SEC_OID_CMS_3DES_KEY_WRAP
):
303 keyType
= kSecAttrKeyType3DES
;
305 case(SEC_OID_AES_128_ECB
):
306 case(SEC_OID_AES_128_CBC
):
307 case(SEC_OID_AES_192_ECB
):
308 case(SEC_OID_AES_192_CBC
):
309 case(SEC_OID_AES_256_ECB
):
310 case(SEC_OID_AES_256_CBC
):
311 case(SEC_OID_AES_128_KEY_WRAP
):
312 case(SEC_OID_AES_192_KEY_WRAP
):
313 case(SEC_OID_AES_256_KEY_WRAP
):
314 keyType
= kSecAttrKeyTypeAES
;
323 static SECStatus
SGN_SignAll(uint8_t *buf
, size_t len
,
324 SecPrivateKeyRef pk
, SECItem
*resultSignature
,
325 SECOidTag digAlgTag
, SECOidTag sigAlgTag
,
327 OSStatus rv
= SECFailure
;
328 CFDataRef signature
= NULL
, dataToSign
= NULL
;
329 CFErrorRef error
= NULL
;
330 SecKeyAlgorithm keyAlg
= NULL
;
332 keyAlg
= SECOID_FindSecKeyAlgorithmByTags(sigAlgTag
, digAlgTag
, isDigest
);
334 /* we no longer support signing with MD5 */
335 if (keyAlg
== kSecKeyAlgorithmRSASignatureMessagePKCS1v15MD5
||
336 keyAlg
== kSecKeyAlgorithmRSASignatureDigestPKCS1v15MD5
) {
337 dprintf("CMS signature failed: MD5 algorithm is disallowed for generating signatures.");
338 rv
= SEC_ERROR_INVALID_ALGORITHM
;
342 if (keyAlg
== NULL
) {
343 rv
= SEC_ERROR_INVALID_ALGORITHM
;
347 dataToSign
= CFDataCreate(NULL
, buf
, len
);
352 signature
= SecKeyCreateSignature(pk
, keyAlg
, dataToSign
, &error
);
357 CFIndex signatureLength
= CFDataGetLength(signature
);
358 if (signatureLength
< 0 || signatureLength
> 1024) {
361 resultSignature
->Data
= (uint8_t *)malloc(signatureLength
);
362 if (!resultSignature
->Data
) {
366 memcpy(resultSignature
->Data
, CFDataGetBytePtr(signature
), signatureLength
);
367 resultSignature
->Length
= signatureLength
;
371 if (signature
) { CFRelease(signature
); }
372 if (dataToSign
) {CFRelease(dataToSign
); }
373 SEC_PrintCFError(error
);
381 SEC_SignData(SECItem
*result
, unsigned char *buf
, int len
,
382 SecPrivateKeyRef pk
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
)
384 return SGN_SignAll(buf
, len
, pk
, result
, digAlgTag
, sigAlgTag
, false);
388 SGN_Digest(SecPrivateKeyRef pk
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
, SECItem
*result
, SECItem
*digest
)
390 return SGN_SignAll(digest
->Data
, digest
->Length
, pk
, result
, digAlgTag
, sigAlgTag
, true);
393 static SECStatus
VFY_VerifyAll(uint8_t *buf
, size_t len
,
394 SecPublicKeyRef pk
, SECItem
*sig
,
395 SECOidTag digAlgTag
, SECOidTag sigAlgTag
,
397 OSStatus rv
= SECFailure
;
398 CFDataRef signature
= NULL
, data
= NULL
;
399 CFErrorRef error
= NULL
;
400 SecKeyAlgorithm keyAlg
= NULL
;
402 signature
= CFDataCreate(NULL
, sig
->Data
, sig
->Length
);
403 data
= CFDataCreate(NULL
, buf
, len
);
404 if (!signature
|| !data
) {
408 keyAlg
= SECOID_FindSecKeyAlgorithmByTags(sigAlgTag
, digAlgTag
, isDigest
);
409 if (keyAlg
== NULL
) {
410 rv
= SEC_ERROR_INVALID_ALGORITHM
;
414 if(SecKeyVerifySignature(pk
, keyAlg
, data
, signature
, &error
)) {
419 if (signature
) { CFRelease(signature
); }
420 if (data
) { CFRelease(data
); }
421 SEC_PrintCFError(error
);
429 VFY_VerifyData(unsigned char *buf
, int len
,
430 SecPublicKeyRef pk
, SECItem
*sig
,
431 SECOidTag digAlgTag
, SECOidTag sigAlgTag
, void *wincx
)
433 return VFY_VerifyAll(buf
, len
, pk
, sig
,
434 digAlgTag
, sigAlgTag
, false);
438 VFY_VerifyDigest(SECItem
*digest
, SecPublicKeyRef pk
,
439 SECItem
*sig
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
, void *wincx
)
441 return VFY_VerifyAll(digest
->Data
, digest
->Length
, pk
, sig
,
442 digAlgTag
, sigAlgTag
, true);
446 WRAP_PubWrapSymKey(SecPublicKeyRef publickey
,
447 SecSymmetricKeyRef bulkkey
,
448 CSSM_DATA_PTR encKey
)
453 rv
= cmsNullWrapKey(bulkkey
, &bk
);
458 return SecKeyEncrypt(publickey
, kSecPaddingPKCS1
,
459 bk
.KeyData
.Data
, bk
.KeyData
.Length
,
460 encKey
->Data
, &encKey
->Length
);
465 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey
, CSSM_DATA_PTR encKey
, SECOidTag bulkalgtag
)
467 CFDataRef encryptedKey
= NULL
, bulkkey
= NULL
;
468 CFMutableDictionaryRef keyparams
= NULL
;
469 CFStringRef keyType
= NULL
;
470 CFErrorRef error
= NULL
;
471 SecSymmetricKeyRef bk
= NULL
;
473 /* decrypt the key */
474 encryptedKey
= CFDataCreate(NULL
, encKey
->Data
, encKey
->Length
);
479 bulkkey
= SecKeyCreateDecryptedData(privkey
, kSecKeyAlgorithmRSAEncryptionPKCS1
, encryptedKey
, &error
);
484 /* create the SecSymmetricKeyRef */
485 keyType
= SECOID_CopyKeyTypeByTag(bulkalgtag
);
490 keyparams
= CFDictionaryCreateMutable(NULL
, 1,
491 &kCFTypeDictionaryKeyCallBacks
,
492 &kCFTypeDictionaryValueCallBacks
);
497 CFDictionaryAddValue(keyparams
, kSecAttrKeyType
, keyType
);
498 bk
= SecKeyCreateFromData(keyparams
, bulkkey
, NULL
);
501 if (encryptedKey
) { CFRelease(encryptedKey
); }
502 if (bulkkey
) { CFRelease(bulkkey
); }
503 if (keyparams
) { CFRelease(keyparams
); }
504 if (keyType
) { CFRelease(keyType
); }
505 SEC_PrintCFError(error
);