]> git.saurik.com Git - apple/security.git/blob - AppleCSP/RSA_DSA/RSA_DSA_signature.cpp
Security-54.1.tar.gz
[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/openRsaSnacc.h>
31
32 #define rsaSigDebug(args...) debug("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 setInitFlag(true);
69 }
70
71 /* sign */
72 void RSASigner::sign(
73 const void *data,
74 size_t dataLen,
75 void *sig,
76 size_t *sigLen) /* IN/OUT */
77 {
78 if(mRsaKey == NULL) {
79 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
80 }
81
82 /* get encoded digest info */
83 CssmAutoData encodedInfo(alloc());
84 int irtn = generateDigestInfo(data,
85 dataLen,
86 digestAlg(),
87 encodedInfo,
88 RSA_size(mRsaKey));
89 if(irtn) {
90 rsaSigDebug("***digestInfo error\n");
91 throwOpensslErr(irtn);
92 }
93
94 /* signature := encrypted digest info */
95 irtn = RSA_private_encrypt(encodedInfo.length(),
96 (unsigned char *)encodedInfo.data(),
97 (unsigned char *)sig,
98 mRsaKey,
99 mPadding);
100 if(irtn < 0) {
101 throwRsaDsa("RSA_private_encrypt");
102 }
103 if((unsigned)irtn > *sigLen) {
104 rsaSigDebug("RSA_private_encrypt: sig overflow");
105 CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
106 }
107 *sigLen = (unsigned)irtn;
108 }
109
110 /* verify */
111 void RSASigner::verify(
112 const void *data,
113 size_t dataLen,
114 const void *sig,
115 size_t sigLen)
116 {
117 const char *op = NULL;
118 bool throwSigVerify = false;
119
120 if(mRsaKey == NULL) {
121 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
122 }
123
124 /* get encoded digest info */
125 CssmAutoData encodedInfo(alloc());
126 int irtn = generateDigestInfo(data,
127 dataLen,
128 digestAlg(),
129 encodedInfo,
130 RSA_size(mRsaKey));
131 if(irtn) {
132 rsaSigDebug("***digestInfo error\n");
133 CssmError::throwMe(/* FIXME */CSSMERR_CSP_INTERNAL_ERROR);
134 }
135
136 /* malloc decrypted signature */
137 unsigned char *decryptSig =
138 (unsigned char *)alloc().malloc(RSA_size(mRsaKey));
139 unsigned decryptSigLen;
140
141 /* signature should be encrypted digest info; decrypt the signature */
142 irtn = RSA_public_decrypt(sigLen,
143 (unsigned char *)sig,
144 decryptSig,
145 mRsaKey,
146 mPadding);
147 if(irtn < 0) {
148 op = "RSA_public_decrypt";
149 throwSigVerify = true;
150 goto abort;
151 }
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";
158 goto abort;
159 }
160 if(memcmp(decryptSig, encodedInfo.data(), decryptSigLen)) {
161 rsaSigDebug("***Signature miscompare\n");
162 throwSigVerify = true;
163 op = "RSA Sig miscompare";
164 goto abort;
165 }
166 else {
167 irtn = 0;
168 }
169 abort:
170 if(decryptSig != NULL) {
171 alloc().free(decryptSig);
172 }
173 if(throwSigVerify) {
174 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
175 }
176 }
177
178 /* works for both, but only used for signing */
179 size_t RSASigner::maxSigSize()
180 {
181 if(mRsaKey == NULL) {
182 return 0;
183 }
184 return RSA_size(mRsaKey);
185 }
186
187 /*
188 * obtain key from context, validate, convert to native RSA key
189 */
190 void RSASigner::keyFromContext(
191 const Context &context)
192 {
193 if(initFlag() && (mRsaKey != NULL)) {
194 /* reusing context, OK */
195 return;
196 }
197
198 CSSM_KEYCLASS keyClass;
199 CSSM_KEYUSE keyUse;
200 if(isSigning()) {
201 /* signing with private key */
202 keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
203 keyUse = CSSM_KEYUSE_SIGN;
204 }
205 else {
206 /* verifying with public key */
207 keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
208 keyUse = CSSM_KEYUSE_VERIFY;
209 }
210 if(mRsaKey == NULL) {
211 mRsaKey = contextToRsaKey(context,
212 mSession,
213 keyClass,
214 keyUse,
215 mWeMallocdRsaKey);
216 }
217 }
218
219 DSASigner::~DSASigner()
220 {
221 if(mWeMallocdDsaKey) {
222 assert(mDsaKey != NULL);
223 DSA_free(mDsaKey);
224 mDsaKey = NULL;
225 mWeMallocdDsaKey = false;
226 }
227 }
228
229 /* reusable init */
230 void DSASigner::signerInit(
231 const Context &context,
232 bool isSigning)
233 {
234 setIsSigning(isSigning);
235 keyFromContext(context);
236 setInitFlag(true);
237 }
238
239 /* sign */
240 void DSASigner::sign(
241 const void *data,
242 size_t dataLen,
243 void *sig,
244 size_t *sigLen) /* IN/OUT */
245 {
246 if(mDsaKey == NULL) {
247 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
248 }
249 if(mDsaKey->priv_key == NULL) {
250 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
251 }
252
253 /* get signature in internal format */
254 DSA_SIG *dsaSig = DSA_do_sign((unsigned char *)data, dataLen, mDsaKey);
255 if(dsaSig == NULL) {
256 throwRsaDsa("DSA_do_sign");
257 }
258
259 /* DER encode the signature */
260 CssmAutoData encodedSig(alloc());
261 int irtn = DSASigEncode(dsaSig, encodedSig);
262 if(irtn) {
263 throwRsaDsa("DSASigEncode");
264 }
265 if(encodedSig.length() > *sigLen) {
266 throwRsaDsa("DSA sign overflow");
267 }
268 memmove(sig, encodedSig.data(), encodedSig.length());
269 *sigLen = encodedSig.length();
270 DSA_SIG_free(dsaSig);
271 }
272
273 /* verify */
274 void DSASigner::verify(
275 const void *data,
276 size_t dataLen,
277 const void *sig,
278 size_t sigLen)
279 {
280 bool throwSigVerify = false;
281 DSA_SIG *dsaSig = NULL;
282 CSSM_RETURN crtn = CSSM_OK;
283 int irtn;
284
285 if(mDsaKey == NULL) {
286 CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR);
287 }
288 if(mDsaKey->pub_key == NULL) {
289 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
290 }
291
292 /* incoming sig is DER encoded....decode into internal format */
293 dsaSig = DSA_SIG_new();
294 crtn = DSASigDecode(dsaSig, sig, sigLen);
295 if(crtn) {
296 goto abort;
297 }
298
299 irtn = DSA_do_verify((unsigned char *)data, dataLen, dsaSig, mDsaKey);
300 if(!irtn) {
301 throwSigVerify = true;
302 }
303
304 abort:
305 if(dsaSig != NULL) {
306 DSA_SIG_free(dsaSig);
307 }
308 if(throwSigVerify) {
309 CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
310 }
311 else if(crtn) {
312 CssmError::throwMe(crtn);
313 }
314 }
315
316 /*
317 * Works for both, but only used for signing.
318 * DSA sig is a sequence of two 160-bit integers.
319 */
320 size_t DSASigner::maxSigSize()
321 {
322 if(mDsaKey == NULL) {
323 return 0;
324 }
325 size_t outSize;
326 size_t sizeOfOneInt;
327
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;
332 return outSize;
333 }
334
335 /*
336 * obtain key from context, validate, convert to native DSA key
337 */
338 void DSASigner::keyFromContext(
339 const Context &context)
340 {
341 if(initFlag() && (mDsaKey != NULL)) {
342 /* reusing context, OK */
343 return;
344 }
345
346 CSSM_KEYCLASS keyClass;
347 CSSM_KEYUSE keyUse;
348 if(isSigning()) {
349 /* signing with private key */
350 keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
351 keyUse = CSSM_KEYUSE_SIGN;
352 }
353 else {
354 /* verifying with public key */
355 keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
356 keyUse = CSSM_KEYUSE_VERIFY;
357 }
358 if(mDsaKey == NULL) {
359 mDsaKey = contextToDsaKey(context,
360 mSession,
361 keyClass,
362 keyUse,
363 mWeMallocdDsaKey);
364 }
365 }