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
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)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
do_soft_hmac_init(void ** s,CK_MECHANISM_PTR pMechanism,CK_BYTE_PTR kval,CK_ULONG klen,int opflag)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
do_soft_hmac_update(void ** s,CK_BYTE_PTR pData,CK_ULONG ulDataLen,int opflag)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
do_soft_hmac_sign(void ** s,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG_PTR pulSignatureLen,int opflag)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
do_soft_hmac_verify(void ** s,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,int opflag)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
free_soft_ctx(void * s,int opflag)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