2 * Copyright (c) 2000-2001,2011-2012,2014 Apple 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"
26 #include <security_utilities/simulatecrash_assert.h>
27 #include <security_utilities/debugging.h>
28 #include <security_cdsa_utilities/cssmdata.h>
29 #include <opensslUtils/opensslUtils.h>
30 #include <opensslUtils/opensslAsn1.h>
32 #define rsaSigDebug(args...) secinfo("rsaSig", ## args)
34 static ModuleNexus
<Mutex
> gMutex
;
36 RSASigner::~RSASigner()
38 StLock
<Mutex
> _(gMutex());
39 if(mWeMallocdRsaKey
) {
40 assert(mRsaKey
!= NULL
);
43 mWeMallocdRsaKey
= false;
48 void RSASigner::signerInit(
49 const Context
&context
,
52 StLock
<Mutex
> _(gMutex());
54 setIsSigning(isSigning
);
55 keyFromContext(context
);
57 /* optional padding attribute */
59 bool padPresent
= context
.getInt(CSSM_ATTRIBUTE_PADDING
, padding
);
61 /* padding specified in context, convert to openssl style */
63 case CSSM_PADDING_NONE
:
64 mPadding
= RSA_NO_PADDING
;
66 case CSSM_PADDING_PKCS1
:
67 mPadding
= RSA_PKCS1_PADDING
;
70 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING
);
74 /* optional blinding attribute */
75 uint32 blinding
= context
.getInt(CSSM_ATTRIBUTE_RSA_BLINDING
);
77 if(RSA_blinding_on(mRsaKey
, NULL
) <= 0) {
78 /* actually no legit failures */
79 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
83 RSA_blinding_off(mRsaKey
);
94 size_t *sigLen
) /* IN/OUT */
96 StLock
<Mutex
> _(gMutex());
99 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
102 /* get encoded digest info */
103 CssmAutoData
encodedInfo(alloc());
104 int irtn
= generateDigestInfo(data
,
110 rsaSigDebug("***digestInfo error\n");
111 throwOpensslErr(irtn
);
114 /* signature := encrypted digest info */
115 irtn
= RSA_private_encrypt((int)encodedInfo
.length(),
116 (unsigned char *)encodedInfo
.data(),
117 (unsigned char *)sig
,
121 throwRsaDsa("RSA_private_encrypt");
123 if((unsigned)irtn
> *sigLen
) {
124 rsaSigDebug("RSA_private_encrypt: sig overflow");
125 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR
);
127 *sigLen
= (unsigned)irtn
;
131 void RSASigner::verify(
137 StLock
<Mutex
> _(gMutex());
139 const char *op
= NULL
;
140 bool throwSigVerify
= false;
142 if(mRsaKey
== NULL
) {
143 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
146 /* get encoded digest info */
147 CssmAutoData
encodedInfo(alloc());
148 int irtn
= generateDigestInfo(data
,
154 rsaSigDebug("***digestInfo error\n");
155 CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR
);
158 /* malloc decrypted signature */
159 unsigned char *decryptSig
=
160 (unsigned char *)alloc().malloc(RSA_size(mRsaKey
));
161 unsigned decryptSigLen
;
163 /* signature should be encrypted digest info; decrypt the signature */
164 irtn
= RSA_public_decrypt((int)sigLen
,
165 (unsigned char *)sig
,
170 op
= "RSA_public_decrypt";
171 throwSigVerify
= true;
174 decryptSigLen
= (unsigned)irtn
;
175 if(decryptSigLen
!= encodedInfo
.length()) {
176 rsaSigDebug("***Decrypted signature length error (exp %ld, got %d)\n",
177 encodedInfo
.length(), decryptSigLen
);
178 throwSigVerify
= true;
179 op
= "RSA Sig length check";
182 if(memcmp(decryptSig
, encodedInfo
.data(), decryptSigLen
)) {
183 rsaSigDebug("***Signature miscompare\n");
184 throwSigVerify
= true;
185 op
= "RSA Sig miscompare";
192 if(decryptSig
!= NULL
) {
193 alloc().free(decryptSig
);
196 clearOpensslErrors();
197 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
201 /* works for both, but only used for signing */
202 size_t RSASigner::maxSigSize()
204 StLock
<Mutex
> _(gMutex());
205 if(mRsaKey
== NULL
) {
208 return RSA_size(mRsaKey
);
212 * obtain key from context, validate, convert to native RSA key
214 void RSASigner::keyFromContext(
215 const Context
&context
)
217 if(initFlag() && (mRsaKey
!= NULL
)) {
218 /* reusing context, OK */
222 CSSM_KEYCLASS keyClass
;
225 /* signing with private key */
226 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
227 keyUse
= CSSM_KEYUSE_SIGN
;
230 /* verifying with public key */
231 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
232 keyUse
= CSSM_KEYUSE_VERIFY
;
234 if(mRsaKey
== NULL
) {
235 CSSM_DATA label
= {0, NULL
};
236 mRsaKey
= contextToRsaKey(context
,
242 /* cannot have label param for signing */
243 assert(label
.Data
== NULL
);
247 DSASigner::~DSASigner()
249 if(mWeMallocdDsaKey
) {
250 assert(mDsaKey
!= NULL
);
253 mWeMallocdDsaKey
= false;
258 void DSASigner::signerInit(
259 const Context
&context
,
262 setIsSigning(isSigning
);
263 keyFromContext(context
);
268 void DSASigner::sign(
272 size_t *sigLen
) /* IN/OUT */
274 if(mDsaKey
== NULL
) {
275 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
277 if(mDsaKey
->priv_key
== NULL
) {
278 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
281 /* get signature in internal format */
282 DSA_SIG
*dsaSig
= DSA_do_sign((unsigned char *)data
, (int)dataLen
, mDsaKey
);
284 throwRsaDsa("DSA_do_sign");
287 /* DER encode the signature */
288 CssmAutoData
encodedSig(alloc());
289 int irtn
= DSASigEncode(dsaSig
, encodedSig
);
291 throwRsaDsa("DSASigEncode");
293 if(encodedSig
.length() > *sigLen
) {
294 throwRsaDsa("DSA sign overflow");
296 memmove(sig
, encodedSig
.data(), encodedSig
.length());
297 *sigLen
= encodedSig
.length();
298 DSA_SIG_free(dsaSig
);
302 void DSASigner::verify(
308 bool throwSigVerify
= false;
309 DSA_SIG
*dsaSig
= NULL
;
310 CSSM_RETURN crtn
= CSSM_OK
;
313 if(mDsaKey
== NULL
) {
314 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR
);
316 if(mDsaKey
->pub_key
== NULL
) {
317 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS
);
320 /* incoming sig is DER encoded....decode into internal format */
321 dsaSig
= DSA_SIG_new();
322 crtn
= DSASigDecode(dsaSig
, sig
, (unsigned int)sigLen
);
327 irtn
= DSA_do_verify((unsigned char *)data
, (int)dataLen
, dsaSig
, mDsaKey
);
329 throwSigVerify
= true;
334 DSA_SIG_free(dsaSig
);
337 clearOpensslErrors();
338 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED
);
341 CssmError::throwMe(crtn
);
346 * Works for both, but only used for signing.
347 * DSA sig is a sequence of two 160-bit integers.
349 size_t DSASigner::maxSigSize()
351 if(mDsaKey
== NULL
) {
357 sizeOfOneInt
= (160 / 8) + // the raw contents
358 1 + // possible leading zero
359 2; // tag + length (assume DER, not BER)
360 outSize
= (2 * sizeOfOneInt
) + 5;
365 * obtain key from context, validate, convert to native DSA key
367 void DSASigner::keyFromContext(
368 const Context
&context
)
370 if(initFlag() && (mDsaKey
!= NULL
)) {
371 /* reusing context, OK */
375 CSSM_KEYCLASS keyClass
;
378 /* signing with private key */
379 keyClass
= CSSM_KEYCLASS_PRIVATE_KEY
;
380 keyUse
= CSSM_KEYUSE_SIGN
;
383 /* verifying with public key */
384 keyClass
= CSSM_KEYCLASS_PUBLIC_KEY
;
385 keyUse
= CSSM_KEYUSE_VERIFY
;
387 if(mDsaKey
== NULL
) {
388 mDsaKey
= contextToDsaKey(context
,