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]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
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.
41 is_hmac(CK_MECHANISM_TYPE mechanism
)
44 case CKM_SSL3_MD5_MAC
:
45 case CKM_SSL3_SHA1_MAC
:
46 case CKM_MD5_HMAC_GENERAL
:
48 case CKM_SHA_1_HMAC_GENERAL
:
50 case CKM_SHA256_HMAC_GENERAL
:
52 case CKM_SHA384_HMAC_GENERAL
:
54 case CKM_SHA512_HMAC_GENERAL
:
64 * Helper routine to allocate an emulation structure for the session.
65 * buflen indicates the size of the scratch buffer to be allocated.
68 emulate_buf_init(kernel_session_t
*session_p
, int buflen
, int opflag
)
71 crypto_active_op_t
*opp
;
73 opp
= (opflag
& OP_DIGEST
) ? &(session_p
->digest
) : \
74 ((opflag
& OP_SIGN
) ? &(session_p
->sign
) : &(session_p
->verify
));
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
) {
89 bufp
= opp
->context
= calloc(1, sizeof (digest_buf_t
));
91 return (CKR_HOST_MEMORY
);
95 if (bufp
->buf
== NULL
) {
96 bufp
->buf
= malloc(buflen
);
97 if (bufp
->buf
== NULL
) {
100 return (CKR_HOST_MEMORY
);
102 bufp
->buf_len
= buflen
;
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.
116 emulate_init(kernel_session_t
*session_p
, CK_MECHANISM_PTR pMechanism
,
117 crypto_key_t
*keyp
, int opflag
)
120 crypto_active_op_t
*opp
;
122 if ((rv
= emulate_buf_init(session_p
, EDIGEST_LENGTH
, opflag
)) !=
126 opp
= (opflag
& OP_SIGN
) ? &(session_p
->sign
) : &(session_p
->verify
);
129 rv
= do_soft_hmac_init(get_spp(opp
), pMechanism
, keyp
->ck_data
,
130 keyp
->ck_length
>> 3, opflag
);
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); \
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.
151 emulate_update(kernel_session_t
*session_p
, CK_BYTE_PTR pPart
,
152 CK_ULONG ulPartLen
, int opflag
)
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
);
172 return (CKR_ARGUMENTS_BAD
);
174 if (opp
->flags
& CRYPTO_EMULATE_USING_SW
) {
176 DO_SOFT_UPDATE(opp
, pPart
, ulPartLen
, opflag
);
177 opp
->flags
|= CRYPTO_EMULATE_UPDATE_DONE
;
183 return (CKR_FUNCTION_FAILED
);
186 /* Did we exceed the maximum allowed? */
187 if (bufp
->indata_len
+ ulPartLen
> maxlen
) {
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 */
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
);
217 DO_SOFT_UPDATE(opp
, bufp
->buf
, bufp
->indata_len
, opflag
);
218 opp
->flags
|= CRYPTO_EMULATE_UPDATE_DONE
;
220 DO_SOFT_UPDATE(opp
, pPart
, ulPartLen
, opflag
);
226 /* accumulate the update data */
227 bcopy(pPart
, bufp
->buf
+ bufp
->indata_len
, ulPartLen
);
228 bufp
->indata_len
+= ulPartLen
;