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