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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/strsun.h>
27 #include <sys/systm.h>
28 #include <sys/sysmacros.h>
33 #include <modes/modes.h>
34 #include <sys/crypto/common.h>
35 #include <sys/crypto/impl.h>
38 * Utility routine to get data from a crypto_data structure.
40 * '*dptr' contains a pointer to a buffer on return. 'buf'
41 * is allocated by the caller and is ignored for CRYPTO_DATA_RAW case.
44 crypto_get_input_data(crypto_data_t
*input
, uchar_t
**dptr
, uchar_t
*buf
)
48 switch (input
->cd_format
) {
50 if (input
->cd_raw
.iov_len
< input
->cd_length
)
51 return (CRYPTO_ARGUMENTS_BAD
);
52 *dptr
= (uchar_t
*)(input
->cd_raw
.iov_base
+
57 if ((rv
= crypto_uio_data(input
, buf
, input
->cd_length
,
58 COPY_FROM_DATA
, NULL
, NULL
)) != CRYPTO_SUCCESS
)
63 case CRYPTO_DATA_MBLK
:
64 if ((rv
= crypto_mblk_data(input
, buf
, input
->cd_length
,
65 COPY_FROM_DATA
, NULL
, NULL
)) != CRYPTO_SUCCESS
)
71 return (CRYPTO_ARGUMENTS_BAD
);
74 return (CRYPTO_SUCCESS
);
78 crypto_copy_key_to_ctx(crypto_key_t
*in_key
, crypto_key_t
**out_key
,
79 size_t *out_size
, int kmflag
)
84 crypto_object_attribute_t
*k_attrs
= NULL
;
87 ASSERT(in_key
->ck_format
== CRYPTO_KEY_ATTR_LIST
);
89 count
= in_key
->ck_count
;
90 /* figure out how much memory to allocate for everything */
91 len
= sizeof (crypto_key_t
) +
92 count
* sizeof (crypto_object_attribute_t
);
93 for (i
= 0; i
< count
; i
++) {
94 len
+= roundup(in_key
->ck_attrs
[i
].oa_value_len
,
98 /* one big allocation for everything */
99 key
= kmem_alloc(len
, kmflag
);
101 return (CRYPTO_HOST_MEMORY
);
102 k_attrs
= (crypto_object_attribute_t
*)(void *)((caddr_t
)key
+
103 sizeof (crypto_key_t
));
105 attr_val
= (caddr_t
)k_attrs
+
106 count
* sizeof (crypto_object_attribute_t
);
107 for (i
= 0; i
< count
; i
++) {
108 k_attrs
[i
].oa_type
= in_key
->ck_attrs
[i
].oa_type
;
109 bcopy(in_key
->ck_attrs
[i
].oa_value
, attr_val
,
110 in_key
->ck_attrs
[i
].oa_value_len
);
111 k_attrs
[i
].oa_value
= attr_val
;
112 k_attrs
[i
].oa_value_len
= in_key
->ck_attrs
[i
].oa_value_len
;
113 attr_val
+= roundup(k_attrs
[i
].oa_value_len
, sizeof (caddr_t
));
116 key
->ck_format
= CRYPTO_KEY_ATTR_LIST
;
117 key
->ck_count
= count
;
118 key
->ck_attrs
= k_attrs
;
120 *out_size
= len
; /* save the size to be freed */
122 return (CRYPTO_SUCCESS
);
126 crypto_digest_data(crypto_data_t
*data
, void *dctx
, uchar_t
*digest
,
127 void (*update
)(), void (*final
)(), uchar_t flag
)
132 ASSERT(flag
& CRYPTO_DO_MD5
|| flag
& CRYPTO_DO_SHA1
||
133 flag
& CRYPTO_DO_SHA2
);
135 ASSERT((flag
& CRYPTO_DO_UPDATE
) == 0);
139 dlen
= data
->cd_length
;
141 if (flag
& CRYPTO_DO_UPDATE
) {
143 switch (data
->cd_format
) {
144 case CRYPTO_DATA_RAW
:
145 dptr
= (uchar_t
*)(data
->cd_raw
.iov_base
+
148 update(dctx
, dptr
, dlen
);
152 case CRYPTO_DATA_UIO
:
153 if (flag
& CRYPTO_DO_MD5
)
154 rv
= crypto_uio_data(data
, NULL
, dlen
,
155 MD5_DIGEST_DATA
, dctx
, update
);
157 else if (flag
& CRYPTO_DO_SHA1
)
158 rv
= crypto_uio_data(data
, NULL
, dlen
,
159 SHA1_DIGEST_DATA
, dctx
, update
);
162 rv
= crypto_uio_data(data
, NULL
, dlen
,
163 SHA2_DIGEST_DATA
, dctx
, update
);
165 if (rv
!= CRYPTO_SUCCESS
)
170 case CRYPTO_DATA_MBLK
:
171 if (flag
& CRYPTO_DO_MD5
)
172 rv
= crypto_mblk_data(data
, NULL
, dlen
,
173 MD5_DIGEST_DATA
, dctx
, update
);
175 else if (flag
& CRYPTO_DO_SHA1
)
176 rv
= crypto_mblk_data(data
, NULL
, dlen
,
177 SHA1_DIGEST_DATA
, dctx
, update
);
180 rv
= crypto_mblk_data(data
, NULL
, dlen
,
181 SHA2_DIGEST_DATA
, dctx
, update
);
183 if (rv
!= CRYPTO_SUCCESS
)
191 if (flag
& CRYPTO_DO_FINAL
) {
195 return (CRYPTO_SUCCESS
);
199 crypto_update_iov(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
200 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*),
201 void (*copy_block
)(uint8_t *, uint64_t *))
203 common_ctx_t
*common_ctx
= ctx
;
206 if (input
->cd_miscdata
!= NULL
) {
207 copy_block((uint8_t *)input
->cd_miscdata
,
208 &common_ctx
->cc_iv
[0]);
211 if (input
->cd_raw
.iov_len
< input
->cd_length
)
212 return (CRYPTO_ARGUMENTS_BAD
);
214 rv
= (cipher
)(ctx
, input
->cd_raw
.iov_base
+ input
->cd_offset
,
215 input
->cd_length
, (input
== output
) ? NULL
: output
);
221 crypto_update_uio(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
222 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*),
223 void (*copy_block
)(uint8_t *, uint64_t *))
225 common_ctx_t
*common_ctx
= ctx
;
226 uio_t
*uiop
= input
->cd_uio
;
227 off_t offset
= input
->cd_offset
;
228 size_t length
= input
->cd_length
;
232 if (input
->cd_miscdata
!= NULL
) {
233 copy_block((uint8_t *)input
->cd_miscdata
,
234 &common_ctx
->cc_iv
[0]);
237 if (input
->cd_uio
->uio_segflg
!= UIO_SYSSPACE
) {
238 return (CRYPTO_ARGUMENTS_BAD
);
242 * Jump to the first iovec containing data to be
245 for (vec_idx
= 0; vec_idx
< uiop
->uio_iovcnt
&&
246 offset
>= uiop
->uio_iov
[vec_idx
].iov_len
;
247 offset
-= uiop
->uio_iov
[vec_idx
++].iov_len
)
249 if (vec_idx
== uiop
->uio_iovcnt
) {
251 * The caller specified an offset that is larger than the
252 * total size of the buffers it provided.
254 return (CRYPTO_DATA_LEN_RANGE
);
258 * Now process the iovecs.
260 while (vec_idx
< uiop
->uio_iovcnt
&& length
> 0) {
261 cur_len
= MIN(uiop
->uio_iov
[vec_idx
].iov_len
-
264 (cipher
)(ctx
, uiop
->uio_iov
[vec_idx
].iov_base
+ offset
,
265 cur_len
, (input
== output
) ? NULL
: output
);
272 if (vec_idx
== uiop
->uio_iovcnt
&& length
> 0) {
274 * The end of the specified iovec's was reached but
275 * the length requested could not be processed, i.e.
276 * The caller requested to digest more data than it provided.
279 return (CRYPTO_DATA_LEN_RANGE
);
282 return (CRYPTO_SUCCESS
);
286 crypto_update_mp(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
287 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*),
288 void (*copy_block
)(uint8_t *, uint64_t *))
290 common_ctx_t
*common_ctx
= ctx
;
291 off_t offset
= input
->cd_offset
;
292 size_t length
= input
->cd_length
;
296 if (input
->cd_miscdata
!= NULL
) {
297 copy_block((uint8_t *)input
->cd_miscdata
,
298 &common_ctx
->cc_iv
[0]);
302 * Jump to the first mblk_t containing data to be processed.
304 for (mp
= input
->cd_mp
; mp
!= NULL
&& offset
>= MBLKL(mp
);
305 offset
-= MBLKL(mp
), mp
= mp
->b_cont
)
309 * The caller specified an offset that is larger than the
310 * total size of the buffers it provided.
312 return (CRYPTO_DATA_LEN_RANGE
);
316 * Now do the processing on the mblk chain.
318 while (mp
!= NULL
&& length
> 0) {
319 cur_len
= MIN(MBLKL(mp
) - offset
, length
);
320 (cipher
)(ctx
, (char *)(mp
->b_rptr
+ offset
), cur_len
,
321 (input
== output
) ? NULL
: output
);
328 if (mp
== NULL
&& length
> 0) {
330 * The end of the mblk was reached but the length requested
331 * could not be processed, i.e. The caller requested
332 * to digest more data than it provided.
334 return (CRYPTO_DATA_LEN_RANGE
);
337 return (CRYPTO_SUCCESS
);
341 * Utility routine to look up a attribute of type, 'type',
345 crypto_get_key_attr(crypto_key_t
*key
, crypto_attr_type_t type
,
346 uchar_t
**value
, ssize_t
*value_len
)
350 ASSERT(key
->ck_format
== CRYPTO_KEY_ATTR_LIST
);
351 for (i
= 0; i
< key
->ck_count
; i
++) {
352 if (key
->ck_attrs
[i
].oa_type
== type
) {
353 *value
= (uchar_t
*)key
->ck_attrs
[i
].oa_value
;
354 *value_len
= key
->ck_attrs
[i
].oa_value_len
;
355 return (CRYPTO_SUCCESS
);
359 return (CRYPTO_FAILED
);