1 /*
2  * The Initial Developer of the Original Code is International
3  * Business Machines Corporation. Portions created by IBM
4  * Corporation are Copyright (C) 2005 International Business
5  * Machines Corporation. All Rights Reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the Common Public License as published by
9  * IBM Corporation; either version 1 of the License, or (at your option)
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * Common Public License for more details.
16  *
17  * You should have received a copy of the Common Public License
18  * along with this program; if not, a copy can be viewed at
19  * http://www.opensource.org/licenses/cpl1.0.php.
20  */
21 
22 /* (C) COPYRIGHT International Business Machines Corp. 2001, 2002, 2005 */
23 /*
24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include "tpmtok_int.h"
29 
30 CK_RV
sign_mgr_init(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_MECHANISM * mech,CK_BBOOL recover_mode,CK_OBJECT_HANDLE key)31 sign_mgr_init(SESSION		* sess,
32 	SIGN_VERIFY_CONTEXT    * ctx,
33 	CK_MECHANISM	   * mech,
34 	CK_BBOOL		 recover_mode,
35 	CK_OBJECT_HANDLE	 key)
36 {
37 	OBJECT	  * key_obj = NULL;
38 	CK_ATTRIBUTE    * attr    = NULL;
39 	CK_BYTE	 * ptr	= NULL;
40 	CK_KEY_TYPE	keytype;
41 	CK_OBJECT_CLASS   class;
42 	CK_BBOOL	  flag;
43 	CK_RV		rc;
44 
45 	if (! sess || ! ctx) {
46 		return (CKR_FUNCTION_FAILED);
47 	}
48 	if (ctx->active != FALSE) {
49 		return (CKR_OPERATION_ACTIVE);
50 	}
51 
52 	rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj);
53 	if (rc != CKR_OK) {
54 		return (CKR_KEY_HANDLE_INVALID);
55 	}
56 	rc = template_attribute_find(key_obj->template, CKA_SIGN, &attr);
57 	if (rc == FALSE) {
58 		return (CKR_KEY_TYPE_INCONSISTENT);
59 	} else {
60 		flag = *(CK_BBOOL *)attr->pValue;
61 		if (flag != TRUE) {
62 			return (CKR_KEY_FUNCTION_NOT_PERMITTED);
63 		}
64 	}
65 
66 	switch (mech->mechanism) {
67 		case CKM_RSA_PKCS:
68 		{
69 			rc = template_attribute_find(key_obj->template,
70 			    CKA_KEY_TYPE, &attr);
71 			if (rc == FALSE) {
72 				return (CKR_KEY_TYPE_INCONSISTENT);
73 			} else {
74 				keytype = *(CK_KEY_TYPE *)attr->pValue;
75 				if (keytype != CKK_RSA) {
76 					return (CKR_KEY_TYPE_INCONSISTENT);
77 				}
78 			}
79 
80 			// must be a PRIVATE key
81 			//
82 			flag = template_attribute_find(key_obj->template,
83 			    CKA_CLASS, &attr);
84 			if (flag == FALSE) {
85 				return (CKR_KEY_TYPE_INCONSISTENT);
86 			}
87 			else
88 				class = *(CK_OBJECT_CLASS *)attr->pValue;
89 
90 			if (class != CKO_PRIVATE_KEY) {
91 				return (CKR_KEY_TYPE_INCONSISTENT);
92 			}
93 			// PKCS #11 doesn't allow multi - part RSA operations
94 			//
95 			ctx->context_len = 0;
96 			ctx->context	= NULL;
97 		}
98 		break;
99 		case CKM_MD5_RSA_PKCS:
100 		case CKM_SHA1_RSA_PKCS:
101 		{
102 			rc = template_attribute_find(key_obj->template,
103 			    CKA_KEY_TYPE, &attr);
104 			if (rc == FALSE) {
105 				return (CKR_KEY_TYPE_INCONSISTENT);
106 			} else {
107 				keytype = *(CK_KEY_TYPE *)attr->pValue;
108 				if (keytype != CKK_RSA) {
109 					return (CKR_KEY_TYPE_INCONSISTENT);
110 				}
111 			}
112 
113 			// must be a PRIVATE key operation
114 			//
115 			flag = template_attribute_find(key_obj->template,
116 			    CKA_CLASS, &attr);
117 			if (flag == FALSE) {
118 				return (CKR_FUNCTION_FAILED);
119 			}
120 			else
121 				class = *(CK_OBJECT_CLASS *)attr->pValue;
122 
123 			if (class != CKO_PRIVATE_KEY) {
124 				return (CKR_FUNCTION_FAILED);
125 			}
126 			ctx->context_len = sizeof (RSA_DIGEST_CONTEXT);
127 			ctx->context = (CK_BYTE *)malloc(
128 			    sizeof (RSA_DIGEST_CONTEXT));
129 			if (! ctx->context) {
130 				return (CKR_HOST_MEMORY);
131 			}
132 			(void) memset(ctx->context, 0x0,
133 			    sizeof (RSA_DIGEST_CONTEXT));
134 		}
135 		break;
136 		case CKM_MD5_HMAC:
137 		case CKM_SHA_1_HMAC:
138 		{
139 			if (mech->ulParameterLen != 0) {
140 				return (CKR_MECHANISM_PARAM_INVALID);
141 			}
142 			rc = template_attribute_find(key_obj->template,
143 			    CKA_KEY_TYPE, &attr);
144 			if (rc == FALSE) {
145 				return (CKR_KEY_TYPE_INCONSISTENT);
146 			} else {
147 				keytype = *(CK_KEY_TYPE *)attr->pValue;
148 				if (keytype != CKK_GENERIC_SECRET) {
149 					return (CKR_KEY_TYPE_INCONSISTENT);
150 				}
151 			}
152 
153 			// PKCS #11 doesn't allow multi - part HMAC operations
154 			//
155 			ctx->context_len = 0;
156 			ctx->context	= NULL;
157 		}
158 		break;
159 
160 		case CKM_MD5_HMAC_GENERAL:
161 		case CKM_SHA_1_HMAC_GENERAL:
162 		{
163 			CK_MAC_GENERAL_PARAMS *param =
164 			    (CK_MAC_GENERAL_PARAMS *)mech->pParameter;
165 
166 			if (mech->ulParameterLen !=
167 			    sizeof (CK_MAC_GENERAL_PARAMS)) {
168 				return (CKR_MECHANISM_PARAM_INVALID);
169 			}
170 
171 			if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) &&
172 			    (*param > 16)) {
173 				return (CKR_MECHANISM_PARAM_INVALID);
174 			}
175 			if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) &&
176 			    (*param > 20)) {
177 				return (CKR_MECHANISM_PARAM_INVALID);
178 			}
179 			rc = template_attribute_find(key_obj->template,
180 			    CKA_KEY_TYPE, &attr);
181 			if (rc == FALSE) {
182 				return (CKR_KEY_TYPE_INCONSISTENT);
183 			} else {
184 				keytype = *(CK_KEY_TYPE *)attr->pValue;
185 				if (keytype != CKK_GENERIC_SECRET) {
186 					return (CKR_KEY_TYPE_INCONSISTENT);
187 				}
188 			}
189 
190 			// PKCS #11 doesn't allow multi - part HMAC operations
191 			//
192 			ctx->context_len = 0;
193 			ctx->context	= NULL;
194 		}
195 		break;
196 		default:
197 			return (CKR_MECHANISM_INVALID);
198 	}
199 
200 	if (mech->ulParameterLen > 0 && mech->pParameter == NULL)
201 		return (CKR_ARGUMENTS_BAD);
202 
203 	if (mech->ulParameterLen > 0) {
204 		ptr = (CK_BYTE *)malloc(mech->ulParameterLen);
205 		if (! ptr) {
206 			return (CKR_HOST_MEMORY);
207 		}
208 		(void) memcpy(ptr, mech->pParameter, mech->ulParameterLen);
209 	}
210 
211 	ctx->key		 = key;
212 	ctx->mech.ulParameterLen = mech->ulParameterLen;
213 	ctx->mech.mechanism	= mech->mechanism;
214 	ctx->mech.pParameter	= ptr;
215 	ctx->multi		= FALSE;
216 	ctx->active		= TRUE;
217 	ctx->recover		= recover_mode;
218 
219 	return (CKR_OK);
220 }
221 
222 CK_RV
sign_mgr_cleanup(SIGN_VERIFY_CONTEXT * ctx)223 sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
224 {
225 	if (! ctx) {
226 		return (CKR_FUNCTION_FAILED);
227 	}
228 	ctx->key		 = 0;
229 	ctx->mech.ulParameterLen = 0;
230 	ctx->mech.mechanism	= 0;
231 	ctx->multi		= FALSE;
232 	ctx->active		= FALSE;
233 	ctx->recover		= FALSE;
234 	ctx->context_len	 = 0;
235 
236 	if (ctx->mech.pParameter) {
237 		free(ctx->mech.pParameter);
238 		ctx->mech.pParameter = NULL;
239 	}
240 
241 	if (ctx->context) {
242 		free(ctx->context);
243 		ctx->context = NULL;
244 	}
245 
246 	return (CKR_OK);
247 }
248 
249 CK_RV
sign_mgr_sign(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)250 sign_mgr_sign(SESSION	* sess,
251 	CK_BBOOL	length_only,
252 	SIGN_VERIFY_CONTEXT  * ctx,
253 	CK_BYTE		* in_data,
254 	CK_ULONG	in_data_len,
255 	CK_BYTE		* out_data,
256 	CK_ULONG	* out_data_len)
257 {
258 	if (! sess || ! ctx) {
259 		return (CKR_FUNCTION_FAILED);
260 	}
261 	if (ctx->active == FALSE) {
262 		return (CKR_OPERATION_NOT_INITIALIZED);
263 	}
264 	if (ctx->recover == TRUE) {
265 		return (CKR_OPERATION_NOT_INITIALIZED);
266 	}
267 
268 	// if the caller just wants the signature length, there is no reason to
269 	// specify the input data.  I just need the input data length
270 	//
271 	if ((length_only == FALSE) && (! in_data || ! out_data)) {
272 		return (CKR_FUNCTION_FAILED);
273 	}
274 	if (ctx->multi == TRUE) {
275 		return (CKR_OPERATION_ACTIVE);
276 	}
277 	switch (ctx->mech.mechanism) {
278 		case CKM_RSA_PKCS:
279 		return (rsa_pkcs_sign(sess,	length_only,  ctx,
280 		    in_data,  in_data_len,
281 		    out_data, out_data_len));
282 		case CKM_MD5_RSA_PKCS:
283 		case CKM_SHA1_RSA_PKCS:
284 		return (rsa_hash_pkcs_sign(sess,	length_only, ctx,
285 		    in_data,  in_data_len,
286 		    out_data, out_data_len));
287 
288 		case CKM_MD5_HMAC:
289 		case CKM_MD5_HMAC_GENERAL:
290 		return (md5_hmac_sign(sess,	length_only, ctx,
291 		    in_data,  in_data_len,
292 		    out_data, out_data_len));
293 		case CKM_SHA_1_HMAC:
294 		case CKM_SHA_1_HMAC_GENERAL:
295 		return (sha1_hmac_sign(sess,	length_only, ctx,
296 		    in_data,  in_data_len,
297 		    out_data, out_data_len));
298 		default:
299 			return (CKR_MECHANISM_INVALID);
300 	}
301 }
302 
303 CK_RV
sign_mgr_sign_update(SESSION * sess,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len)304 sign_mgr_sign_update(SESSION		* sess,
305 	SIGN_VERIFY_CONTEXT * ctx,
306 	CK_BYTE		* in_data,
307 	CK_ULONG		in_data_len)
308 {
309 	if (! sess || ! ctx || ! in_data) {
310 		return (CKR_FUNCTION_FAILED);
311 	}
312 
313 	if (ctx->active == FALSE) {
314 		return (CKR_OPERATION_NOT_INITIALIZED);
315 	}
316 	if (ctx->recover == TRUE) {
317 		return (CKR_OPERATION_NOT_INITIALIZED);
318 	}
319 	ctx->multi = TRUE;
320 
321 	switch (ctx->mech.mechanism) {
322 		case CKM_MD5_RSA_PKCS:
323 		case CKM_SHA1_RSA_PKCS:
324 			return (rsa_hash_pkcs_sign_update(sess, ctx,
325 			    in_data, in_data_len));
326 		default:
327 			return (CKR_MECHANISM_INVALID);
328 	}
329 }
330 
331 CK_RV
sign_mgr_sign_final(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * signature,CK_ULONG * sig_len)332 sign_mgr_sign_final(SESSION		* sess,
333 	CK_BBOOL		length_only,
334 	SIGN_VERIFY_CONTEXT * ctx,
335 	CK_BYTE		* signature,
336 	CK_ULONG	    * sig_len)
337 {
338 	if (! sess || ! ctx) {
339 		return (CKR_FUNCTION_FAILED);
340 	}
341 	if (ctx->active == FALSE) {
342 		return (CKR_OPERATION_NOT_INITIALIZED);
343 	}
344 	if (ctx->recover == TRUE) {
345 		return (CKR_OPERATION_NOT_INITIALIZED);
346 	}
347 	switch (ctx->mech.mechanism) {
348 		case CKM_MD5_RSA_PKCS:
349 		case CKM_SHA1_RSA_PKCS:
350 			return (rsa_hash_pkcs_sign_final(sess, length_only,
351 			    ctx, signature, sig_len));
352 		default:
353 		return (CKR_MECHANISM_INVALID);
354 	}
355 }
356 
357 CK_RV
sign_mgr_sign_recover(SESSION * sess,CK_BBOOL length_only,SIGN_VERIFY_CONTEXT * ctx,CK_BYTE * in_data,CK_ULONG in_data_len,CK_BYTE * out_data,CK_ULONG * out_data_len)358 sign_mgr_sign_recover(SESSION		* sess,
359 	CK_BBOOL		length_only,
360 	SIGN_VERIFY_CONTEXT * ctx,
361 	CK_BYTE		* in_data,
362 	CK_ULONG		in_data_len,
363 	CK_BYTE		* out_data,
364 	CK_ULONG	    * out_data_len)
365 {
366 	if (! sess || ! ctx) {
367 		return (CKR_FUNCTION_FAILED);
368 	}
369 	if (ctx->active == FALSE) {
370 		return (CKR_OPERATION_NOT_INITIALIZED);
371 	}
372 	if (ctx->recover == FALSE) {
373 		return (CKR_OPERATION_NOT_INITIALIZED);
374 	}
375 
376 	// if the caller just wants the signature length, there is no reason to
377 	// specify the input data.  I just need the input data length
378 	//
379 	if ((length_only == FALSE) && (! in_data || ! out_data)) {
380 		return (CKR_FUNCTION_FAILED);
381 	}
382 	if (ctx->multi == TRUE) {
383 		return (CKR_OPERATION_ACTIVE);
384 	}
385 	switch (ctx->mech.mechanism) {
386 		case CKM_RSA_PKCS:
387 			return (rsa_pkcs_sign(sess,	length_only,  ctx,
388 			    in_data,  in_data_len,
389 			    out_data, out_data_len));
390 		default:
391 			return (CKR_MECHANISM_INVALID);
392 	}
393 }
394