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