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.
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>
34 #define rsaMiscDebug(args...) debug("rsaMisc", ## args)
39 unsigned long e
= logSslErrInfo(op
);
40 CSSM_RETURN cerr
= CSSM_OK
;
42 /* try to parse into something meaningful */
43 int reason
= ERR_GET_REASON(e
);
44 int lib
= ERR_GET_LIB(e
);
46 /* first try the global ones */
48 case ERR_R_MALLOC_FAILURE
:
49 cerr
= CSSMERR_CSP_MEMORY_ERROR
; break;
50 case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
:
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;
66 CssmError::throwMe(cerr
);
69 /* now the lib-specific ones */
72 /* all indicate serious internal error...right? */
73 cerr
= CSSMERR_CSP_INTERNAL_ERROR
; break;
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;
97 cerr
= CSSMERR_CSP_INTERNAL_ERROR
; break;
102 case DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE
:
103 cerr
= CSSMERR_CSP_INPUT_LENGTH_ERROR
; break;
105 cerr
= CSSMERR_CSP_INTERNAL_ERROR
; break;
109 cerr
= CSSMERR_CSP_INTERNAL_ERROR
; break;
111 CssmError::throwMe(cerr
);
115 * given an openssl-style error, throw appropriate CssmError.
117 void throwOpensslErr(int irtn
)
120 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
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
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
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
);
143 if(hdr
.KeyClass
!= keyClass
) {
144 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
146 cspValidateIntendedKeyUsage(&hdr
, usage
);
147 return cssmKeyToRsa(cssmKey
, session
, mallocdKey
);
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).
155 const CssmKey
&cssmKey
,
156 AppleCSPSession
&session
,
157 bool &allocdKey
) // RETURNED
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
);
167 switch(hdr
->BlobType
) {
168 case CSSM_KEYBLOB_RAW
:
169 rsaKey
= rawCssmKeyToRsa(cssmKey
);
172 case CSSM_KEYBLOB_REFERENCE
:
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
);
182 assert(rsaBinKey
->mRsaKey
!= NULL
);
183 rsaKey
= rsaBinKey
->mRsaKey
;
187 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
193 * Convert a raw CssmKey to a newly alloc'd RSA key.
195 RSA
*rawCssmKeyToRsa(
196 const CssmKey
&cssmKey
)
198 const CSSM_KEYHEADER
*hdr
= &cssmKey
.KeyHeader
;
201 assert(hdr
->BlobType
== CSSM_KEYBLOB_RAW
);
203 if(hdr
->AlgorithmId
!= CSSM_ALGID_RSA
) {
204 // someone else's key (should never happen)
205 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
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
);
214 case CSSM_KEYCLASS_PRIVATE_KEY
:
215 if(hdr
->Format
!= RSA_PRIV_KEY_FORMAT
) {
216 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT
);
221 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
224 RSA
*rsaKey
= RSA_new();
226 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
230 crtn
= RSAPublicKeyDecode(rsaKey
,
231 cssmKey
.KeyData
.Data
,
232 cssmKey
.KeyData
.Length
);
235 crtn
= RSAPrivateKeyDecode(rsaKey
,
236 cssmKey
.KeyData
.Data
,
237 cssmKey
.KeyData
.Length
);
240 CssmError::throwMe(crtn
);
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
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
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
);
265 if(hdr
.KeyClass
!= keyClass
) {
266 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
268 cspValidateIntendedKeyUsage(&hdr
, usage
);
269 return cssmKeyToDsa(cssmKey
, session
, mallocdKey
);
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).
277 const CssmKey
&cssmKey
,
278 AppleCSPSession
&session
,
279 bool &allocdKey
) // RETURNED
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
);
289 switch(hdr
->BlobType
) {
290 case CSSM_KEYBLOB_RAW
:
291 dsaKey
= rawCssmKeyToDsa(cssmKey
);
294 case CSSM_KEYBLOB_REFERENCE
:
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
);
304 assert(dsaBinKey
->mDsaKey
!= NULL
);
305 dsaKey
= dsaBinKey
->mDsaKey
;
309 CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT
);
315 * Convert a raw CssmKey to a newly alloc'd DSA key.
317 DSA
*rawCssmKeyToDsa(
318 const CssmKey
&cssmKey
)
320 const CSSM_KEYHEADER
*hdr
= &cssmKey
.KeyHeader
;
323 assert(hdr
->BlobType
== CSSM_KEYBLOB_RAW
);
325 if(hdr
->AlgorithmId
!= CSSM_ALGID_DSA
) {
326 // someone else's key (should never happen)
327 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
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
);
336 case CSSM_KEYCLASS_PRIVATE_KEY
:
337 if(hdr
->Format
!= DSA_PRIV_KEY_FORMAT
) {
338 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT
);
343 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
346 DSA
*dsaKey
= DSA_new();
348 CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR
);
352 crtn
= DSAPublicKeyDecode(dsaKey
,
353 cssmKey
.KeyData
.Data
,
354 cssmKey
.KeyData
.Length
);
357 crtn
= DSAPrivateKeyDecode(dsaKey
,
358 cssmKey
.KeyData
.Data
,
359 cssmKey
.KeyData
.Length
);
362 CssmError::throwMe(crtn
);