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/opensslAsn1.h>
32 #define rsaSigDebug(args...) secdebug("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
);
69 /* optional blinding attribute */
70 uint32 blinding
= context
.getInt(CSSM_ATTRIBUTE_RSA_BLINDING
);
72 if(RSA_blinding_on(mRsaKey
, NULL
) <= 0) {
73 /* actually no legit failures */
74 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
78 RSA_blinding_off(mRsaKey
);
89 size_t *sigLen
) /* IN/OUT */
92 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
95 /* get encoded digest info */
96 CssmAutoData
encodedInfo(alloc());
97 int irtn
= generateDigestInfo(data
,
103 rsaSigDebug("***digestInfo error\n");
104 throwOpensslErr(irtn
);
107 /* signature := encrypted digest info */
108 irtn
= RSA_private_encrypt(encodedInfo
.length(),
109 (unsigned char *)encodedInfo
.data(),
110 (unsigned char *)sig
,
114 throwRsaDsa("RSA_private_encrypt");
116 if((unsigned)irtn
> *sigLen
) {
117 rsaSigDebug("RSA_private_encrypt: sig overflow");
118 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
120 *sigLen
= (unsigned)irtn
;
124 void RSASigner::verify(
130 const char *op
= NULL
;
131 bool throwSigVerify
= false;
133 if(mRsaKey
== NULL
) {
134 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
137 /* get encoded digest info */
138 CssmAutoData
encodedInfo(alloc());
139 int irtn
= generateDigestInfo(data
,
145 rsaSigDebug("***digestInfo error\n");
146 CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR
);
149 /* malloc decrypted signature */
150 unsigned char *decryptSig
=
151 (unsigned char *)alloc().malloc(RSA_size(mRsaKey
));
152 unsigned decryptSigLen
;
154 /* signature should be encrypted digest info; decrypt the signature */
155 irtn
= RSA_public_decrypt(sigLen
,
156 (unsigned char *)sig
,
161 op
= "RSA_public_decrypt";
162 throwSigVerify
= true;
165 decryptSigLen
= (unsigned)irtn
;
166 if(decryptSigLen
!= encodedInfo
.length()) {
167 rsaSigDebug("***Decrypted signature length error (exp %ld, got %d)\n",
168 encodedInfo
.length(), decryptSigLen
);
169 throwSigVerify
= true;
170 op
= "RSA Sig length check";
173 if(memcmp(decryptSig
, encodedInfo
.data(), decryptSigLen
)) {
174 rsaSigDebug("***Signature miscompare\n");
175 throwSigVerify
= true;
176 op
= "RSA Sig miscompare";
183 if(decryptSig
!= NULL
) {
184 alloc().free(decryptSig
);
187 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
191 /* works for both, but only used for signing */
192 size_t RSASigner::maxSigSize()
194 if(mRsaKey
== NULL
) {
197 return RSA_size(mRsaKey
);
201 * obtain key from context, validate, convert to native RSA key
203 void RSASigner::keyFromContext(
204 const Context
&context
)
206 if(initFlag() && (mRsaKey
!= NULL
)) {
207 /* reusing context, OK */
211 CSSM_KEYCLASS keyClass
;
214 /* signing with private key */
215 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
216 keyUse
= CSSM_KEYUSE_SIGN
;
219 /* verifying with public key */
220 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
221 keyUse
= CSSM_KEYUSE_VERIFY
;
223 if(mRsaKey
== NULL
) {
224 mRsaKey
= contextToRsaKey(context
,
232 DSASigner::~DSASigner()
234 if(mWeMallocdDsaKey
) {
235 assert(mDsaKey
!= NULL
);
238 mWeMallocdDsaKey
= false;
243 void DSASigner::signerInit(
244 const Context
&context
,
247 setIsSigning(isSigning
);
248 keyFromContext(context
);
253 void DSASigner::sign(
257 size_t *sigLen
) /* IN/OUT */
259 if(mDsaKey
== NULL
) {
260 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
262 if(mDsaKey
->priv_key
== NULL
) {
263 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
266 /* get signature in internal format */
267 DSA_SIG
*dsaSig
= DSA_do_sign((unsigned char *)data
, dataLen
, mDsaKey
);
269 throwRsaDsa("DSA_do_sign");
272 /* DER encode the signature */
273 CssmAutoData
encodedSig(alloc());
274 int irtn
= DSASigEncode(dsaSig
, encodedSig
);
276 throwRsaDsa("DSASigEncode");
278 if(encodedSig
.length() > *sigLen
) {
279 throwRsaDsa("DSA sign overflow");
281 memmove(sig
, encodedSig
.data(), encodedSig
.length());
282 *sigLen
= encodedSig
.length();
283 DSA_SIG_free(dsaSig
);
287 void DSASigner::verify(
293 bool throwSigVerify
= false;
294 DSA_SIG
*dsaSig
= NULL
;
295 CSSM_RETURN crtn
= CSSM_OK
;
298 if(mDsaKey
== NULL
) {
299 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
301 if(mDsaKey
->pub_key
== NULL
) {
302 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
305 /* incoming sig is DER encoded....decode into internal format */
306 dsaSig
= DSA_SIG_new();
307 crtn
= DSASigDecode(dsaSig
, sig
, sigLen
);
312 irtn
= DSA_do_verify((unsigned char *)data
, dataLen
, dsaSig
, mDsaKey
);
314 throwSigVerify
= true;
319 DSA_SIG_free(dsaSig
);
322 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
325 CssmError::throwMe(crtn
);
330 * Works for both, but only used for signing.
331 * DSA sig is a sequence of two 160-bit integers.
333 size_t DSASigner::maxSigSize()
335 if(mDsaKey
== NULL
) {
341 sizeOfOneInt
= (160 / 8) + // the raw contents
342 1 + // possible leading zero
343 2; // tag + length (assume DER, not BER)
344 outSize
= (2 * sizeOfOneInt
) + 5;
349 * obtain key from context, validate, convert to native DSA key
351 void DSASigner::keyFromContext(
352 const Context
&context
)
354 if(initFlag() && (mDsaKey
!= NULL
)) {
355 /* reusing context, OK */
359 CSSM_KEYCLASS keyClass
;
362 /* signing with private key */
363 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
364 keyUse
= CSSM_KEYUSE_SIGN
;
367 /* verifying with public key */
368 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
369 keyUse
= CSSM_KEYUSE_VERIFY
;
371 if(mDsaKey
== NULL
) {
372 mDsaKey
= contextToDsaKey(context
,