xref: /titanic_52/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelSoftCommon.c (revision b2a962217309a877fd63575155d80ad56aca8071)
1ba5f469cSkrishna /*
2ba5f469cSkrishna  * CDDL HEADER START
3ba5f469cSkrishna  *
4ba5f469cSkrishna  * The contents of this file are subject to the terms of the
5ba5f469cSkrishna  * Common Development and Distribution License (the "License").
6ba5f469cSkrishna  * You may not use this file except in compliance with the License.
7ba5f469cSkrishna  *
8ba5f469cSkrishna  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9ba5f469cSkrishna  * or http://www.opensolaris.org/os/licensing.
10ba5f469cSkrishna  * See the License for the specific language governing permissions
11ba5f469cSkrishna  * and limitations under the License.
12ba5f469cSkrishna  *
13ba5f469cSkrishna  * When distributing Covered Code, include this CDDL HEADER in each
14ba5f469cSkrishna  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15ba5f469cSkrishna  * If applicable, add the following below this CDDL HEADER, with the
16ba5f469cSkrishna  * fields enclosed by brackets "[]" replaced with your own identifying
17ba5f469cSkrishna  * information: Portions Copyright [yyyy] [name of copyright owner]
18ba5f469cSkrishna  *
19ba5f469cSkrishna  * CDDL HEADER END
20ba5f469cSkrishna  */
21ba5f469cSkrishna 
22ba5f469cSkrishna /*
23ba5f469cSkrishna  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24ba5f469cSkrishna  * Use is subject to license terms.
25ba5f469cSkrishna  */
26ba5f469cSkrishna 
27ba5f469cSkrishna #pragma ident	"%Z%%M%	%I%	%E% SMI"
28ba5f469cSkrishna 
29ba5f469cSkrishna #include <pthread.h>
30ba5f469cSkrishna #include <errno.h>
31ba5f469cSkrishna #include <stdio.h>
32ba5f469cSkrishna #include <strings.h>
33ba5f469cSkrishna #include <sys/crypto/ioctl.h>
34ba5f469cSkrishna #include <security/cryptoki.h>
35ba5f469cSkrishna #include <security/pkcs11t.h>
36ba5f469cSkrishna #include "softSession.h"
37ba5f469cSkrishna #include "softObject.h"
38ba5f469cSkrishna #include "softOps.h"
39ba5f469cSkrishna #include "softMAC.h"
40ba5f469cSkrishna #include "kernelSoftCommon.h"
41ba5f469cSkrishna 
42ba5f469cSkrishna /*
43*b2a96221Skrishna  * Do the operation(s) specified by opflag.
44ba5f469cSkrishna  */
45ba5f469cSkrishna CK_RV
46ba5f469cSkrishna do_soft_digest(void **s, CK_MECHANISM_PTR pMechanism, CK_BYTE_PTR pData,
47ba5f469cSkrishna     CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen,
48ba5f469cSkrishna     int opflag)
49ba5f469cSkrishna {
50ba5f469cSkrishna 	soft_session_t *session_p;
51*b2a96221Skrishna 	CK_RV rv = CKR_ARGUMENTS_BAD;
52ba5f469cSkrishna 
53ba5f469cSkrishna 	session_p = *((soft_session_t **)s);
54ba5f469cSkrishna 	if (session_p == NULL) {
55ba5f469cSkrishna 		if (!(opflag & OP_INIT)) {
56ba5f469cSkrishna 			return (CKR_ARGUMENTS_BAD);
57ba5f469cSkrishna 		}
58ba5f469cSkrishna 
59ba5f469cSkrishna 		session_p = calloc(1, sizeof (soft_session_t));
60ba5f469cSkrishna 		/*
61ba5f469cSkrishna 		 * Initialize the lock for the newly created session.
62ba5f469cSkrishna 		 * We do only the minimum needed setup for the
63ba5f469cSkrishna 		 * soft_digest* routines to succeed.
64ba5f469cSkrishna 		 */
65ba5f469cSkrishna 		if (pthread_mutex_init(&session_p->session_mutex, NULL) != 0) {
66ba5f469cSkrishna 			free(session_p);
67ba5f469cSkrishna 			return (CKR_CANT_LOCK);
68ba5f469cSkrishna 		}
69ba5f469cSkrishna 
70ba5f469cSkrishna 		*s = session_p;
71ba5f469cSkrishna 	} else if (opflag & OP_INIT) {
72ba5f469cSkrishna 		free_soft_ctx(session_p, OP_DIGEST);
73ba5f469cSkrishna 	}
74ba5f469cSkrishna 
75*b2a96221Skrishna 	if (opflag & OP_INIT) {
76ba5f469cSkrishna 		rv = soft_digest_init(session_p, pMechanism);
77*b2a96221Skrishna 		if (rv != CKR_OK)
78*b2a96221Skrishna 			return (rv);
79*b2a96221Skrishna 	}
80ba5f469cSkrishna 
81*b2a96221Skrishna 	if (opflag & OP_SINGLE) {
82ba5f469cSkrishna 		rv = soft_digest(session_p, pData, ulDataLen,
83ba5f469cSkrishna 		    pDigest, pulDigestLen);
84*b2a96221Skrishna 	} else {
85*b2a96221Skrishna 		if (opflag & OP_UPDATE) {
86ba5f469cSkrishna 			rv = soft_digest_update(session_p, pData, ulDataLen);
87*b2a96221Skrishna 			if (rv != CKR_OK)
88*b2a96221Skrishna 				return (rv);
89*b2a96221Skrishna 		}
90ba5f469cSkrishna 
91*b2a96221Skrishna 		if (opflag & OP_FINAL) {
92*b2a96221Skrishna 			rv = soft_digest_final(session_p,
93*b2a96221Skrishna 			    pDigest, pulDigestLen);
94*b2a96221Skrishna 		}
95ba5f469cSkrishna 	}
96ba5f469cSkrishna 
97ba5f469cSkrishna 	return (rv);
98ba5f469cSkrishna }
99ba5f469cSkrishna 
100ba5f469cSkrishna /*
101ba5f469cSkrishna  * opflag specifies whether this is a sign or verify.
102ba5f469cSkrishna  */
103ba5f469cSkrishna CK_RV
104ba5f469cSkrishna do_soft_hmac_init(void **s, CK_MECHANISM_PTR pMechanism,
105ba5f469cSkrishna     CK_BYTE_PTR kval, CK_ULONG klen, int opflag)
106ba5f469cSkrishna {
107ba5f469cSkrishna 	CK_RV rv;
108ba5f469cSkrishna 	soft_object_t keyobj;
109ba5f469cSkrishna 	secret_key_obj_t skeyobj;
110ba5f469cSkrishna 	soft_object_t *key_p;
111ba5f469cSkrishna 	soft_session_t *session_p;
112ba5f469cSkrishna 
113ba5f469cSkrishna 	session_p = *((soft_session_t **)s);
114ba5f469cSkrishna 	if (session_p == NULL) {
115ba5f469cSkrishna 		session_p = calloc(1, sizeof (soft_session_t));
116ba5f469cSkrishna 		/* See comments in do_soft_digest() above */
117ba5f469cSkrishna 		if (pthread_mutex_init(&session_p->session_mutex, NULL) != 0) {
118ba5f469cSkrishna 			free(session_p);
119ba5f469cSkrishna 			return (CKR_CANT_LOCK);
120ba5f469cSkrishna 		}
121ba5f469cSkrishna 
122ba5f469cSkrishna 		*s = session_p;
123ba5f469cSkrishna 	} else if (opflag & OP_INIT) {
124ba5f469cSkrishna 		free_soft_ctx(session_p, opflag);
125ba5f469cSkrishna 	}
126ba5f469cSkrishna 
127ba5f469cSkrishna 	/* Do the minimum needed setup for the call to succeed */
128ba5f469cSkrishna 	key_p = &keyobj;
129ba5f469cSkrishna 	bzero(key_p, sizeof (soft_object_t));
130ba5f469cSkrishna 	key_p->class = CKO_SECRET_KEY;
131ba5f469cSkrishna 	key_p->key_type = CKK_GENERIC_SECRET;
132ba5f469cSkrishna 
133ba5f469cSkrishna 	bzero(&skeyobj, sizeof (secret_key_obj_t));
134ba5f469cSkrishna 	OBJ_SEC(key_p) = &skeyobj;
135ba5f469cSkrishna 	OBJ_SEC_VALUE(key_p) = kval;
136ba5f469cSkrishna 	OBJ_SEC_VALUE_LEN(key_p) = klen;
137ba5f469cSkrishna 
138ba5f469cSkrishna 	rv = soft_hmac_sign_verify_init_common(session_p, pMechanism,
139ba5f469cSkrishna 	    key_p, opflag & OP_SIGN);
140ba5f469cSkrishna 
141ba5f469cSkrishna 	return (rv);
142ba5f469cSkrishna }
143ba5f469cSkrishna 
144ba5f469cSkrishna /*
145ba5f469cSkrishna  * opflag specifies whether this is a sign or verify.
146ba5f469cSkrishna  */
147ba5f469cSkrishna CK_RV
148ba5f469cSkrishna do_soft_hmac_update(void **s, CK_BYTE_PTR pData, CK_ULONG ulDataLen, int opflag)
149ba5f469cSkrishna {
150ba5f469cSkrishna 	soft_session_t *session_p;
151ba5f469cSkrishna 
152ba5f469cSkrishna 	session_p = *((soft_session_t **)s);
153ba5f469cSkrishna 	if (session_p == NULL) {
154ba5f469cSkrishna 		return (CKR_ARGUMENTS_BAD);
155ba5f469cSkrishna 	}
156ba5f469cSkrishna 
157ba5f469cSkrishna 	return (soft_hmac_sign_verify_update(session_p,
158ba5f469cSkrishna 	    pData, ulDataLen, opflag & OP_SIGN));
159ba5f469cSkrishna }
160ba5f469cSkrishna 
161ba5f469cSkrishna /*
162ba5f469cSkrishna  * opflag specifies whether this is a final or single.
163ba5f469cSkrishna  */
164ba5f469cSkrishna CK_RV
165ba5f469cSkrishna do_soft_hmac_sign(void **s, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
166ba5f469cSkrishna     CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen, int opflag)
167ba5f469cSkrishna {
168ba5f469cSkrishna 	CK_RV rv;
169ba5f469cSkrishna 	soft_session_t *session_p;
170ba5f469cSkrishna 	CK_BYTE hmac[SHA512_DIGEST_LENGTH]; /* use the maximum size */
171ba5f469cSkrishna 
172ba5f469cSkrishna 	session_p = *((soft_session_t **)s);
173ba5f469cSkrishna 	if (session_p == NULL || !(opflag & OP_SINGLE || opflag & OP_FINAL)) {
174ba5f469cSkrishna 		return (CKR_ARGUMENTS_BAD);
175ba5f469cSkrishna 	}
176ba5f469cSkrishna 
177ba5f469cSkrishna 	rv = soft_hmac_sign_verify_common(session_p, pData, ulDataLen,
178ba5f469cSkrishna 	    (pSignature != NULL ? hmac : NULL), pulSignatureLen, B_TRUE);
179ba5f469cSkrishna 
180ba5f469cSkrishna 	if ((rv == CKR_OK) && (pSignature != NULL)) {
181ba5f469cSkrishna 		(void) memcpy(pSignature, hmac, *pulSignatureLen);
182ba5f469cSkrishna 	}
183ba5f469cSkrishna 
184ba5f469cSkrishna 	return (rv);
185ba5f469cSkrishna }
186ba5f469cSkrishna 
187ba5f469cSkrishna /*
188ba5f469cSkrishna  * opflag specifies whether this is a final or single.
189ba5f469cSkrishna  */
190ba5f469cSkrishna CK_RV
191ba5f469cSkrishna do_soft_hmac_verify(void **s, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
192ba5f469cSkrishna     CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, int opflag)
193ba5f469cSkrishna {
194ba5f469cSkrishna 	CK_RV rv;
195ba5f469cSkrishna 	CK_ULONG len;
196ba5f469cSkrishna 	soft_session_t *session_p;
197ba5f469cSkrishna 	soft_hmac_ctx_t *hmac_ctx;
198ba5f469cSkrishna 	CK_BYTE hmac[SHA512_DIGEST_LENGTH]; /* use the maximum size */
199ba5f469cSkrishna 
200ba5f469cSkrishna 	session_p = *((soft_session_t **)s);
201ba5f469cSkrishna 	if (session_p == NULL || !(opflag & OP_SINGLE || opflag & OP_FINAL)) {
202ba5f469cSkrishna 		return (CKR_ARGUMENTS_BAD);
203ba5f469cSkrishna 	}
204ba5f469cSkrishna 
205ba5f469cSkrishna 	hmac_ctx = (soft_hmac_ctx_t *)session_p->verify.context;
206ba5f469cSkrishna 	len = hmac_ctx->hmac_len;
207ba5f469cSkrishna 
208ba5f469cSkrishna 	rv = soft_hmac_sign_verify_common(session_p, pData,
209ba5f469cSkrishna 	    ulDataLen, hmac, &len, B_FALSE);
210ba5f469cSkrishna 
211ba5f469cSkrishna 	if (rv == CKR_OK) {
212ba5f469cSkrishna 		if (len != ulSignatureLen) {
213ba5f469cSkrishna 			rv = CKR_SIGNATURE_LEN_RANGE;
214ba5f469cSkrishna 		}
215ba5f469cSkrishna 
216ba5f469cSkrishna 		if (memcmp(hmac, pSignature, len) != 0) {
217ba5f469cSkrishna 			rv = CKR_SIGNATURE_INVALID;
218ba5f469cSkrishna 		}
219ba5f469cSkrishna 	}
220ba5f469cSkrishna 
221ba5f469cSkrishna 	return (rv);
222ba5f469cSkrishna }
223ba5f469cSkrishna 
224ba5f469cSkrishna /*
225ba5f469cSkrishna  * Helper routine to handle the case when the ctx is abandoned.
226ba5f469cSkrishna  */
227ba5f469cSkrishna void
228ba5f469cSkrishna free_soft_ctx(void *s, int opflag)
229ba5f469cSkrishna {
230ba5f469cSkrishna 	soft_session_t *session_p;
231ba5f469cSkrishna 
232ba5f469cSkrishna 	session_p = (soft_session_t *)s;
233ba5f469cSkrishna 	if (session_p == NULL)
234ba5f469cSkrishna 		return;
235ba5f469cSkrishna 
236ba5f469cSkrishna 	if (opflag & OP_SIGN) {
237ba5f469cSkrishna 		if (session_p->sign.context == NULL)
238ba5f469cSkrishna 			return;
239ba5f469cSkrishna 		bzero(session_p->sign.context, sizeof (soft_hmac_ctx_t));
240ba5f469cSkrishna 		free(session_p->sign.context);
241ba5f469cSkrishna 		session_p->sign.context = NULL;
242ba5f469cSkrishna 		session_p->sign.flags = 0;
243ba5f469cSkrishna 	} else if (opflag & OP_VERIFY) {
244ba5f469cSkrishna 		if (session_p->verify.context == NULL)
245ba5f469cSkrishna 			return;
246ba5f469cSkrishna 		bzero(session_p->verify.context, sizeof (soft_hmac_ctx_t));
247ba5f469cSkrishna 		free(session_p->verify.context);
248ba5f469cSkrishna 		session_p->verify.context = NULL;
249ba5f469cSkrishna 		session_p->verify.flags = 0;
250ba5f469cSkrishna 	} else {
251ba5f469cSkrishna 		if (session_p->digest.context == NULL)
252ba5f469cSkrishna 			return;
253ba5f469cSkrishna 		free(session_p->digest.context);
254ba5f469cSkrishna 		session_p->digest.context = NULL;
255ba5f469cSkrishna 		session_p->digest.flags = 0;
256ba5f469cSkrishna 	}
257ba5f469cSkrishna }
258