8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_kernel / common / kernelEmulate.c
blob2c586049dae055f7fdc733ab233ac9366f97ea82
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <errno.h>
28 #include <stdio.h>
29 #include <strings.h>
30 #include <sys/crypto/ioctl.h>
31 #include <security/cryptoki.h>
32 #include "kernelGlobal.h"
33 #include "kernelSession.h"
34 #include "kernelEmulate.h"
37 * Helper routine to know if this is a HMAC. We can't just check
38 * the CKF_SIGN mech flag as it is set for non-HMAC mechs too.
40 boolean_t
41 is_hmac(CK_MECHANISM_TYPE mechanism)
43 switch (mechanism) {
44 case CKM_SSL3_MD5_MAC:
45 case CKM_SSL3_SHA1_MAC:
46 case CKM_MD5_HMAC_GENERAL:
47 case CKM_MD5_HMAC:
48 case CKM_SHA_1_HMAC_GENERAL:
49 case CKM_SHA_1_HMAC:
50 case CKM_SHA256_HMAC_GENERAL:
51 case CKM_SHA256_HMAC:
52 case CKM_SHA384_HMAC_GENERAL:
53 case CKM_SHA384_HMAC:
54 case CKM_SHA512_HMAC_GENERAL:
55 case CKM_SHA512_HMAC:
56 return (B_TRUE);
58 default:
59 return (B_FALSE);
64 * Helper routine to allocate an emulation structure for the session.
65 * buflen indicates the size of the scratch buffer to be allocated.
67 CK_RV
68 emulate_buf_init(kernel_session_t *session_p, int buflen, int opflag)
70 digest_buf_t *bufp;
71 crypto_active_op_t *opp;
73 opp = (opflag & OP_DIGEST) ? &(session_p->digest) : \
74 ((opflag & OP_SIGN) ? &(session_p->sign) : &(session_p->verify));
76 bufp = opp->context;
78 if (bufp != NULL) {
79 bufp->indata_len = 0;
81 * We can reuse the context structure, digest_buf_t.
82 * See if we can reuse the scratch buffer in the context too.
84 if (buflen > bufp->buf_len) {
85 free(bufp->buf);
86 bufp->buf = NULL;
88 } else {
89 bufp = opp->context = calloc(1, sizeof (digest_buf_t));
90 if (bufp == NULL) {
91 return (CKR_HOST_MEMORY);
95 if (bufp->buf == NULL) {
96 bufp->buf = malloc(buflen);
97 if (bufp->buf == NULL) {
98 free(bufp);
99 opp->context = NULL;
100 return (CKR_HOST_MEMORY);
102 bufp->buf_len = buflen;
105 return (CKR_OK);
109 * Setup the support necessary to do this operation in a
110 * single part. We allocate a buffer to accumulate the
111 * input data from later calls. We also get ready for
112 * the case where we have to do it in software by initializing
113 * a standby context. The opflag tells if this is a sign or verify.
115 CK_RV
116 emulate_init(kernel_session_t *session_p, CK_MECHANISM_PTR pMechanism,
117 crypto_key_t *keyp, int opflag)
119 CK_RV rv;
120 crypto_active_op_t *opp;
122 if ((rv = emulate_buf_init(session_p, EDIGEST_LENGTH, opflag)) !=
123 CKR_OK)
124 return (rv);
126 opp = (opflag & OP_SIGN) ? &(session_p->sign) : &(session_p->verify);
128 opflag |= OP_INIT;
129 rv = do_soft_hmac_init(get_spp(opp), pMechanism, keyp->ck_data,
130 keyp->ck_length >> 3, opflag);
132 return (rv);
135 #define DO_SOFT_UPDATE(opp, pPart, ulPartLen, opflag) \
136 if ((opflag) & OP_DIGEST) { \
137 rv = do_soft_digest(get_spp(opp), NULL, pPart, \
138 ulPartLen, NULL, NULL, opflag); \
139 } else { \
140 rv = do_soft_hmac_update(get_spp(opp), pPart, \
141 ulPartLen, opflag); \
145 * Accumulate the input data in the buffer, allocating a bigger
146 * buffer if needed. If we reach the maximum input data size
147 * that can be accumulated, start using the software from then on.
148 * The opflag tells if this is a digest, sign or verify.
150 CK_RV
151 emulate_update(kernel_session_t *session_p, CK_BYTE_PTR pPart,
152 CK_ULONG ulPartLen, int opflag)
154 CK_RV rv;
155 int maxlen;
156 digest_buf_t *bufp;
157 boolean_t use_soft = B_FALSE;
158 crypto_active_op_t *opp;
160 if (opflag & OP_DIGEST) {
161 opp = &(session_p->digest);
162 if (!SLOT_HAS_LIMITED_HASH(session_p))
163 return (CKR_ARGUMENTS_BAD);
164 maxlen = SLOT_HASH_MAX_INDATA_LEN(session_p);
165 } else if (opflag & (OP_SIGN | OP_VERIFY)) {
166 opp = (opflag & OP_SIGN) ?
167 &(session_p->sign) : &(session_p->verify);
168 if (!SLOT_HAS_LIMITED_HMAC(session_p))
169 return (CKR_ARGUMENTS_BAD);
170 maxlen = SLOT_HMAC_MAX_INDATA_LEN(session_p);
171 } else
172 return (CKR_ARGUMENTS_BAD);
174 if (opp->flags & CRYPTO_EMULATE_USING_SW) {
175 opflag |= OP_UPDATE;
176 DO_SOFT_UPDATE(opp, pPart, ulPartLen, opflag);
177 opp->flags |= CRYPTO_EMULATE_UPDATE_DONE;
178 return (rv);
181 bufp = opp->context;
182 if (bufp == NULL) {
183 return (CKR_FUNCTION_FAILED);
186 /* Did we exceed the maximum allowed? */
187 if (bufp->indata_len + ulPartLen > maxlen) {
188 use_soft = B_TRUE;
189 } else if (ulPartLen > (bufp->buf_len - bufp->indata_len)) {
190 int siz = ulPartLen < bufp->buf_len ?
191 bufp->buf_len * 2 : bufp->buf_len + ulPartLen;
192 uint8_t *old = bufp->buf;
194 bufp->buf = realloc(bufp->buf, siz);
195 if (bufp->buf == NULL) {
196 /* Try harder rather than failing */
197 bufp->buf = old;
198 use_soft = B_TRUE;
199 } else
200 bufp->buf_len = siz;
203 if (use_soft) {
204 opp->flags |= CRYPTO_EMULATE_USING_SW;
206 if (opflag & OP_DIGEST) {
207 CK_MECHANISM_PTR pMechanism;
209 pMechanism = &(opp->mech);
210 rv = do_soft_digest(get_spp(opp), pMechanism, NULL, 0,
211 NULL, NULL, OP_INIT);
212 if (rv != CKR_OK)
213 return (rv);
216 opflag |= OP_UPDATE;
217 DO_SOFT_UPDATE(opp, bufp->buf, bufp->indata_len, opflag);
218 opp->flags |= CRYPTO_EMULATE_UPDATE_DONE;
219 if (rv == CKR_OK) {
220 DO_SOFT_UPDATE(opp, pPart, ulPartLen, opflag);
223 return (rv);
226 /* accumulate the update data */
227 bcopy(pPart, bufp->buf + bufp->indata_len, ulPartLen);
228 bufp->indata_len += ulPartLen;
230 return (CKR_OK);