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