]> git.saurik.com Git - apple/security.git/blob - AppleCSP/RSA_DSA/RSA_DSA_signature.cpp
35cd0a839a0f7f78a7312600f01506a113e4efaa
[apple/security.git] / AppleCSP / RSA_DSA / RSA_DSA_signature.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
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
8 * using this file.
9 *
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.
16 */
17
18
19 /*
20 * RSA_DSA_signature.cpp - openssl-based signature classes.
21 */
22
23 #include "RSA_DSA_signature.h"
24 #include "RSA_DSA_utils.h"
25 #include <stdexcept>
26 #include <assert.h>
27 #include <Security/debugging.h>
28 #include <Security/cssmdata.h>
29 #include <opensslUtils/opensslUtils.h>
30 #include <opensslUtils/opensslAsn1.h>
31
32 #define rsaSigDebug(args...) secdebug("rsaSig", ## args)
33
34 RSASigner::~RSASigner()
35 {
36 if(mWeMallocdRsaKey) {
37 assert(mRsaKey != NULL);
38 RSA_free(mRsaKey);
39 mRsaKey = NULL;
40 mWeMallocdRsaKey = false;
41 }
42 }
43
44 /* reusable init */
45 void RSASigner::signerInit(
46 const Context &context,
47 bool isSigning)
48 {
49 setIsSigning(isSigning);
50 keyFromContext(context);
51
52 /* optional padding attribute */
53 uint32 padding;
54 bool padPresent = context.getInt(CSSM_ATTRIBUTE_PADDING, padding);
55 if(padPresent) {
56 /* padding specified in context, convert to openssl style */
57 switch(padding) {
58 case CSSM_PADDING_NONE:
59 mPadding = RSA_NO_PADDING;
60 break;
61 case CSSM_PADDING_PKCS1:
62 mPadding = RSA_PKCS1_PADDING;
63 break;
64 default:
65 CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PADDING);
66 }
67 }
68
69 /* optional blinding attribute */
70 uint32 blinding = context.getInt(CSSM_ATTRIBUTE_RSA_BLINDING);
71 if(blinding) {
72 if(RSA_blinding_on(mRsaKey, NULL) <= 0) {
73 /* actually no legit failures */
74 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
75 }
76 }
77 else {
78 RSA_blinding_off(mRsaKey);
79 }
80
81 setInitFlag(true);
82 }
83
84 /* sign */
85 void RSASigner::sign(
86 const void *data,
87 size_t dataLen,
88 void *sig,
89 size_t *sigLen) /* IN/OUT */
90 {
91 if(mRsaKey == NULL) {
92 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
93 }
94
95 /* get encoded digest info */
96 CssmAutoData encodedInfo(alloc());
97 int irtn = generateDigestInfo(data,
98 dataLen,
99 digestAlg(),
100 encodedInfo,
101 RSA_size(mRsaKey));
102 if(irtn) {
103 rsaSigDebug("***digestInfo error\n");
104 throwOpensslErr(irtn);
105 }
106
107 /* signature := encrypted digest info */
108 irtn = RSA_private_encrypt(encodedInfo.length(),
109 (unsigned char *)encodedInfo.data(),
110 (unsigned char *)sig,
111 mRsaKey,
112 mPadding);
113 if(irtn < 0) {
114 throwRsaDsa("RSA_private_encrypt");
115 }
116 if((unsigned)irtn > *sigLen) {
117 rsaSigDebug("RSA_private_encrypt: sig overflow");
118 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
119 }
120 *sigLen = (unsigned)irtn;
121 }
122
123 /* verify */
124 void RSASigner::verify(
125 const void *data,
126 size_t dataLen,
127 const void *sig,
128 size_t sigLen)
129 {
130 const char *op = NULL;
131 bool throwSigVerify = false;
132
133 if(mRsaKey == NULL) {
134 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
135 }
136
137 /* get encoded digest info */
138 CssmAutoData encodedInfo(alloc());
139 int irtn = generateDigestInfo(data,
140 dataLen,
141 digestAlg(),
142 encodedInfo,
143 RSA_size(mRsaKey));
144 if(irtn) {
145 rsaSigDebug("***digestInfo error\n");
146 CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR);
147 }
148
149 /* malloc decrypted signature */
150 unsigned char *decryptSig =
151 (unsigned char *)alloc().malloc(RSA_size(mRsaKey));
152 unsigned decryptSigLen;
153
154 /* signature should be encrypted digest info; decrypt the signature */
155 irtn = RSA_public_decrypt(sigLen,
156 (unsigned char *)sig,
157 decryptSig,
158 mRsaKey,
159 mPadding);
160 if(irtn < 0) {
161 op = "RSA_public_decrypt";
162 throwSigVerify = true;
163 goto abort;
164 }
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";
171 goto abort;
172 }
173 if(memcmp(decryptSig, encodedInfo.data(), decryptSigLen)) {
174 rsaSigDebug("***Signature miscompare\n");
175 throwSigVerify = true;
176 op = "RSA Sig miscompare";
177 goto abort;
178 }
179 else {
180 irtn = 0;
181 }
182 abort:
183 if(decryptSig != NULL) {
184 alloc().free(decryptSig);
185 }
186 if(throwSigVerify) {
187 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
188 }
189 }
190
191 /* works for both, but only used for signing */
192 size_t RSASigner::maxSigSize()
193 {
194 if(mRsaKey == NULL) {
195 return 0;
196 }
197 return RSA_size(mRsaKey);
198 }
199
200 /*
201 * obtain key from context, validate, convert to native RSA key
202 */
203 void RSASigner::keyFromContext(
204 const Context &context)
205 {
206 if(initFlag() && (mRsaKey != NULL)) {
207 /* reusing context, OK */
208 return;
209 }
210
211 CSSM_KEYCLASS keyClass;
212 CSSM_KEYUSE keyUse;
213 if(isSigning()) {
214 /* signing with private key */
215 keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
216 keyUse = CSSM_KEYUSE_SIGN;
217 }
218 else {
219 /* verifying with public key */
220 keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
221 keyUse = CSSM_KEYUSE_VERIFY;
222 }
223 if(mRsaKey == NULL) {
224 mRsaKey = contextToRsaKey(context,
225 mSession,
226 keyClass,
227 keyUse,
228 mWeMallocdRsaKey);
229 }
230 }
231
232 DSASigner::~DSASigner()
233 {
234 if(mWeMallocdDsaKey) {
235 assert(mDsaKey != NULL);
236 DSA_free(mDsaKey);
237 mDsaKey = NULL;
238 mWeMallocdDsaKey = false;
239 }
240 }
241
242 /* reusable init */
243 void DSASigner::signerInit(
244 const Context &context,
245 bool isSigning)
246 {
247 setIsSigning(isSigning);
248 keyFromContext(context);
249 setInitFlag(true);
250 }
251
252 /* sign */
253 void DSASigner::sign(
254 const void *data,
255 size_t dataLen,
256 void *sig,
257 size_t *sigLen) /* IN/OUT */
258 {
259 if(mDsaKey == NULL) {
260 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
261 }
262 if(mDsaKey->priv_key == NULL) {
263 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
264 }
265
266 /* get signature in internal format */
267 DSA_SIG *dsaSig = DSA_do_sign((unsigned char *)data, dataLen, mDsaKey);
268 if(dsaSig == NULL) {
269 throwRsaDsa("DSA_do_sign");
270 }
271
272 /* DER encode the signature */
273 CssmAutoData encodedSig(alloc());
274 int irtn = DSASigEncode(dsaSig, encodedSig);
275 if(irtn) {
276 throwRsaDsa("DSASigEncode");
277 }
278 if(encodedSig.length() > *sigLen) {
279 throwRsaDsa("DSA sign overflow");
280 }
281 memmove(sig, encodedSig.data(), encodedSig.length());
282 *sigLen = encodedSig.length();
283 DSA_SIG_free(dsaSig);
284 }
285
286 /* verify */
287 void DSASigner::verify(
288 const void *data,
289 size_t dataLen,
290 const void *sig,
291 size_t sigLen)
292 {
293 bool throwSigVerify = false;
294 DSA_SIG *dsaSig = NULL;
295 CSSM_RETURN crtn = CSSM_OK;
296 int irtn;
297
298 if(mDsaKey == NULL) {
299 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
300 }
301 if(mDsaKey->pub_key == NULL) {
302 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
303 }
304
305 /* incoming sig is DER encoded....decode into internal format */
306 dsaSig = DSA_SIG_new();
307 crtn = DSASigDecode(dsaSig, sig, sigLen);
308 if(crtn) {
309 goto abort;
310 }
311
312 irtn = DSA_do_verify((unsigned char *)data, dataLen, dsaSig, mDsaKey);
313 if(irtn != 1) {
314 throwSigVerify = true;
315 }
316
317 abort:
318 if(dsaSig != NULL) {
319 DSA_SIG_free(dsaSig);
320 }
321 if(throwSigVerify) {
322 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
323 }
324 else if(crtn) {
325 CssmError::throwMe(crtn);
326 }
327 }
328
329 /*
330 * Works for both, but only used for signing.
331 * DSA sig is a sequence of two 160-bit integers.
332 */
333 size_t DSASigner::maxSigSize()
334 {
335 if(mDsaKey == NULL) {
336 return 0;
337 }
338 size_t outSize;
339 size_t sizeOfOneInt;
340
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;
345 return outSize;
346 }
347
348 /*
349 * obtain key from context, validate, convert to native DSA key
350 */
351 void DSASigner::keyFromContext(
352 const Context &context)
353 {
354 if(initFlag() && (mDsaKey != NULL)) {
355 /* reusing context, OK */
356 return;
357 }
358
359 CSSM_KEYCLASS keyClass;
360 CSSM_KEYUSE keyUse;
361 if(isSigning()) {
362 /* signing with private key */
363 keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
364 keyUse = CSSM_KEYUSE_SIGN;
365 }
366 else {
367 /* verifying with public key */
368 keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
369 keyUse = CSSM_KEYUSE_VERIFY;
370 }
371 if(mDsaKey == NULL) {
372 mDsaKey = contextToDsaKey(context,
373 mSession,
374 keyClass,
375 keyUse,
376 mWeMallocdDsaKey);
377 }
378 }