]> git.saurik.com Git - apple/security.git/blob - AppleCSP/RSA_DSA/RSA_DSA_utils.cpp
Security-30.1.tar.gz
[apple/security.git] / AppleCSP / RSA_DSA / RSA_DSA_utils.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 * RSA_DSA_utils.cpp
21 */
22
23 #include "RSA_DSA_utils.h"
24 #include "RSA_DSA_keys.h"
25 #include <opensslUtils/openRsaSnacc.h>
26 #include <Security/logging.h>
27 #include <Security/debugging.h>
28 #include <open_ssl/opensslUtils/opensslUtils.h>
29 #include <openssl/bn.h>
30 #include <openssl/rsa.h>
31 #include <openssl/dsa.h>
32 #include <openssl/err.h>
33
34 #define rsaMiscDebug(args...) debug("rsaMisc", ## args)
35
36 void throwRsaDsa(
37 const char *op)
38 {
39 unsigned long e = logSslErrInfo(op);
40 CSSM_RETURN cerr = CSSM_OK;
41
42 /* try to parse into something meaningful */
43 int reason = ERR_GET_REASON(e);
44 int lib = ERR_GET_LIB(e);
45
46 /* first try the global ones */
47 switch(reason) {
48 case ERR_R_MALLOC_FAILURE:
49 cerr = CSSMERR_CSP_MEMORY_ERROR; break;
50 case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED:
51 /* internal */ break;
52 case ERR_R_PASSED_NULL_PARAMETER:
53 cerr = CSSMERR_CSP_INVALID_POINTER; break;
54 case ERR_R_NESTED_ASN1_ERROR:
55 case ERR_R_BAD_ASN1_OBJECT_HEADER:
56 case ERR_R_BAD_GET_ASN1_OBJECT_CALL:
57 case ERR_R_EXPECTING_AN_ASN1_SEQUENCE:
58 case ERR_R_ASN1_LENGTH_MISMATCH:
59 case ERR_R_MISSING_ASN1_EOS:
60 /* ASN - shouldn't happen, right? */
61 cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
62 default:
63 break;
64 }
65 if(cerr != CSSM_OK) {
66 CssmError::throwMe(cerr);
67 }
68
69 /* now the lib-specific ones */
70 switch(lib) {
71 case ERR_R_BN_LIB:
72 /* all indicate serious internal error...right? */
73 cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
74 case ERR_R_RSA_LIB:
75 switch(reason) {
76 case RSA_R_ALGORITHM_MISMATCH:
77 cerr = CSSMERR_CSP_ALGID_MISMATCH; break;
78 case RSA_R_BAD_SIGNATURE:
79 cerr = CSSMERR_CSP_VERIFY_FAILED; break;
80 case RSA_R_DATA_TOO_LARGE:
81 case RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
82 case RSA_R_DATA_TOO_SMALL:
83 case RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE:
84 case RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY:
85 cerr = CSSMERR_CSP_INPUT_LENGTH_ERROR; break;
86 case RSA_R_KEY_SIZE_TOO_SMALL:
87 cerr = CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH; break;
88 case RSA_R_PADDING_CHECK_FAILED:
89 cerr = CSSMERR_CSP_INVALID_DATA; break;
90 case RSA_R_RSA_OPERATIONS_NOT_SUPPORTED:
91 cerr = CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED; break;
92 case RSA_R_UNKNOWN_ALGORITHM_TYPE:
93 cerr = CSSMERR_CSP_INVALID_ALGORITHM; break;
94 case RSA_R_WRONG_SIGNATURE_LENGTH:
95 cerr = CSSMERR_CSP_VERIFY_FAILED; break;
96 default:
97 cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
98 }
99 break;
100 case ERR_R_DSA_LIB:
101 switch(reason) {
102 case DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE:
103 cerr = CSSMERR_CSP_INPUT_LENGTH_ERROR; break;
104 default:
105 cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
106 }
107 break;
108 default:
109 cerr = CSSMERR_CSP_INTERNAL_ERROR; break;
110 }
111 CssmError::throwMe(cerr);
112 }
113
114 /*
115 * given an openssl-style error, throw appropriate CssmError.
116 */
117 void throwOpensslErr(int irtn)
118 {
119 /* FIXME */
120 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
121 }
122
123 /*
124 * Given a Context:
125 * -- obtain CSSM key (there must only be one)
126 * -- validate keyClass
127 * -- validate keyUsage
128 * -- convert to RSA *, allocating the RSA key if necessary
129 */
130 RSA *contextToRsaKey(
131 const Context &context,
132 AppleCSPSession &session,
133 CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
134 CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
135 bool &mallocdKey) // RETURNED
136 {
137 CssmKey &cssmKey =
138 context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
139 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
140 if(hdr.AlgorithmId != CSSM_ALGID_RSA) {
141 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
142 }
143 if(hdr.KeyClass != keyClass) {
144 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
145 }
146 cspValidateIntendedKeyUsage(&hdr, usage);
147 return cssmKeyToRsa(cssmKey, session, mallocdKey);
148 }
149 /*
150 * Convert a CssmKey to an RSA * key. May result in the creation of a new
151 * RSA (when cssmKey is a raw key); allocdKey is true in that case
152 * in which case the caller generally has to free the allocd key).
153 */
154 RSA *cssmKeyToRsa(
155 const CssmKey &cssmKey,
156 AppleCSPSession &session,
157 bool &allocdKey) // RETURNED
158 {
159 RSA *rsaKey = NULL;
160 allocdKey = false;
161
162 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
163 if(hdr->AlgorithmId != CSSM_ALGID_RSA) {
164 // someone else's key (should never happen)
165 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
166 }
167 switch(hdr->BlobType) {
168 case CSSM_KEYBLOB_RAW:
169 rsaKey = rawCssmKeyToRsa(cssmKey);
170 allocdKey = true;
171 break;
172 case CSSM_KEYBLOB_REFERENCE:
173 {
174 BinaryKey &binKey = session.lookupRefKey(cssmKey);
175 RSABinaryKey *rsaBinKey = dynamic_cast<RSABinaryKey *>(&binKey);
176 /* this cast failing means that this is some other
177 * kind of binary key */
178 if(rsaBinKey == NULL) {
179 rsaMiscDebug("cssmKeyToRsa: wrong BinaryKey subclass\n");
180 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
181 }
182 assert(rsaBinKey->mRsaKey != NULL);
183 rsaKey = rsaBinKey->mRsaKey;
184 break;
185 }
186 default:
187 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
188 }
189 return rsaKey;
190 }
191
192 /*
193 * Convert a raw CssmKey to a newly alloc'd RSA key.
194 */
195 RSA *rawCssmKeyToRsa(
196 const CssmKey &cssmKey)
197 {
198 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
199 bool isPub;
200
201 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
202
203 if(hdr->AlgorithmId != CSSM_ALGID_RSA) {
204 // someone else's key (should never happen)
205 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
206 }
207 switch(hdr->KeyClass) {
208 case CSSM_KEYCLASS_PUBLIC_KEY:
209 if(hdr->Format != RSA_PUB_KEY_FORMAT) {
210 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
211 }
212 isPub = true;
213 break;
214 case CSSM_KEYCLASS_PRIVATE_KEY:
215 if(hdr->Format != RSA_PRIV_KEY_FORMAT) {
216 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
217 }
218 isPub = false;
219 break;
220 default:
221 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
222 }
223
224 RSA *rsaKey = RSA_new();
225 if(rsaKey == NULL) {
226 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
227 }
228 CSSM_RETURN crtn;
229 if(isPub) {
230 crtn = RSAPublicKeyDecode(rsaKey,
231 cssmKey.KeyData.Data,
232 cssmKey.KeyData.Length);
233 }
234 else {
235 crtn = RSAPrivateKeyDecode(rsaKey,
236 cssmKey.KeyData.Data,
237 cssmKey.KeyData.Length);
238 }
239 if(crtn) {
240 CssmError::throwMe(crtn);
241 }
242 return rsaKey;
243 }
244
245 /*
246 * Given a Context:
247 * -- obtain CSSM key (there must only be one)
248 * -- validate keyClass
249 * -- validate keyUsage
250 * -- convert to DSA *, allocating the DSA key if necessary
251 */
252 DSA *contextToDsaKey(
253 const Context &context,
254 AppleCSPSession &session,
255 CSSM_KEYCLASS keyClass, // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY
256 CSSM_KEYUSE usage, // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
257 bool &mallocdKey) // RETURNED
258 {
259 CssmKey &cssmKey =
260 context.get<CssmKey>(CSSM_ATTRIBUTE_KEY, CSSMERR_CSP_MISSING_ATTR_KEY);
261 const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader;
262 if(hdr.AlgorithmId != CSSM_ALGID_DSA) {
263 CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
264 }
265 if(hdr.KeyClass != keyClass) {
266 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
267 }
268 cspValidateIntendedKeyUsage(&hdr, usage);
269 return cssmKeyToDsa(cssmKey, session, mallocdKey);
270 }
271 /*
272 * Convert a CssmKey to an DSA * key. May result in the creation of a new
273 * DSA (when cssmKey is a raw key); allocdKey is true in that case
274 * in which case the caller generally has to free the allocd key).
275 */
276 DSA *cssmKeyToDsa(
277 const CssmKey &cssmKey,
278 AppleCSPSession &session,
279 bool &allocdKey) // RETURNED
280 {
281 DSA *dsaKey = NULL;
282 allocdKey = false;
283
284 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
285 if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
286 // someone else's key (should never happen)
287 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
288 }
289 switch(hdr->BlobType) {
290 case CSSM_KEYBLOB_RAW:
291 dsaKey = rawCssmKeyToDsa(cssmKey);
292 allocdKey = true;
293 break;
294 case CSSM_KEYBLOB_REFERENCE:
295 {
296 BinaryKey &binKey = session.lookupRefKey(cssmKey);
297 DSABinaryKey *dsaBinKey = dynamic_cast<DSABinaryKey *>(&binKey);
298 /* this cast failing means that this is some other
299 * kind of binary key */
300 if(dsaBinKey == NULL) {
301 rsaMiscDebug("cssmKeyToDsa: wrong BinaryKey subclass\n");
302 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
303 }
304 assert(dsaBinKey->mDsaKey != NULL);
305 dsaKey = dsaBinKey->mDsaKey;
306 break;
307 }
308 default:
309 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
310 }
311 return dsaKey;
312 }
313
314 /*
315 * Convert a raw CssmKey to a newly alloc'd DSA key.
316 */
317 DSA *rawCssmKeyToDsa(
318 const CssmKey &cssmKey)
319 {
320 const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
321 bool isPub;
322
323 assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
324
325 if(hdr->AlgorithmId != CSSM_ALGID_DSA) {
326 // someone else's key (should never happen)
327 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
328 }
329 switch(hdr->KeyClass) {
330 case CSSM_KEYCLASS_PUBLIC_KEY:
331 if(hdr->Format != DSA_PUB_KEY_FORMAT) {
332 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
333 }
334 isPub = true;
335 break;
336 case CSSM_KEYCLASS_PRIVATE_KEY:
337 if(hdr->Format != DSA_PRIV_KEY_FORMAT) {
338 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
339 }
340 isPub = false;
341 break;
342 default:
343 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
344 }
345
346 DSA *dsaKey = DSA_new();
347 if(dsaKey == NULL) {
348 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
349 }
350 CSSM_RETURN crtn;
351 if(isPub) {
352 crtn = DSAPublicKeyDecode(dsaKey,
353 cssmKey.KeyData.Data,
354 cssmKey.KeyData.Length);
355 }
356 else {
357 crtn = DSAPrivateKeyDecode(dsaKey,
358 cssmKey.KeyData.Data,
359 cssmKey.KeyData.Length);
360 }
361 if(crtn) {
362 CssmError::throwMe(crtn);
363 }
364 return dsaKey;
365 }