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 * RSA_DSA_signature.cpp - openssl-based signature classes.
23 #include "RSA_DSA_signature.h"
24 #include "RSA_DSA_utils.h"
27 #include <Security/debugging.h>
28 #include <Security/cssmdata.h>
29 #include <opensslUtils/opensslUtils.h>
30 #include <opensslUtils/openRsaSnacc.h>
32 #define rsaSigDebug(args...) debug("rsaSig", ## args)
34 RSASigner::~RSASigner()
36 if(mWeMallocdRsaKey
) {
37 assert(mRsaKey
!= NULL
);
40 mWeMallocdRsaKey
= false;
45 void RSASigner::signerInit(
46 const Context
&context
,
49 setIsSigning(isSigning
);
50 keyFromContext(context
);
59 size_t *sigLen
) /* IN/OUT */
62 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
65 /* get encoded digest info */
66 CssmAutoData
encodedInfo(alloc());
67 int irtn
= generateDigestInfo(data
,
73 rsaSigDebug("***digestInfo error\n");
74 throwOpensslErr(irtn
);
77 /* signature := encrypted digest info */
78 irtn
= RSA_private_encrypt(encodedInfo
.length(),
79 (unsigned char *)encodedInfo
.data(),
84 throwRsaDsa("RSA_private_encrypt");
86 if((unsigned)irtn
> *sigLen
) {
87 rsaSigDebug("RSA_private_encrypt: sig overflow");
88 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
90 *sigLen
= (unsigned)irtn
;
94 void RSASigner::verify(
100 const char *op
= NULL
;
101 bool throwSigVerify
= false;
103 if(mRsaKey
== NULL
) {
104 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
107 /* get encoded digest info */
108 CssmAutoData
encodedInfo(alloc());
109 int irtn
= generateDigestInfo(data
,
115 rsaSigDebug("***digestInfo error\n");
116 CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR
);
119 /* malloc decrypted signature */
120 unsigned char *decryptSig
=
121 (unsigned char *)alloc().malloc(RSA_size(mRsaKey
));
122 unsigned decryptSigLen
;
124 /* signature should be encrypted digest info; decrypt the signature */
125 irtn
= RSA_public_decrypt(sigLen
,
126 (unsigned char *)sig
,
131 op
= "RSA_public_decrypt";
132 throwSigVerify
= true;
135 decryptSigLen
= (unsigned)irtn
;
136 if(decryptSigLen
!= encodedInfo
.length()) {
137 rsaSigDebug("***Decrypted signature length error (exp %ld, got %d)\n",
138 encodedInfo
.length(), decryptSigLen
);
139 throwSigVerify
= true;
140 op
= "RSA Sig length check";
143 if(memcmp(decryptSig
, encodedInfo
.data(), decryptSigLen
)) {
144 rsaSigDebug("***Signature miscompare\n");
145 throwSigVerify
= true;
146 op
= "RSA Sig miscompare";
153 if(decryptSig
!= NULL
) {
154 alloc().free(decryptSig
);
157 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
161 /* works for both, but only used for signing */
162 size_t RSASigner::maxSigSize()
164 if(mRsaKey
== NULL
) {
167 return RSA_size(mRsaKey
);
171 * obtain key from context, validate, convert to native RSA key
173 void RSASigner::keyFromContext(
174 const Context
&context
)
176 if(initFlag() && (mRsaKey
!= NULL
)) {
177 /* reusing context, OK */
181 CSSM_KEYCLASS keyClass
;
184 /* signing with private key */
185 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
186 keyUse
= CSSM_KEYUSE_SIGN
;
189 /* verifying with public key */
190 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
191 keyUse
= CSSM_KEYUSE_VERIFY
;
193 if(mRsaKey
== NULL
) {
194 mRsaKey
= contextToRsaKey(context
,
202 DSASigner::~DSASigner()
204 if(mWeMallocdDsaKey
) {
205 assert(mDsaKey
!= NULL
);
208 mWeMallocdDsaKey
= false;
213 void DSASigner::signerInit(
214 const Context
&context
,
217 setIsSigning(isSigning
);
218 keyFromContext(context
);
223 void DSASigner::sign(
227 size_t *sigLen
) /* IN/OUT */
229 if(mDsaKey
== NULL
) {
230 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
232 if(mDsaKey
->priv_key
== NULL
) {
233 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
236 /* get signature in internal format */
237 DSA_SIG
*dsaSig
= DSA_do_sign((unsigned char *)data
, dataLen
, mDsaKey
);
239 throwRsaDsa("DSA_do_sign");
242 /* DER encode the signature */
243 CssmAutoData
encodedSig(alloc());
244 int irtn
= DSASigEncode(dsaSig
, encodedSig
);
246 throwRsaDsa("DSASigEncode");
248 if(encodedSig
.length() > *sigLen
) {
249 throwRsaDsa("DSA sign overflow");
251 memmove(sig
, encodedSig
.data(), encodedSig
.length());
252 *sigLen
= encodedSig
.length();
253 DSA_SIG_free(dsaSig
);
257 void DSASigner::verify(
263 bool throwSigVerify
= false;
264 DSA_SIG
*dsaSig
= NULL
;
265 CSSM_RETURN crtn
= CSSM_OK
;
268 if(mDsaKey
== NULL
) {
269 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
271 if(mDsaKey
->pub_key
== NULL
) {
272 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
275 /* incoming sig is DER encoded....decode into internal format */
276 dsaSig
= DSA_SIG_new();
277 crtn
= DSASigDecode(dsaSig
, sig
, sigLen
);
282 irtn
= DSA_do_verify((unsigned char *)data
, dataLen
, dsaSig
, mDsaKey
);
284 throwSigVerify
= true;
289 DSA_SIG_free(dsaSig
);
292 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
295 CssmError::throwMe(crtn
);
300 * Works for both, but only used for signing.
301 * DSA sig is a sequence of two 160-bit integers.
303 size_t DSASigner::maxSigSize()
305 if(mDsaKey
== NULL
) {
311 sizeOfOneInt
= (160 / 8) + // the raw contents
312 1 + // possible leading zero
313 2; // tag + length (assume DER, not BER)
314 outSize
= (2 * sizeOfOneInt
) + 5;
319 * obtain key from context, validate, convert to native DSA key
321 void DSASigner::keyFromContext(
322 const Context
&context
)
324 if(initFlag() && (mDsaKey
!= NULL
)) {
325 /* reusing context, OK */
329 CSSM_KEYCLASS keyClass
;
332 /* signing with private key */
333 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
334 keyUse
= CSSM_KEYUSE_SIGN
;
337 /* verifying with public key */
338 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
339 keyUse
= CSSM_KEYUSE_VERIFY
;
341 if(mDsaKey
== NULL
) {
342 mDsaKey
= contextToDsaKey(context
,