14072Skrishna /*
24072Skrishna * CDDL HEADER START
34072Skrishna *
44072Skrishna * The contents of this file are subject to the terms of the
54072Skrishna * Common Development and Distribution License (the "License").
64072Skrishna * You may not use this file except in compliance with the License.
74072Skrishna *
84072Skrishna * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94072Skrishna * or http://www.opensolaris.org/os/licensing.
104072Skrishna * See the License for the specific language governing permissions
114072Skrishna * and limitations under the License.
124072Skrishna *
134072Skrishna * When distributing Covered Code, include this CDDL HEADER in each
144072Skrishna * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154072Skrishna * If applicable, add the following below this CDDL HEADER, with the
164072Skrishna * fields enclosed by brackets "[]" replaced with your own identifying
174072Skrishna * information: Portions Copyright [yyyy] [name of copyright owner]
184072Skrishna *
194072Skrishna * CDDL HEADER END
204072Skrishna */
214072Skrishna
224072Skrishna /*
234072Skrishna * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
244072Skrishna * Use is subject to license terms.
254072Skrishna */
264072Skrishna
274072Skrishna #pragma ident "%Z%%M% %I% %E% SMI"
284072Skrishna
294072Skrishna #include <pthread.h>
304072Skrishna #include <errno.h>
314072Skrishna #include <stdio.h>
324072Skrishna #include <strings.h>
334072Skrishna #include <sys/crypto/ioctl.h>
344072Skrishna #include <security/cryptoki.h>
354072Skrishna #include <security/pkcs11t.h>
364072Skrishna #include "softSession.h"
374072Skrishna #include "softObject.h"
384072Skrishna #include "softOps.h"
394072Skrishna #include "softMAC.h"
404072Skrishna #include "kernelSoftCommon.h"
414072Skrishna
424072Skrishna /*
43*5616Skrishna * Do the operation(s) specified by opflag.
444072Skrishna */
454072Skrishna 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)464072Skrishna do_soft_digest(void **s, CK_MECHANISM_PTR pMechanism, CK_BYTE_PTR pData,
474072Skrishna CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen,
484072Skrishna int opflag)
494072Skrishna {
504072Skrishna soft_session_t *session_p;
51*5616Skrishna CK_RV rv = CKR_ARGUMENTS_BAD;
524072Skrishna
534072Skrishna session_p = *((soft_session_t **)s);
544072Skrishna if (session_p == NULL) {
554072Skrishna if (!(opflag & OP_INIT)) {
564072Skrishna return (CKR_ARGUMENTS_BAD);
574072Skrishna }
584072Skrishna
594072Skrishna session_p = calloc(1, sizeof (soft_session_t));
604072Skrishna /*
614072Skrishna * Initialize the lock for the newly created session.
624072Skrishna * We do only the minimum needed setup for the
634072Skrishna * soft_digest* routines to succeed.
644072Skrishna */
654072Skrishna if (pthread_mutex_init(&session_p->session_mutex, NULL) != 0) {
664072Skrishna free(session_p);
674072Skrishna return (CKR_CANT_LOCK);
684072Skrishna }
694072Skrishna
704072Skrishna *s = session_p;
714072Skrishna } else if (opflag & OP_INIT) {
724072Skrishna free_soft_ctx(session_p, OP_DIGEST);
734072Skrishna }
744072Skrishna
75*5616Skrishna if (opflag & OP_INIT) {
764072Skrishna rv = soft_digest_init(session_p, pMechanism);
77*5616Skrishna if (rv != CKR_OK)
78*5616Skrishna return (rv);
79*5616Skrishna }
804072Skrishna
81*5616Skrishna if (opflag & OP_SINGLE) {
824072Skrishna rv = soft_digest(session_p, pData, ulDataLen,
834072Skrishna pDigest, pulDigestLen);
84*5616Skrishna } else {
85*5616Skrishna if (opflag & OP_UPDATE) {
86*5616Skrishna rv = soft_digest_update(session_p, pData, ulDataLen);
87*5616Skrishna if (rv != CKR_OK)
88*5616Skrishna return (rv);
89*5616Skrishna }
904072Skrishna
91*5616Skrishna if (opflag & OP_FINAL) {
92*5616Skrishna rv = soft_digest_final(session_p,
93*5616Skrishna pDigest, pulDigestLen);
94*5616Skrishna }
954072Skrishna }
964072Skrishna
974072Skrishna return (rv);
984072Skrishna }
994072Skrishna
1004072Skrishna /*
1014072Skrishna * opflag specifies whether this is a sign or verify.
1024072Skrishna */
1034072Skrishna CK_RV
do_soft_hmac_init(void ** s,CK_MECHANISM_PTR pMechanism,CK_BYTE_PTR kval,CK_ULONG klen,int opflag)1044072Skrishna do_soft_hmac_init(void **s, CK_MECHANISM_PTR pMechanism,
1054072Skrishna CK_BYTE_PTR kval, CK_ULONG klen, int opflag)
1064072Skrishna {
1074072Skrishna CK_RV rv;
1084072Skrishna soft_object_t keyobj;
1094072Skrishna secret_key_obj_t skeyobj;
1104072Skrishna soft_object_t *key_p;
1114072Skrishna soft_session_t *session_p;
1124072Skrishna
1134072Skrishna session_p = *((soft_session_t **)s);
1144072Skrishna if (session_p == NULL) {
1154072Skrishna session_p = calloc(1, sizeof (soft_session_t));
1164072Skrishna /* See comments in do_soft_digest() above */
1174072Skrishna if (pthread_mutex_init(&session_p->session_mutex, NULL) != 0) {
1184072Skrishna free(session_p);
1194072Skrishna return (CKR_CANT_LOCK);
1204072Skrishna }
1214072Skrishna
1224072Skrishna *s = session_p;
1234072Skrishna } else if (opflag & OP_INIT) {
1244072Skrishna free_soft_ctx(session_p, opflag);
1254072Skrishna }
1264072Skrishna
1274072Skrishna /* Do the minimum needed setup for the call to succeed */
1284072Skrishna key_p = &keyobj;
1294072Skrishna bzero(key_p, sizeof (soft_object_t));
1304072Skrishna key_p->class = CKO_SECRET_KEY;
1314072Skrishna key_p->key_type = CKK_GENERIC_SECRET;
1324072Skrishna
1334072Skrishna bzero(&skeyobj, sizeof (secret_key_obj_t));
1344072Skrishna OBJ_SEC(key_p) = &skeyobj;
1354072Skrishna OBJ_SEC_VALUE(key_p) = kval;
1364072Skrishna OBJ_SEC_VALUE_LEN(key_p) = klen;
1374072Skrishna
1384072Skrishna rv = soft_hmac_sign_verify_init_common(session_p, pMechanism,
1394072Skrishna key_p, opflag & OP_SIGN);
1404072Skrishna
1414072Skrishna return (rv);
1424072Skrishna }
1434072Skrishna
1444072Skrishna /*
1454072Skrishna * opflag specifies whether this is a sign or verify.
1464072Skrishna */
1474072Skrishna CK_RV
do_soft_hmac_update(void ** s,CK_BYTE_PTR pData,CK_ULONG ulDataLen,int opflag)1484072Skrishna do_soft_hmac_update(void **s, CK_BYTE_PTR pData, CK_ULONG ulDataLen, int opflag)
1494072Skrishna {
1504072Skrishna soft_session_t *session_p;
1514072Skrishna
1524072Skrishna session_p = *((soft_session_t **)s);
1534072Skrishna if (session_p == NULL) {
1544072Skrishna return (CKR_ARGUMENTS_BAD);
1554072Skrishna }
1564072Skrishna
1574072Skrishna return (soft_hmac_sign_verify_update(session_p,
1584072Skrishna pData, ulDataLen, opflag & OP_SIGN));
1594072Skrishna }
1604072Skrishna
1614072Skrishna /*
1624072Skrishna * opflag specifies whether this is a final or single.
1634072Skrishna */
1644072Skrishna 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)1654072Skrishna do_soft_hmac_sign(void **s, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
1664072Skrishna CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen, int opflag)
1674072Skrishna {
1684072Skrishna CK_RV rv;
1694072Skrishna soft_session_t *session_p;
1704072Skrishna CK_BYTE hmac[SHA512_DIGEST_LENGTH]; /* use the maximum size */
1714072Skrishna
1724072Skrishna session_p = *((soft_session_t **)s);
1734072Skrishna if (session_p == NULL || !(opflag & OP_SINGLE || opflag & OP_FINAL)) {
1744072Skrishna return (CKR_ARGUMENTS_BAD);
1754072Skrishna }
1764072Skrishna
1774072Skrishna rv = soft_hmac_sign_verify_common(session_p, pData, ulDataLen,
1784072Skrishna (pSignature != NULL ? hmac : NULL), pulSignatureLen, B_TRUE);
1794072Skrishna
1804072Skrishna if ((rv == CKR_OK) && (pSignature != NULL)) {
1814072Skrishna (void) memcpy(pSignature, hmac, *pulSignatureLen);
1824072Skrishna }
1834072Skrishna
1844072Skrishna return (rv);
1854072Skrishna }
1864072Skrishna
1874072Skrishna /*
1884072Skrishna * opflag specifies whether this is a final or single.
1894072Skrishna */
1904072Skrishna CK_RV
do_soft_hmac_verify(void ** s,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,int opflag)1914072Skrishna do_soft_hmac_verify(void **s, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
1924072Skrishna CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, int opflag)
1934072Skrishna {
1944072Skrishna CK_RV rv;
1954072Skrishna CK_ULONG len;
1964072Skrishna soft_session_t *session_p;
1974072Skrishna soft_hmac_ctx_t *hmac_ctx;
1984072Skrishna CK_BYTE hmac[SHA512_DIGEST_LENGTH]; /* use the maximum size */
1994072Skrishna
2004072Skrishna session_p = *((soft_session_t **)s);
2014072Skrishna if (session_p == NULL || !(opflag & OP_SINGLE || opflag & OP_FINAL)) {
2024072Skrishna return (CKR_ARGUMENTS_BAD);
2034072Skrishna }
2044072Skrishna
2054072Skrishna hmac_ctx = (soft_hmac_ctx_t *)session_p->verify.context;
2064072Skrishna len = hmac_ctx->hmac_len;
2074072Skrishna
2084072Skrishna rv = soft_hmac_sign_verify_common(session_p, pData,
2094072Skrishna ulDataLen, hmac, &len, B_FALSE);
2104072Skrishna
2114072Skrishna if (rv == CKR_OK) {
2124072Skrishna if (len != ulSignatureLen) {
2134072Skrishna rv = CKR_SIGNATURE_LEN_RANGE;
2144072Skrishna }
2154072Skrishna
2164072Skrishna if (memcmp(hmac, pSignature, len) != 0) {
2174072Skrishna rv = CKR_SIGNATURE_INVALID;
2184072Skrishna }
2194072Skrishna }
2204072Skrishna
2214072Skrishna return (rv);
2224072Skrishna }
2234072Skrishna
2244072Skrishna /*
2254072Skrishna * Helper routine to handle the case when the ctx is abandoned.
2264072Skrishna */
2274072Skrishna void
free_soft_ctx(void * s,int opflag)2284072Skrishna free_soft_ctx(void *s, int opflag)
2294072Skrishna {
2304072Skrishna soft_session_t *session_p;
2314072Skrishna
2324072Skrishna session_p = (soft_session_t *)s;
2334072Skrishna if (session_p == NULL)
2344072Skrishna return;
2354072Skrishna
2364072Skrishna if (opflag & OP_SIGN) {
2374072Skrishna if (session_p->sign.context == NULL)
2384072Skrishna return;
2394072Skrishna bzero(session_p->sign.context, sizeof (soft_hmac_ctx_t));
2404072Skrishna free(session_p->sign.context);
2414072Skrishna session_p->sign.context = NULL;
2424072Skrishna session_p->sign.flags = 0;
2434072Skrishna } else if (opflag & OP_VERIFY) {
2444072Skrishna if (session_p->verify.context == NULL)
2454072Skrishna return;
2464072Skrishna bzero(session_p->verify.context, sizeof (soft_hmac_ctx_t));
2474072Skrishna free(session_p->verify.context);
2484072Skrishna session_p->verify.context = NULL;
2494072Skrishna session_p->verify.flags = 0;
2504072Skrishna } else {
2514072Skrishna if (session_p->digest.context == NULL)
2524072Skrishna return;
2534072Skrishna free(session_p->digest.context);
2544072Skrishna session_p->digest.context = NULL;
2554072Skrishna session_p->digest.flags = 0;
2564072Skrishna }
2574072Skrishna }
258