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