xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_tpm/common/sign_mgr.c (revision 7a088f03b431bdffa96c3b2175964d4d38420caa)
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
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 
46 	if (! sess || ! ctx) {
47 		return (CKR_FUNCTION_FAILED);
48 	}
49 	if (ctx->active != FALSE) {
50 		return (CKR_OPERATION_ACTIVE);
51 	}
52 
53 	rc = object_mgr_find_in_map1(sess->hContext, key, &key_obj);
54 	if (rc != CKR_OK) {
55 		return (CKR_KEY_HANDLE_INVALID);
56 	}
57 	rc = template_attribute_find(key_obj->template, CKA_SIGN, &attr);
58 	if (rc == FALSE) {
59 		return (CKR_KEY_TYPE_INCONSISTENT);
60 	} else {
61 		flag = *(CK_BBOOL *)attr->pValue;
62 		if (flag != TRUE) {
63 			return (CKR_KEY_FUNCTION_NOT_PERMITTED);
64 		}
65 	}
66 
67 	switch (mech->mechanism) {
68 		case CKM_RSA_PKCS:
69 		{
70 			if (mech->ulParameterLen != 0) {
71 				return (CKR_MECHANISM_PARAM_INVALID);
72 			}
73 			rc = template_attribute_find(key_obj->template,
74 			    CKA_KEY_TYPE, &attr);
75 			if (rc == FALSE) {
76 				return (CKR_KEY_TYPE_INCONSISTENT);
77 			} else {
78 				keytype = *(CK_KEY_TYPE *)attr->pValue;
79 				if (keytype != CKK_RSA) {
80 					return (CKR_KEY_TYPE_INCONSISTENT);
81 				}
82 			}
83 
84 			// must be a PRIVATE key
85 			//
86 			flag = template_attribute_find(key_obj->template,
87 			    CKA_CLASS, &attr);
88 			if (flag == FALSE) {
89 				return (CKR_KEY_TYPE_INCONSISTENT);
90 			}
91 			else
92 				class = *(CK_OBJECT_CLASS *)attr->pValue;
93 
94 			if (class != CKO_PRIVATE_KEY) {
95 				return (CKR_KEY_TYPE_INCONSISTENT);
96 			}
97 			// PKCS #11 doesn't allow multi - part RSA operations
98 			//
99 			ctx->context_len = 0;
100 			ctx->context	= NULL;
101 		}
102 		break;
103 		case CKM_MD5_RSA_PKCS:
104 		case CKM_SHA1_RSA_PKCS:
105 		{
106 			if (mech->ulParameterLen != 0) {
107 				return (CKR_MECHANISM_PARAM_INVALID);
108 			}
109 			rc = template_attribute_find(key_obj->template,
110 			    CKA_KEY_TYPE, &attr);
111 			if (rc == FALSE) {
112 				return (CKR_KEY_TYPE_INCONSISTENT);
113 			} else {
114 				keytype = *(CK_KEY_TYPE *)attr->pValue;
115 				if (keytype != CKK_RSA) {
116 					return (CKR_KEY_TYPE_INCONSISTENT);
117 				}
118 			}
119 
120 			// must be a PRIVATE key operation
121 			//
122 			flag = template_attribute_find(key_obj->template,
123 			    CKA_CLASS, &attr);
124 			if (flag == FALSE) {
125 				return (CKR_FUNCTION_FAILED);
126 			}
127 			else
128 				class = *(CK_OBJECT_CLASS *)attr->pValue;
129 
130 			if (class != CKO_PRIVATE_KEY) {
131 				return (CKR_FUNCTION_FAILED);
132 			}
133 			ctx->context_len = sizeof (RSA_DIGEST_CONTEXT);
134 			ctx->context = (CK_BYTE *)malloc(
135 			    sizeof (RSA_DIGEST_CONTEXT));
136 			if (! ctx->context) {
137 				return (CKR_HOST_MEMORY);
138 			}
139 			(void) memset(ctx->context, 0x0,
140 			    sizeof (RSA_DIGEST_CONTEXT));
141 		}
142 		break;
143 		case CKM_MD5_HMAC:
144 		case CKM_SHA_1_HMAC:
145 		{
146 			if (mech->ulParameterLen != 0) {
147 				return (CKR_MECHANISM_PARAM_INVALID);
148 			}
149 			rc = template_attribute_find(key_obj->template,
150 			    CKA_KEY_TYPE, &attr);
151 			if (rc == FALSE) {
152 				return (CKR_KEY_TYPE_INCONSISTENT);
153 			} else {
154 				keytype = *(CK_KEY_TYPE *)attr->pValue;
155 				if (keytype != CKK_GENERIC_SECRET) {
156 					return (CKR_KEY_TYPE_INCONSISTENT);
157 				}
158 			}
159 
160 			// PKCS #11 doesn't allow multi - part HMAC operations
161 			//
162 			ctx->context_len = 0;
163 			ctx->context	= NULL;
164 		}
165 		break;
166 
167 		case CKM_MD5_HMAC_GENERAL:
168 		case CKM_SHA_1_HMAC_GENERAL:
169 		{
170 			CK_MAC_GENERAL_PARAMS *param =
171 			    (CK_MAC_GENERAL_PARAMS *)mech->pParameter;
172 
173 			if (mech->ulParameterLen !=
174 			    sizeof (CK_MAC_GENERAL_PARAMS)) {
175 				return (CKR_MECHANISM_PARAM_INVALID);
176 			}
177 
178 			if ((mech->mechanism == CKM_MD5_HMAC_GENERAL) &&
179 			    (*param > 16)) {
180 				return (CKR_MECHANISM_PARAM_INVALID);
181 			}
182 			if ((mech->mechanism == CKM_SHA_1_HMAC_GENERAL) &&
183 			    (*param > 20)) {
184 				return (CKR_MECHANISM_PARAM_INVALID);
185 			}
186 			rc = template_attribute_find(key_obj->template,
187 			    CKA_KEY_TYPE, &attr);
188 			if (rc == FALSE) {
189 				return (CKR_KEY_TYPE_INCONSISTENT);
190 			} else {
191 				keytype = *(CK_KEY_TYPE *)attr->pValue;
192 				if (keytype != CKK_GENERIC_SECRET) {
193 					return (CKR_KEY_TYPE_INCONSISTENT);
194 				}
195 			}
196 
197 			// PKCS #11 doesn't allow multi - part HMAC operations
198 			//
199 			ctx->context_len = 0;
200 			ctx->context	= NULL;
201 		}
202 		break;
203 		default:
204 			return (CKR_MECHANISM_INVALID);
205 	}
206 
207 
208 	if (mech->ulParameterLen > 0) {
209 		ptr = (CK_BYTE *)malloc(mech->ulParameterLen);
210 		if (! ptr) {
211 			return (CKR_HOST_MEMORY);
212 		}
213 		(void) memcpy(ptr, mech->pParameter, mech->ulParameterLen);
214 	}
215 
216 	ctx->key		 = key;
217 	ctx->mech.ulParameterLen = mech->ulParameterLen;
218 	ctx->mech.mechanism	= mech->mechanism;
219 	ctx->mech.pParameter	= ptr;
220 	ctx->multi		= FALSE;
221 	ctx->active		= TRUE;
222 	ctx->recover		= recover_mode;
223 
224 	return (CKR_OK);
225 }
226 
227 CK_RV
228 sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
229 {
230 	if (! ctx) {
231 		return (CKR_FUNCTION_FAILED);
232 	}
233 	ctx->key		 = 0;
234 	ctx->mech.ulParameterLen = 0;
235 	ctx->mech.mechanism	= 0;
236 	ctx->multi		= FALSE;
237 	ctx->active		= FALSE;
238 	ctx->recover		= FALSE;
239 	ctx->context_len	 = 0;
240 
241 	if (ctx->mech.pParameter) {
242 		free(ctx->mech.pParameter);
243 		ctx->mech.pParameter = NULL;
244 	}
245 
246 	if (ctx->context) {
247 		free(ctx->context);
248 		ctx->context = NULL;
249 	}
250 
251 	return (CKR_OK);
252 }
253 
254 CK_RV
255 sign_mgr_sign(SESSION	* sess,
256 	CK_BBOOL	length_only,
257 	SIGN_VERIFY_CONTEXT  * ctx,
258 	CK_BYTE		* in_data,
259 	CK_ULONG	in_data_len,
260 	CK_BYTE		* out_data,
261 	CK_ULONG	* out_data_len)
262 {
263 	if (! sess || ! ctx) {
264 		return (CKR_FUNCTION_FAILED);
265 	}
266 	if (ctx->active == FALSE) {
267 		return (CKR_OPERATION_NOT_INITIALIZED);
268 	}
269 	if (ctx->recover == TRUE) {
270 		return (CKR_OPERATION_NOT_INITIALIZED);
271 	}
272 
273 	// if the caller just wants the signature length, there is no reason to
274 	// specify the input data.  I just need the input data length
275 	//
276 	if ((length_only == FALSE) && (! in_data || ! out_data)) {
277 		return (CKR_FUNCTION_FAILED);
278 	}
279 	if (ctx->multi == TRUE) {
280 		return (CKR_OPERATION_ACTIVE);
281 	}
282 	switch (ctx->mech.mechanism) {
283 		case CKM_RSA_PKCS:
284 		return (rsa_pkcs_sign(sess,	length_only,  ctx,
285 		    in_data,  in_data_len,
286 		    out_data, out_data_len));
287 		case CKM_MD5_RSA_PKCS:
288 		case CKM_SHA1_RSA_PKCS:
289 		return (rsa_hash_pkcs_sign(sess,	length_only, ctx,
290 		    in_data,  in_data_len,
291 		    out_data, out_data_len));
292 
293 		case CKM_MD5_HMAC:
294 		case CKM_MD5_HMAC_GENERAL:
295 		return (md5_hmac_sign(sess,	length_only, ctx,
296 		    in_data,  in_data_len,
297 		    out_data, out_data_len));
298 		case CKM_SHA_1_HMAC:
299 		case CKM_SHA_1_HMAC_GENERAL:
300 		return (sha1_hmac_sign(sess,	length_only, ctx,
301 		    in_data,  in_data_len,
302 		    out_data, out_data_len));
303 		default:
304 			return (CKR_MECHANISM_INVALID);
305 	}
306 }
307 
308 CK_RV
309 sign_mgr_sign_update(SESSION		* sess,
310 	SIGN_VERIFY_CONTEXT * ctx,
311 	CK_BYTE		* in_data,
312 	CK_ULONG		in_data_len)
313 {
314 	if (! sess || ! ctx || ! in_data) {
315 		return (CKR_FUNCTION_FAILED);
316 	}
317 
318 	if (ctx->active == FALSE) {
319 		return (CKR_OPERATION_NOT_INITIALIZED);
320 	}
321 	if (ctx->recover == TRUE) {
322 		return (CKR_OPERATION_NOT_INITIALIZED);
323 	}
324 	ctx->multi = TRUE;
325 
326 	switch (ctx->mech.mechanism) {
327 		case CKM_MD5_RSA_PKCS:
328 		case CKM_SHA1_RSA_PKCS:
329 			return (rsa_hash_pkcs_sign_update(sess, ctx,
330 			    in_data, in_data_len));
331 		default:
332 			return (CKR_MECHANISM_INVALID);
333 	}
334 }
335 
336 CK_RV
337 sign_mgr_sign_final(SESSION		* sess,
338 	CK_BBOOL		length_only,
339 	SIGN_VERIFY_CONTEXT * ctx,
340 	CK_BYTE		* signature,
341 	CK_ULONG	    * sig_len)
342 {
343 	if (! sess || ! ctx) {
344 		return (CKR_FUNCTION_FAILED);
345 	}
346 	if (ctx->active == FALSE) {
347 		return (CKR_OPERATION_NOT_INITIALIZED);
348 	}
349 	if (ctx->recover == TRUE) {
350 		return (CKR_OPERATION_NOT_INITIALIZED);
351 	}
352 	switch (ctx->mech.mechanism) {
353 		case CKM_MD5_RSA_PKCS:
354 		case CKM_SHA1_RSA_PKCS:
355 			return (rsa_hash_pkcs_sign_final(sess, length_only,
356 			    ctx, signature, sig_len));
357 		default:
358 		return (CKR_MECHANISM_INVALID);
359 	}
360 }
361 
362 CK_RV
363 sign_mgr_sign_recover(SESSION		* sess,
364 	CK_BBOOL		length_only,
365 	SIGN_VERIFY_CONTEXT * ctx,
366 	CK_BYTE		* in_data,
367 	CK_ULONG		in_data_len,
368 	CK_BYTE		* out_data,
369 	CK_ULONG	    * out_data_len)
370 {
371 	if (! sess || ! ctx) {
372 		return (CKR_FUNCTION_FAILED);
373 	}
374 	if (ctx->active == FALSE) {
375 		return (CKR_OPERATION_NOT_INITIALIZED);
376 	}
377 	if (ctx->recover == FALSE) {
378 		return (CKR_OPERATION_NOT_INITIALIZED);
379 	}
380 
381 	// if the caller just wants the signature length, there is no reason to
382 	// specify the input data.  I just need the input data length
383 	//
384 	if ((length_only == FALSE) && (! in_data || ! out_data)) {
385 		return (CKR_FUNCTION_FAILED);
386 	}
387 	if (ctx->multi == TRUE) {
388 		return (CKR_OPERATION_ACTIVE);
389 	}
390 	switch (ctx->mech.mechanism) {
391 		case CKM_RSA_PKCS:
392 			return (rsa_pkcs_sign(sess,	length_only,  ctx,
393 			    in_data,  in_data_len,
394 			    out_data, out_data_len));
395 		default:
396 			return (CKR_MECHANISM_INVALID);
397 	}
398 }
399