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>
46 static CSSM_CSP_HANDLE gCsp
= 0;
47 static char gCssmInitialized
= 0;
49 /* @@@ Ugly hack casting, but the extra argument at the end will be ignored. */
50 static CSSM_API_MEMORY_FUNCS memFuncs
=
54 (CSSM_REALLOC
)realloc
,
61 * SecCspHandleForAlgorithm
62 * @@@ This function should get more parameters like keysize and operation required and use mds.
66 SecCspHandleForAlgorithm(CSSM_ALGORITHMS algorithm
)
71 CSSM_VERSION version
= { 2, 0 };
74 if (!gCssmInitialized
)
76 CSSM_GUID myGuid
= { 0xFADE, 0, 0, { 1, 2, 3, 4, 5, 6, 7, 0 } };
77 CSSM_PVC_MODE pvcPolicy
= CSSM_PVC_NONE
;
79 rv
= CSSM_Init (&version
, CSSM_PRIVILEGE_SCOPE_NONE
, &myGuid
, CSSM_KEY_HIERARCHY_NONE
, &pvcPolicy
, NULL
);
85 rv
= CSSM_ModuleLoad(&gGuidAppleCSP
, CSSM_KEY_HIERARCHY_NONE
, NULL
, NULL
);
88 rv
= CSSM_ModuleAttach(&gGuidAppleCSP
, &version
, &memFuncs
, 0, CSSM_SERVICE_CSP
, 0, CSSM_KEY_HIERARCHY_NONE
, NULL
, 0, NULL
, &gCsp
);
96 SECOID_FindyCssmAlgorithmByTag(SECOidTag algTag
)
98 const SECOidData
*oidData
= SECOID_FindOIDByTag(algTag
);
99 return oidData
? oidData
->cssmAlgorithm
: CSSM_ALGID_NONE
;
103 SEC_SignData(SecAsn1Item
*result
, unsigned char *buf
, int len
,
104 SecPrivateKeyRef pk
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
)
106 const CSSM_ACCESS_CREDENTIALS
*accessCred
;
107 CSSM_ALGORITHMS algorithm
;
108 CSSM_CC_HANDLE cc
= 0;
111 SecAsn1Item dataBuf
= { (uint32
)len
, (uint8_t *)buf
};
112 SecAsn1Item sig
= {};
115 algorithm
= SECOID_FindyCssmAlgorithmByTag(SecCmsUtilMakeSignatureAlgorithm(digAlgTag
, sigAlgTag
));
118 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
123 rv
= SecKeyGetCSPHandle(pk
, &csp
);
125 PORT_SetError(SEC_ERROR_BAD_KEY
);
128 rv
= SecKeyGetCSSMKey(pk
, &key
);
130 PORT_SetError(SEC_ERROR_BAD_KEY
);
133 rv
= SecKeyGetCredentials(pk
, CSSM_ACL_AUTHORIZATION_SIGN
, kSecCredentialTypeDefault
, &accessCred
);
135 PORT_SetError(SEC_ERROR_BAD_KEY
);
139 rv
= CSSM_CSP_CreateSignatureContext(csp
, algorithm
, accessCred
, key
, &cc
);
141 PORT_SetError(SEC_ERROR_NO_MEMORY
);
145 rv
= CSSM_SignData(cc
, &dataBuf
, 1, CSSM_ALGID_NONE
, &sig
);
148 if (CSSM_ERRCODE(rv
) == CSSM_ERRCODE_USER_CANCELED
149 || CSSM_ERRCODE(rv
) == CSSM_ERRCODE_OPERATION_AUTH_DENIED
)
150 code
= SEC_ERROR_USER_CANCELLED
;
151 else if (CSSM_ERRCODE(rv
) == CSSM_ERRCODE_NO_USER_INTERACTION
152 || rv
== CSSMERR_CSP_KEY_USAGE_INCORRECT
)
153 code
= SEC_ERROR_INADEQUATE_KEY_USAGE
;
155 code
= SEC_ERROR_LIBRARY_FAILURE
;
161 result
->Length
= sig
.Length
;
162 result
->Data
= sig
.Data
;
166 CSSM_DeleteContext(cc
);
172 SGN_Digest(SecPrivateKeyRef pk
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
, SecAsn1Item
*result
, SecAsn1Item
*digest
)
174 const CSSM_ACCESS_CREDENTIALS
*accessCred
;
175 CSSM_ALGORITHMS digalg
, sigalg
;
176 CSSM_CC_HANDLE cc
= 0;
179 SecAsn1Item sig
= {};
182 digalg
= SECOID_FindyCssmAlgorithmByTag(digAlgTag
);
183 sigalg
= SECOID_FindyCssmAlgorithmByTag(sigAlgTag
);
184 if (!digalg
|| !sigalg
)
186 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM
);
191 rv
= SecKeyGetCSPHandle(pk
, &csp
);
193 PORT_SetError(SEC_ERROR_BAD_KEY
);
196 rv
= SecKeyGetCSSMKey(pk
, &key
);
198 PORT_SetError(SEC_ERROR_BAD_KEY
);
201 rv
= SecKeyGetCredentials(pk
, CSSM_ACL_AUTHORIZATION_SIGN
, kSecCredentialTypeDefault
, &accessCred
);
203 PORT_SetError(SEC_ERROR_BAD_KEY
);
207 rv
= CSSM_CSP_CreateSignatureContext(csp
, sigalg
, accessCred
, key
, &cc
);
209 PORT_SetError(SEC_ERROR_NO_MEMORY
);
213 rv
= CSSM_SignData(cc
, digest
, 1, digalg
, &sig
);
216 if (CSSM_ERRCODE(rv
) == CSSM_ERRCODE_USER_CANCELED
217 || CSSM_ERRCODE(rv
) == CSSM_ERRCODE_OPERATION_AUTH_DENIED
)
218 code
= SEC_ERROR_USER_CANCELLED
;
219 else if (CSSM_ERRCODE(rv
) == CSSM_ERRCODE_NO_USER_INTERACTION
220 || rv
== CSSMERR_CSP_KEY_USAGE_INCORRECT
)
221 code
= SEC_ERROR_INADEQUATE_KEY_USAGE
;
223 code
= SEC_ERROR_LIBRARY_FAILURE
;
229 result
->Length
= sig
.Length
;
230 result
->Data
= sig
.Data
;
234 CSSM_DeleteContext(cc
);
240 VFY_VerifyData(unsigned char *buf
, int len
,
241 SecPublicKeyRef pk
, SecAsn1Item
*sig
,
242 SECOidTag digAlgTag
, SECOidTag sigAlgTag
, void *wincx
)
245 CSSM_ALGORITHMS algorithm
;
246 CSSM_CC_HANDLE cc
= 0;
248 OSStatus rv
= SECFailure
;
249 SecAsn1Item dataBuf
= { (uint32
)len
, (uint8_t *)buf
};
252 algTag
= SecCmsUtilMakeSignatureAlgorithm(digAlgTag
, sigAlgTag
);
253 algorithm
= SECOID_FindyCssmAlgorithmByTag(algTag
);
256 rv
= algTag
== SEC_OID_UNKNOWN
? SecCmsVSSignatureAlgorithmUnknown
: SecCmsVSSignatureAlgorithmUnsupported
;
260 rv
= SecKeyGetCSPHandle(pk
, &csp
);
263 rv
= SecKeyGetCSSMKey(pk
, &key
);
267 rv
= CSSM_CSP_CreateSignatureContext(csp
, algorithm
, NULL
, key
, &cc
);
271 rv
= CSSM_VerifyData(cc
, &dataBuf
, 1, CSSM_ALGID_NONE
, sig
);
275 CSSM_DeleteContext(cc
);
281 VFY_VerifyDigest(SecAsn1Item
*digest
, SecPublicKeyRef pk
,
282 SecAsn1Item
*sig
, SECOidTag digAlgTag
, SECOidTag sigAlgTag
, void *wincx
)
284 CSSM_ALGORITHMS sigalg
, digalg
;
285 CSSM_CC_HANDLE cc
= 0;
290 digalg
= SECOID_FindyCssmAlgorithmByTag(digAlgTag
);
291 sigalg
= SECOID_FindyCssmAlgorithmByTag(sigAlgTag
);
292 if (!digalg
|| !sigalg
)
294 rv
= digAlgTag
== SEC_OID_UNKNOWN
|| sigAlgTag
== SEC_OID_UNKNOWN
? SecCmsVSSignatureAlgorithmUnknown
: SecCmsVSSignatureAlgorithmUnsupported
;
298 rv
= SecKeyGetCSPHandle(pk
, &csp
);
301 rv
= SecKeyGetCSSMKey(pk
, &key
);
305 rv
= CSSM_CSP_CreateSignatureContext(csp
, sigalg
, NULL
, key
, &cc
);
309 rv
= CSSM_VerifyData(cc
, digest
, 1, digalg
, sig
);
313 CSSM_DeleteContext(cc
);
319 WRAP_PubWrapSymKey(SecPublicKeyRef publickey
,
320 SecSymmetricKeyRef bulkkey
,
321 SecAsn1Item
* encKey
)
323 CSSM_WRAP_KEY wrappedKey
= {};
324 //CSSM_WRAP_KEY wrappedPk = {}
326 CSSM_CC_HANDLE cc
= 0;
327 CSSM_CSP_HANDLE pkCsp
, bkCsp
;
328 const CSSM_KEY
*pk
, *bk
, *pubkey
;
330 CSSM_ACCESS_CREDENTIALS accessCred
= {};
332 rv
= SecKeyGetCSPHandle(publickey
, &pkCsp
);
335 rv
= SecKeyGetCSSMKey(publickey
, &pk
);
339 rv
= SecKeyGetCSPHandle(bulkkey
, &bkCsp
);
342 rv
= SecKeyGetCSSMKey(bulkkey
, &bk
);
349 /* We need to get the publickey out of it's pkCsp and into the bkCsp so we can operate with it. */
351 /* Make a NULL wrap symmetric context to extract the public key from pkCsp. */
352 rv
= CSSM_CSP_CreateSymmetricContext(pkCsp
,
355 NULL
, /* accessCred */
363 rv
= CSSM_WrapKey(cc
,
364 NULL
/* accessCred */,
366 NULL
/* descriptiveData */,
368 CSSM_DeleteContext(cc
);
371 /* Make a NULL unwrap symmetric context to import the public key into bkCsp. */
372 rv
= CSSM_CSP_CreateSymmetricContext(bkCsp
,
375 NULL
, /* accessCred */
383 rv
= CSSM_UnwrapKey(cc
, NULL
, &wrappedPk
, usage
, attr
, NULL
/* label */, NULL
/* rcc */, &upk
, NULL
/* descriptiveData */);
384 CSSM_DeleteContext(cc
);
390 rv
= CSSM_CSP_CreateAsymmetricContext(bkCsp
,
391 pubkey
->KeyHeader
.AlgorithmId
,
400 /* Set the wrapped key format to indicate we want just the raw bits encrypted. */
401 CSSM_CONTEXT_ATTRIBUTE contextAttribute
= { CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT
, sizeof(uint32
) };
402 contextAttribute
.Attribute
.Uint32
= CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
;
403 rv
= CSSM_UpdateContextAttributes(cc
, 1, &contextAttribute
);
409 /* Set the mode to CSSM_ALGMODE_PKCS1_EME_V15. */
410 CSSM_CONTEXT_ATTRIBUTE contextAttribute
= { CSSM_ATTRIBUTE_MODE
, sizeof(uint32
) };
411 contextAttribute
.Attribute
.Uint32
= CSSM_ALGMODE_NONE
; /* CSSM_ALGMODE_PKCS1_EME_V15 */
412 rv
= CSSM_UpdateContextAttributes(cc
, 1, &contextAttribute
);
418 // @@@ Stick in an empty initVector to work around a csp bug.
419 SecAsn1Item initVector
= {};
420 CSSM_CONTEXT_ATTRIBUTE contextAttribute
= { CSSM_ATTRIBUTE_INIT_VECTOR
, sizeof(SecAsn1Item
*) };
421 contextAttribute
.Attribute
.Data
= &initVector
;
422 rv
= CSSM_UpdateContextAttributes(cc
, 1, &contextAttribute
);
427 rv
= CSSM_WrapKey(cc
,
430 NULL
, /* descriptiveData */
436 if (encKey
->Length
< wrappedKey
.KeyData
.Length
)
438 encKey
->Length
= wrappedKey
.KeyData
.Length
;
439 memcpy(encKey
->Data
, wrappedKey
.KeyData
.Data
, encKey
->Length
);
440 CSSM_FreeKey(bkCsp
, NULL
/* credentials */, &wrappedKey
, FALSE
);
444 CSSM_DeleteContext(cc
);
450 WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey
, const SecAsn1Item
*encKey
, SECOidTag bulkalgtag
)
452 SecSymmetricKeyRef bulkkey
= NULL
;
453 CSSM_WRAP_KEY wrappedKey
= {};
454 CSSM_CC_HANDLE cc
= 0;
455 CSSM_CSP_HANDLE pkCsp
;
457 CSSM_KEY unwrappedKey
= {};
458 const CSSM_ACCESS_CREDENTIALS
*accessCred
;
459 SecAsn1Item descriptiveData
= {};
460 CSSM_ALGORITHMS bulkalg
;
463 rv
= SecKeyGetCSPHandle(privkey
, &pkCsp
);
466 rv
= SecKeyGetCSSMKey(privkey
, &pk
);
469 rv
= SecKeyGetCredentials(privkey
,
470 CSSM_ACL_AUTHORIZATION_DECRYPT
, /* @@@ Should be UNWRAP */
471 kSecCredentialTypeDefault
,
476 bulkalg
= SECOID_FindyCssmAlgorithmByTag(bulkalgtag
);
479 rv
= SEC_ERROR_INVALID_ALGORITHM
;
483 rv
= CSSM_CSP_CreateAsymmetricContext(pkCsp
,
484 pk
->KeyHeader
.AlgorithmId
,
493 // @@@ Stick in an empty initvector to work around a csp bug.
494 SecAsn1Item initVector
= {};
495 CSSM_CONTEXT_ATTRIBUTE contextAttribute
= { CSSM_ATTRIBUTE_INIT_VECTOR
, sizeof(SecAsn1Item
*) };
496 contextAttribute
.Attribute
.Data
= &initVector
;
497 rv
= CSSM_UpdateContextAttributes(cc
, 1, &contextAttribute
);
502 wrappedKey
.KeyHeader
.HeaderVersion
= CSSM_KEYHEADER_VERSION
;
503 wrappedKey
.KeyHeader
.BlobType
= CSSM_KEYBLOB_WRAPPED
;
504 wrappedKey
.KeyHeader
.Format
= CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7
;
505 wrappedKey
.KeyHeader
.AlgorithmId
= bulkalg
;
506 wrappedKey
.KeyHeader
.KeyClass
= CSSM_KEYCLASS_SESSION_KEY
;
507 wrappedKey
.KeyHeader
.WrapAlgorithmId
= pk
->KeyHeader
.AlgorithmId
;
508 wrappedKey
.KeyHeader
.WrapMode
= CSSM_ALGMODE_NONE
; /* CSSM_ALGMODE_PKCS1_EME_V15 */
509 wrappedKey
.KeyData
= *encKey
;
511 rv
= CSSM_UnwrapKey(cc
,
512 NULL
, /* publicKey */
515 CSSM_KEYATTR_EXTRACTABLE
/* | CSSM_KEYATTR_RETURN_DATA */,
522 if (CSSM_ERRCODE(rv
) == CSSM_ERRCODE_USER_CANCELED
523 || CSSM_ERRCODE(rv
) == CSSM_ERRCODE_OPERATION_AUTH_DENIED
)
524 code
= SEC_ERROR_USER_CANCELLED
;
525 else if (CSSM_ERRCODE(rv
) == CSSM_ERRCODE_NO_USER_INTERACTION
526 || rv
== CSSMERR_CSP_KEY_USAGE_INCORRECT
)
527 code
= SEC_ERROR_INADEQUATE_KEY_USAGE
;
529 code
= SEC_ERROR_LIBRARY_FAILURE
;
535 // @@@ Export this key from the csp/dl and import it to the standard csp
536 rv
= SecKeyCreate(&unwrappedKey
, &bulkkey
);
545 CSSM_DeleteContext(cc
);