]> git.saurik.com Git - apple/security.git/blob - AppleCSP/CryptKitCSP/FEECSPUtils.cpp
Security-28.tar.gz
[apple/security.git] / AppleCSP / CryptKitCSP / FEECSPUtils.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 /*
20 * FEECSPUtils.h - Misc. utility function for FEE/CryptKit CSP.
21 *
22 * Created 2/20/2001 by dmitch.
23 */
24
25 #ifdef CRYPTKIT_CSP_ENABLE
26
27 #include <Security/utilities.h>
28 #include <Security/debugging.h>
29 #include <Security/logging.h>
30 #include "FEECSPUtils.h"
31 #include "FEEKeys.h"
32 #include <CryptKit/feeFunctions.h>
33 #include <CryptKit/feePublicKey.h>
34
35 #define feeMiscDebug(args...) debug("feeMisc", ## args)
36
37 /* Given a FEE error, throw appropriate CssmError */
38 void CryptKit::throwCryptKit(
39 feeReturn frtn,
40 const char *op) /* optional */
41 {
42 if(op) {
43 Security::Syslog::error("Apple CSP %s: %s", op, feeReturnString(frtn));
44 }
45 switch(frtn) {
46 case FR_Success:
47 return;
48 case FR_BadPubKey:
49 case FR_BadPubKeyString:
50 case FR_IncompatibleKey:
51 case FR_BadKeyBlob:
52 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
53 case FR_IllegalDepth:
54 CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
55 case FR_BadSignatureFormat: /* signature corrupted */
56 CssmError::throwMe(CSSMERR_CSP_INVALID_SIGNATURE);
57 case FR_InvalidSignature: /* signature intact, but not valid */
58 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
59 case FR_IllegalArg: /* illegal argument */
60 CssmError::throwMe(CSSMERR_CSP_INVALID_CONTEXT);
61 case FR_BadCipherText: /* malformed ciphertext */
62 case FR_BadEnc64: /* bad enc64() format */
63 CssmError::throwMe(CSSMERR_CSP_INVALID_DATA);
64 case FR_Unimplemented: /* unimplemented function */
65 CssmError::throwMe(CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED);
66 case FR_Memory: /* unimplemented function */
67 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
68 case FR_ShortPrivData:
69 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_SEED);
70 case FR_IllegalCurve: /* e.g., ECDSA with Montgomery curve */
71 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
72
73 /* I don't think we should ever see these no matter what the
74 * caller throws at us */
75 case FR_WrongSignatureType: /* ElGamal vs. ECDSA */
76 case FR_BadUsageName: /* bad usageName */
77 case FR_BadCipherFile:
78 case FR_Internal: /* internal library error */
79 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
80 }
81 }
82
83 /*
84 * Given a Context:
85 * -- obtain CSSM key of specified CSSM_ATTRIBUTE_TYPE
86 * -- validate keyClass
87 * -- validate keyUsage
88 * -- convert to feePubKey, allocating the feePubKey if necessary
89 */
90 feePubKey CryptKit::contextToFeeKey(
91 const Context &context,
92 AppleCSPSession &session,
93 CSSM_ATTRIBUTE_TYPE attrType, // CSSM_ATTRIBUTE_KEY, CSSM_ATTRIBUTE_PUBLIC_KEY
94 CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
95 CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
96 bool &mallocdKey) // RETURNED
97 {
98 CssmKey &cssmKey =
99 context.get<CssmKey>(attrType, CSSMERR_CSP_MISSING_ATTR_KEY);
100 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
101 if(hdr.AlgorithmId != CSSM_ALGID_FEE) {
102 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
103 }
104 if(hdr.KeyClass != keyClass) {
105 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
106 }
107 cspValidateIntendedKeyUsage(&hdr, usage);
108 return cssmKeyToFee(cssmKey, session, mallocdKey);
109 }
110
111 /*
112 * Convert a CssmKey to a feePubKey. May result in the creation of a new
113 * feePubKey (when cssmKey is a raw key); allocdKey is true in that case
114 * in which case the caller generally has to free the allocd key).
115 */
116 feePubKey CryptKit::cssmKeyToFee(
117 const CssmKey &cssmKey,
118 AppleCSPSession &session,
119 bool &allocdKey) // RETURNED
120 {
121 feePubKey feeKey = NULL;
122 allocdKey = false;
123
124 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
125 if(hdr->AlgorithmId != CSSM_ALGID_FEE) {
126 // someone else's key (should never happen)
127 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
128 }
129 switch(hdr->BlobType) {
130 case CSSM_KEYBLOB_RAW:
131 feeKey = rawCssmKeyToFee(cssmKey);
132 allocdKey = true;
133 break;
134 case CSSM_KEYBLOB_REFERENCE:
135 {
136 BinaryKey &binKey = session.lookupRefKey(cssmKey);
137 FEEBinaryKey *feeBinKey = dynamic_cast<FEEBinaryKey *>(&binKey);
138 /* this cast failing means that this is some other
139 * kind of binary key */
140 if(feeBinKey == NULL) {
141 feeMiscDebug("CryptKit::cssmKeyToFee: wrong BinaryKey subclass\n");
142 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
143 }
144 assert(feeBinKey->feeKey() != NULL);
145 feeKey = feeBinKey->feeKey();
146 break;
147 }
148 default:
149 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
150 }
151 return feeKey;
152 }
153
154 /*
155 * Convert a raw CssmKey to a newly alloc'd feePubKey.
156 */
157 feePubKey CryptKit::rawCssmKeyToFee(
158 const CssmKey &cssmKey)
159 {
160 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
161 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
162
163 if(hdr->AlgorithmId != CSSM_ALGID_FEE) {
164 // someone else's key (should never happen)
165 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
166 }
167 bool derBlob;
168 switch(hdr->Format) {
169 case FEE_KEYBLOB_DEFAULT_FORMAT:
170 derBlob = true;
171 break;
172 case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
173 derBlob = false;
174 break;
175 default:
176 feeMiscDebug("CryptKit::rawCssmKeyToFee: format mismatch\n");
177 CssmError::throwMe(hdr->KeyClass == CSSM_KEYCLASS_PRIVATE_KEY ?
178 CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
179 CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
180 }
181 switch(hdr->KeyClass) {
182 case CSSM_KEYCLASS_PUBLIC_KEY:
183 case CSSM_KEYCLASS_PRIVATE_KEY:
184 break;
185 default:
186 // someone else's key
187 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
188 }
189
190 feePubKey feeKey = feePubKeyAlloc();
191 if(feeKey == NULL) {
192 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
193 }
194 feeReturn frtn = FR_Internal;
195 switch(hdr->KeyClass) {
196 case CSSM_KEYCLASS_PUBLIC_KEY:
197 if(derBlob) {
198 frtn = feePubKeyInitFromDERPubBlob(feeKey,
199 cssmKey.KeyData.Data,
200 cssmKey.KeyData.Length);
201 }
202 else {
203 frtn = feePubKeyInitFromPubBlob(feeKey,
204 cssmKey.KeyData.Data,
205 cssmKey.KeyData.Length);
206 }
207 break;
208 case CSSM_KEYCLASS_PRIVATE_KEY:
209 if(derBlob) {
210 frtn = feePubKeyInitFromDERPrivBlob(feeKey,
211 cssmKey.KeyData.Data,
212 cssmKey.KeyData.Length);
213 }
214 else {
215 frtn = feePubKeyInitFromPrivBlob(feeKey,
216 cssmKey.KeyData.Data,
217 cssmKey.KeyData.Length);
218 }
219 }
220 if(frtn) {
221 feePubKeyFree(feeKey);
222 throwCryptKit(frtn, "feePubKeyInitFromKeyBlob");
223 }
224 return feeKey;
225 }
226
227 /*
228 * Glue function which allows C code to use AppleCSPSession
229 * as an RNG. A ptr to this function gets passed down to
230 * CryptKit C functions as a feeRandFcn.
231 */
232 feeReturn CryptKit::feeRandCallback(
233 void *ref, // actually an AppleCSPSession *
234 unsigned char *bytes, // must be alloc'd by caller
235 unsigned numBytes)
236 {
237 AppleCSPSession *session =
238 reinterpret_cast<AppleCSPSession *>(ref);
239 try {
240 session->getRandomBytes(numBytes, bytes);
241 }
242 catch(...) {
243 return FR_Internal;
244 }
245 return FR_Success;
246 }
247
248 #endif /* CRYPTKIT_CSP_ENABLE */