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