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
);
52 /* optional padding attribute */
54 bool padPresent
= context
.getInt(CSSM_ATTRIBUTE_PADDING
, padding
);
56 /* padding specified in context, convert to openssl style */
58 case CSSM_PADDING_NONE
:
59 mPadding
= RSA_NO_PADDING
;
61 case CSSM_PADDING_PKCS1
:
62 mPadding
= RSA_PKCS1_PADDING
;
65 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING
);
76 size_t *sigLen
) /* IN/OUT */
79 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
82 /* get encoded digest info */
83 CssmAutoData
encodedInfo(alloc());
84 int irtn
= generateDigestInfo(data
,
90 rsaSigDebug("***digestInfo error\n");
91 throwOpensslErr(irtn
);
94 /* signature := encrypted digest info */
95 irtn
= RSA_private_encrypt(encodedInfo
.length(),
96 (unsigned char *)encodedInfo
.data(),
101 throwRsaDsa("RSA_private_encrypt");
103 if((unsigned)irtn
> *sigLen
) {
104 rsaSigDebug("RSA_private_encrypt: sig overflow");
105 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
107 *sigLen
= (unsigned)irtn
;
111 void RSASigner::verify(
117 const char *op
= NULL
;
118 bool throwSigVerify
= false;
120 if(mRsaKey
== NULL
) {
121 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
124 /* get encoded digest info */
125 CssmAutoData
encodedInfo(alloc());
126 int irtn
= generateDigestInfo(data
,
132 rsaSigDebug("***digestInfo error\n");
133 CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR
);
136 /* malloc decrypted signature */
137 unsigned char *decryptSig
=
138 (unsigned char *)alloc().malloc(RSA_size(mRsaKey
));
139 unsigned decryptSigLen
;
141 /* signature should be encrypted digest info; decrypt the signature */
142 irtn
= RSA_public_decrypt(sigLen
,
143 (unsigned char *)sig
,
148 op
= "RSA_public_decrypt";
149 throwSigVerify
= true;
152 decryptSigLen
= (unsigned)irtn
;
153 if(decryptSigLen
!= encodedInfo
.length()) {
154 rsaSigDebug("***Decrypted signature length error (exp %ld, got %d)\n",
155 encodedInfo
.length(), decryptSigLen
);
156 throwSigVerify
= true;
157 op
= "RSA Sig length check";
160 if(memcmp(decryptSig
, encodedInfo
.data(), decryptSigLen
)) {
161 rsaSigDebug("***Signature miscompare\n");
162 throwSigVerify
= true;
163 op
= "RSA Sig miscompare";
170 if(decryptSig
!= NULL
) {
171 alloc().free(decryptSig
);
174 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
178 /* works for both, but only used for signing */
179 size_t RSASigner::maxSigSize()
181 if(mRsaKey
== NULL
) {
184 return RSA_size(mRsaKey
);
188 * obtain key from context, validate, convert to native RSA key
190 void RSASigner::keyFromContext(
191 const Context
&context
)
193 if(initFlag() && (mRsaKey
!= NULL
)) {
194 /* reusing context, OK */
198 CSSM_KEYCLASS keyClass
;
201 /* signing with private key */
202 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
203 keyUse
= CSSM_KEYUSE_SIGN
;
206 /* verifying with public key */
207 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
208 keyUse
= CSSM_KEYUSE_VERIFY
;
210 if(mRsaKey
== NULL
) {
211 mRsaKey
= contextToRsaKey(context
,
219 DSASigner::~DSASigner()
221 if(mWeMallocdDsaKey
) {
222 assert(mDsaKey
!= NULL
);
225 mWeMallocdDsaKey
= false;
230 void DSASigner::signerInit(
231 const Context
&context
,
234 setIsSigning(isSigning
);
235 keyFromContext(context
);
240 void DSASigner::sign(
244 size_t *sigLen
) /* IN/OUT */
246 if(mDsaKey
== NULL
) {
247 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
249 if(mDsaKey
->priv_key
== NULL
) {
250 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
253 /* get signature in internal format */
254 DSA_SIG
*dsaSig
= DSA_do_sign((unsigned char *)data
, dataLen
, mDsaKey
);
256 throwRsaDsa("DSA_do_sign");
259 /* DER encode the signature */
260 CssmAutoData
encodedSig(alloc());
261 int irtn
= DSASigEncode(dsaSig
, encodedSig
);
263 throwRsaDsa("DSASigEncode");
265 if(encodedSig
.length() > *sigLen
) {
266 throwRsaDsa("DSA sign overflow");
268 memmove(sig
, encodedSig
.data(), encodedSig
.length());
269 *sigLen
= encodedSig
.length();
270 DSA_SIG_free(dsaSig
);
274 void DSASigner::verify(
280 bool throwSigVerify
= false;
281 DSA_SIG
*dsaSig
= NULL
;
282 CSSM_RETURN crtn
= CSSM_OK
;
285 if(mDsaKey
== NULL
) {
286 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
288 if(mDsaKey
->pub_key
== NULL
) {
289 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
292 /* incoming sig is DER encoded....decode into internal format */
293 dsaSig
= DSA_SIG_new();
294 crtn
= DSASigDecode(dsaSig
, sig
, sigLen
);
299 irtn
= DSA_do_verify((unsigned char *)data
, dataLen
, dsaSig
, mDsaKey
);
301 throwSigVerify
= true;
306 DSA_SIG_free(dsaSig
);
309 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
312 CssmError::throwMe(crtn
);
317 * Works for both, but only used for signing.
318 * DSA sig is a sequence of two 160-bit integers.
320 size_t DSASigner::maxSigSize()
322 if(mDsaKey
== NULL
) {
328 sizeOfOneInt
= (160 / 8) + // the raw contents
329 1 + // possible leading zero
330 2; // tag + length (assume DER, not BER)
331 outSize
= (2 * sizeOfOneInt
) + 5;
336 * obtain key from context, validate, convert to native DSA key
338 void DSASigner::keyFromContext(
339 const Context
&context
)
341 if(initFlag() && (mDsaKey
!= NULL
)) {
342 /* reusing context, OK */
346 CSSM_KEYCLASS keyClass
;
349 /* signing with private key */
350 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
351 keyUse
= CSSM_KEYUSE_SIGN
;
354 /* verifying with public key */
355 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
356 keyUse
= CSSM_KEYUSE_VERIFY
;
358 if(mDsaKey
== NULL
) {
359 mDsaKey
= contextToDsaKey(context
,