2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
20 * FEECSPUtils.h - Misc. utility function for FEE/CryptKit CSP.
22 * Created 2/20/2001 by dmitch.
25 #ifdef CRYPTKIT_CSP_ENABLE
27 #include <security_utilities/debugging.h>
28 #include <security_utilities/logging.h>
29 #include "FEECSPUtils.h"
31 #include <security_cryptkit/feeFunctions.h>
32 #include <security_cryptkit/feePublicKey.h>
34 #define feeMiscDebug(args...) secdebug("feeMisc", ## args)
36 /* Given a FEE error, throw appropriate CssmError */
37 void CryptKit::throwCryptKit(
39 const char *op
) /* optional */
42 Security::Syslog::error("Apple CSP %s: %s", op
, feeReturnString(frtn
));
48 case FR_BadPubKeyString
:
49 case FR_IncompatibleKey
:
51 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
53 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE
);
54 case FR_BadSignatureFormat
: /* signature corrupted */
55 CssmError::throwMe(CSSMERR_CSP_INVALID_SIGNATURE
);
56 case FR_InvalidSignature
: /* signature intact, but not valid */
57 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
58 case FR_IllegalArg
: /* illegal argument */
59 CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT
);
60 case FR_BadCipherText
: /* malformed ciphertext */
61 case FR_BadEnc64
: /* bad enc64() format */
62 CssmError::throwMe(CSSMERR_CSP_INVALID_DATA
);
63 case FR_Unimplemented
: /* unimplemented function */
64 CssmError::throwMe(CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED
);
65 case FR_Memory
: /* unimplemented function */
66 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
67 case FR_ShortPrivData
:
68 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED
);
69 case FR_IllegalCurve
: /* e.g., ECDSA with Montgomery curve */
70 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY
);
72 /* I don't think we should ever see these no matter what the
73 * caller throws at us */
74 case FR_WrongSignatureType
: /* ElGamal vs. ECDSA */
75 case FR_BadUsageName
: /* bad usageName */
76 case FR_BadCipherFile
:
77 case FR_Internal
: /* internal library error */
78 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
84 * -- obtain CSSM key of specified CSSM_ATTRIBUTE_TYPE
85 * -- validate keyClass
86 * -- validate keyUsage
87 * -- convert to feePubKey, allocating the feePubKey if necessary
89 * Returned key can be of algorithm CSSM_ALGID_ECDSA or CSSM_ALGID_FEE;
90 * caller has to verify proper algorithm for operation.
92 feePubKey
CryptKit::contextToFeeKey(
93 const Context
&context
,
94 AppleCSPSession
&session
,
95 CSSM_ATTRIBUTE_TYPE attrType
, // CSSM_ATTRIBUTE_KEY, CSSM_ATTRIBUTE_PUBLIC_KEY
96 CSSM_KEYCLASS keyClass
, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
97 CSSM_KEYUSE usage
, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
98 bool &mallocdKey
) // RETURNED
101 context
.get
<CssmKey
>(attrType
, CSSMERR_CSP_MISSING_ATTR_KEY
);
102 const CSSM_KEYHEADER
&hdr
= cssmKey
.KeyHeader
;
103 switch(hdr
.AlgorithmId
) {
105 case CSSM_ALGID_ECDSA
:
108 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH
);
110 if(hdr
.KeyClass
!= keyClass
) {
111 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
113 cspValidateIntendedKeyUsage(&hdr
, usage
);
114 cspVerifyKeyTimes(hdr
);
115 return cssmKeyToFee(cssmKey
, session
, mallocdKey
);
119 * Convert a CssmKey to a feePubKey. May result in the creation of a new
120 * feePubKey (when cssmKey is a raw key); allocdKey is true in that case
121 * in which case the caller generally has to free the allocd key).
123 feePubKey
CryptKit::cssmKeyToFee(
124 const CssmKey
&cssmKey
,
125 AppleCSPSession
&session
,
126 bool &allocdKey
) // RETURNED
128 feePubKey feeKey
= NULL
;
131 const CSSM_KEYHEADER
*hdr
= &cssmKey
.KeyHeader
;
132 switch(hdr
->AlgorithmId
) {
134 case CSSM_ALGID_ECDSA
:
137 // someone else's key (should never happen)
138 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
140 switch(hdr
->BlobType
) {
141 case CSSM_KEYBLOB_RAW
:
142 feeKey
= rawCssmKeyToFee(cssmKey
);
145 case CSSM_KEYBLOB_REFERENCE
:
147 BinaryKey
&binKey
= session
.lookupRefKey(cssmKey
);
148 FEEBinaryKey
*feeBinKey
= dynamic_cast<FEEBinaryKey
*>(&binKey
);
149 /* this cast failing means that this is some other
150 * kind of binary key */
151 if(feeBinKey
== NULL
) {
152 feeMiscDebug("CryptKit::cssmKeyToFee: wrong BinaryKey subclass\n");
153 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
155 assert(feeBinKey
->feeKey() != NULL
);
156 feeKey
= feeBinKey
->feeKey();
160 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
166 * Convert a raw CssmKey to a newly alloc'd feePubKey.
168 feePubKey
CryptKit::rawCssmKeyToFee(
169 const CssmKey
&cssmKey
)
171 const CSSM_KEYHEADER
*hdr
= &cssmKey
.KeyHeader
;
172 assert(hdr
->BlobType
== CSSM_KEYBLOB_RAW
);
174 switch(hdr
->AlgorithmId
) {
176 case CSSM_ALGID_ECDSA
:
179 // someone else's key (should never happen)
180 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
183 switch(hdr
->KeyClass
) {
184 case CSSM_KEYCLASS_PUBLIC_KEY
:
185 case CSSM_KEYCLASS_PRIVATE_KEY
:
188 // someone else's key
189 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
192 feePubKey feeKey
= feePubKeyAlloc();
194 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
197 feeReturn frtn
= FR_IllegalArg
;
198 bool badFormat
= false;
201 * The actual key init depends on key type and incoming format
203 switch(hdr
->AlgorithmId
) {
205 switch(hdr
->KeyClass
) {
206 case CSSM_KEYCLASS_PUBLIC_KEY
:
207 switch(hdr
->Format
) {
208 case FEE_KEYBLOB_DEFAULT_FORMAT
:
209 /* FEE, public key, default: custom DER */
210 frtn
= feePubKeyInitFromDERPubBlob(feeKey
,
211 cssmKey
.KeyData
.Data
,
212 cssmKey
.KeyData
.Length
);
214 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
:
215 /* FEE, public key, native byte stream */
216 frtn
= feePubKeyInitFromPubBlob(feeKey
,
217 cssmKey
.KeyData
.Data
,
218 cssmKey
.KeyData
.Length
);
225 case CSSM_KEYCLASS_PRIVATE_KEY
:
226 switch(hdr
->Format
) {
227 case FEE_KEYBLOB_DEFAULT_FORMAT
:
228 /* FEE, private key, default: custom DER */
229 frtn
= feePubKeyInitFromDERPrivBlob(feeKey
,
230 cssmKey
.KeyData
.Data
,
231 cssmKey
.KeyData
.Length
);
233 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
:
234 /* FEE, private key, native byte stream */
235 frtn
= feePubKeyInitFromPrivBlob(feeKey
,
236 cssmKey
.KeyData
.Data
,
237 cssmKey
.KeyData
.Length
);
245 /* not reached, we already checked */
248 /* end of case ALGID_FEE */
251 case CSSM_ALGID_ECDSA
:
252 switch(hdr
->KeyClass
) {
253 case CSSM_KEYCLASS_PUBLIC_KEY
:
254 switch(hdr
->Format
) {
255 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
256 case CSSM_KEYBLOB_RAW_FORMAT_X509
:
257 /* ECDSA, public key, default: X509 */
258 frtn
= feePubKeyInitFromX509Blob(feeKey
,
259 cssmKey
.KeyData
.Data
,
260 cssmKey
.KeyData
.Length
);
263 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
:
265 * An oddity here: we can parse this incoming key, but
266 * it contains both private and public parts. We throw
267 * out the private component here.
269 frtn
= feePubKeyInitFromOpenSSLBlob(feeKey
,
271 cssmKey
.KeyData
.Data
,
272 cssmKey
.KeyData
.Length
);
275 * NOTE: we cannot *import* a key in raw X9.62 format.
276 * We'd need to know the curve, i.e., the feeDepth.
277 * I suppose we could infer that from the blob length but
278 * a better way would be to have a new context attribute
279 * specifying which curve.
280 * For now, imported raw keys have to be in X509 format.
282 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
:
288 case CSSM_KEYCLASS_PRIVATE_KEY
:
289 switch(hdr
->Format
) {
290 case CSSM_KEYBLOB_RAW_FORMAT_PKCS8
:
291 /* ECDSA, private key, PKCS8 */
292 frtn
= feePubKeyInitFromPKCS8Blob(feeKey
,
293 cssmKey
.KeyData
.Data
,
294 cssmKey
.KeyData
.Length
);
297 case CSSM_KEYBLOB_RAW_FORMAT_NONE
:
298 case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
:
299 /* ECDSA, private, default: OpenSSL */
300 /* see comment above re: OpenSSL public/private keys */
301 frtn
= feePubKeyInitFromOpenSSLBlob(feeKey
,
303 cssmKey
.KeyData
.Data
,
304 cssmKey
.KeyData
.Length
);
306 /* see comment above about X9.62 format public key blobs */
307 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
:
314 /* not reached, we already checked */
317 /* end of case CSSM_ALGID_ECDSA */
321 CssmError::throwMe(hdr
->KeyClass
== CSSM_KEYCLASS_PRIVATE_KEY
?
322 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT
:
323 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT
);
326 feePubKeyFree(feeKey
);
327 throwCryptKit(frtn
, "feePubKeyInitFromKeyBlob");
333 * Glue function which allows C code to use AppleCSPSession
334 * as an RNG. A ptr to this function gets passed down to
335 * CryptKit C functions as a feeRandFcn.
337 feeReturn
CryptKit::feeRandCallback(
338 void *ref
, // actually an AppleCSPSession *
339 unsigned char *bytes
, // must be alloc'd by caller
342 AppleCSPSession
*session
=
343 reinterpret_cast<AppleCSPSession
*>(ref
);
345 session
->getRandomBytes(numBytes
, bytes
);
353 #endif /* CRYPTKIT_CSP_ENABLE */