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 * FEESignatureObject.cpp - implementations of FEE-style raw sign/verify classes
21 *
22 * Created 2/20/2001 by dmitch.
23 */
24
25#ifdef	CRYPTKIT_CSP_ENABLE
26
27#include "FEESignatureObject.h"
28#include <security_cryptkit/feePublicKey.h>
29#include <security_cryptkit/feeDigitalSignature.h>
30#include <security_cryptkit/falloc.h>
31#include <stdexcept>
32#include <assert.h>
33#include <security_utilities/debugging.h>
34
35#define feeSigObjDebug(args...)		secdebug("feeSig", ##args)
36
37CryptKit::FEESigner::~FEESigner()
38{
39	if(mWeMallocdFeeKey) {
40		assert(mFeeKey != NULL);
41		feePubKeyFree(mFeeKey);
42	}
43}
44
45/*
46 * obtain key from context, validate, convert to native FEE key
47 */
48void CryptKit::FEESigner::keyFromContext(
49	const Context 	&context)
50{
51	if(initFlag() && (mFeeKey != NULL)) {
52		/* reusing context, OK */
53		return;
54	}
55
56	CSSM_KEYCLASS 	keyClass;
57	CSSM_KEYUSE		keyUse;
58	if(isSigning()) {
59		/* signing with private key */
60		keyClass = CSSM_KEYCLASS_PRIVATE_KEY;
61		keyUse   = CSSM_KEYUSE_SIGN;
62	}
63	else {
64		/* verifying with public key */
65		keyClass = CSSM_KEYCLASS_PUBLIC_KEY;
66		keyUse   = CSSM_KEYUSE_VERIFY;
67	}
68	if(mFeeKey == NULL) {
69		mFeeKey = contextToFeeKey(context,
70			mSession,
71			CSSM_ATTRIBUTE_KEY,
72			keyClass,
73			keyUse,
74			mWeMallocdFeeKey);
75	}
76}
77
78/* reusable init */
79void CryptKit::FEESigner::signerInit(
80	const Context 	&context,
81	bool			isSigning)
82{
83	setIsSigning(isSigning);
84	keyFromContext(context);
85	setInitFlag(true);
86}
87
88/*
89 * Note that, unlike the implementation in security_cryptkit/feePublicKey.c, we ignore
90 * the Pm which used to be used as salt for the digest. That made staged verification
91 * impossible and I do not believe it increased security.
92 */
93void CryptKit::FEERawSigner::sign(
94	const void	 	*data,
95	size_t 			dataLen,
96	void			*sig,
97	size_t			*sigLen)	/* IN/OUT */
98{
99	feeSig 			fsig;
100	feeReturn		frtn;
101	unsigned char	*feeSig;
102	unsigned		feeSigLen=0;
103
104	if(mFeeKey == NULL) {
105		throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)");
106	}
107	fsig = feeSigNewWithKey(mFeeKey, mRandFcn, mRandRef);
108	if(fsig == NULL) {
109		throwCryptKit(FR_BadPubKey, "FEERawSigner::sign");
110	}
111	frtn = feeSigSign(fsig,
112		(unsigned char *)data,
113		(unsigned)dataLen,
114		mFeeKey);
115	if(frtn == FR_Success) {
116		frtn = feeSigData(fsig, &feeSig, &feeSigLen);
117	}
118	feeSigFree(fsig);
119	if(frtn) {
120		throwCryptKit(frtn, "FEERawSigner::sign");
121	}
122
123	/* copy out to caller and ffree */
124	if(*sigLen < feeSigLen) {
125		feeSigObjDebug("FEERawSigner sign overflow\n");
126		ffree(feeSig);
127		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
128	}
129	memmove(sig, feeSig, feeSigLen);
130	*sigLen = feeSigLen;
131	ffree(feeSig);
132}
133
134void CryptKit::FEERawSigner::verify(
135	const void	 	*data,
136	size_t 			dataLen,
137	const void		*sig,
138	size_t			sigLen)
139{
140	feeSig 		fsig;
141	feeReturn	frtn;
142
143	if(mFeeKey == NULL) {
144		throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)");
145	}
146	frtn = feeSigParse((unsigned char *)sig, sigLen, &fsig);
147	if(frtn) {
148		throwCryptKit(frtn, "feeSigParse");
149	}
150	frtn = feeSigVerify(fsig,
151		(unsigned char *)data,
152		(unsigned int)dataLen,
153		mFeeKey);
154	feeSigFree(fsig);
155	if(frtn) {
156		throwCryptKit(frtn, NULL);
157	}
158}
159
160size_t CryptKit::FEERawSigner::maxSigSize()
161{
162	unsigned 	rtn;
163	feeReturn 	frtn;
164
165	frtn = feeSigSize(mFeeKey, &rtn);
166	if(frtn) {
167		throwCryptKit(frtn, "feeSigSize");
168	}
169	return rtn;
170}
171
172/* ECDSA - this is really easy. */
173
174void CryptKit::FEEECDSASigner::sign(
175	const void	 	*data,
176	size_t 			dataLen,
177	void			*sig,
178	size_t			*sigLen)	/* IN/OUT */
179{
180	unsigned char	*feeSig;
181	unsigned		feeSigLen;
182	feeReturn		frtn;
183
184	if(mFeeKey == NULL) {
185		throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)");
186	}
187	frtn = feeECDSASign(mFeeKey,
188		(unsigned char *)data,   // data to be signed
189		(unsigned int)dataLen,				// in bytes
190		mRandFcn,
191		mRandRef,
192		&feeSig,
193		&feeSigLen);
194	if(frtn) {
195		throwCryptKit(frtn, "feeECDSASign");
196	}
197	/* copy out to caller and ffree */
198	if(*sigLen < feeSigLen) {
199		feeSigObjDebug("feeECDSASign overflow\n");
200		ffree(feeSig);
201		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
202	}
203	memmove(sig, feeSig, feeSigLen);
204	*sigLen = feeSigLen;
205	ffree(feeSig);
206
207}
208
209void CryptKit::FEEECDSASigner::verify(
210	const void	*data,
211	size_t 		dataLen,
212	const void	*sig,
213	size_t		sigLen)
214{
215	feeReturn	frtn;
216
217	if(mFeeKey == NULL) {
218		throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)");
219	}
220	frtn = feeECDSAVerify((unsigned char *)sig,
221		sigLen,
222		(unsigned char *)data,
223		(unsigned int)dataLen,
224		mFeeKey);
225	if(frtn) {
226		throwCryptKit(frtn, NULL);
227	}
228}
229
230size_t CryptKit::FEEECDSASigner::maxSigSize()
231{
232	unsigned 	rtn;
233	feeReturn 	frtn;
234
235	frtn = feeECDSASigSize(mFeeKey, &rtn);
236	if(frtn) {
237		throwCryptKit(frtn, "feeECDSASigSize");
238	}
239	return rtn;
240}
241
242#endif	/* CRYPTKIT_CSP_ENABLE */
243