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 https://opensource.org/licenses/CDDL-1.0.
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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/zfs_context.h>
27 #include <modes/modes.h>
28 #include <sys/crypto/common.h>
29 #include <sys/crypto/impl.h>
32 * Utility routine to copy a buffer to a crypto_data structure.
36 * Utility routine to apply the command COPY_TO_DATA to the
37 * data in the uio structure.
40 crypto_uio_copy_to_data(crypto_data_t
*data
, uchar_t
*buf
, int len
)
42 zfs_uio_t
*uiop
= data
->cd_uio
;
43 off_t offset
= data
->cd_offset
;
49 ASSERT(data
->cd_format
== CRYPTO_DATA_UIO
);
50 if (zfs_uio_segflg(uiop
) != UIO_SYSSPACE
) {
51 return (CRYPTO_ARGUMENTS_BAD
);
55 * Jump to the first iovec containing data to be
58 offset
= zfs_uio_index_at_offset(uiop
, offset
, &vec_idx
);
60 if (vec_idx
== zfs_uio_iovcnt(uiop
) && length
> 0) {
62 * The caller specified an offset that is larger than
63 * the total size of the buffers it provided.
65 return (CRYPTO_DATA_LEN_RANGE
);
68 while (vec_idx
< zfs_uio_iovcnt(uiop
) && length
> 0) {
69 cur_len
= MIN(zfs_uio_iovlen(uiop
, vec_idx
) -
72 datap
= (uchar_t
*)(zfs_uio_iovbase(uiop
, vec_idx
) + offset
);
73 memcpy(datap
, buf
, cur_len
);
81 if (vec_idx
== zfs_uio_iovcnt(uiop
) && length
> 0) {
83 * The end of the specified iovecs was reached but
84 * the length requested could not be processed.
86 data
->cd_length
= len
;
87 return (CRYPTO_BUFFER_TOO_SMALL
);
90 return (CRYPTO_SUCCESS
);
94 crypto_put_output_data(uchar_t
*buf
, crypto_data_t
*output
, int len
)
96 switch (output
->cd_format
) {
98 if (output
->cd_raw
.iov_len
< len
) {
99 output
->cd_length
= len
;
100 return (CRYPTO_BUFFER_TOO_SMALL
);
102 memcpy((uchar_t
*)(output
->cd_raw
.iov_base
+
103 output
->cd_offset
), buf
, len
);
106 case CRYPTO_DATA_UIO
:
107 return (crypto_uio_copy_to_data(output
, buf
, len
));
109 return (CRYPTO_ARGUMENTS_BAD
);
112 return (CRYPTO_SUCCESS
);
116 crypto_update_iov(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
117 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*))
119 ASSERT(input
!= output
);
121 if (input
->cd_raw
.iov_len
< input
->cd_length
)
122 return (CRYPTO_ARGUMENTS_BAD
);
124 return ((cipher
)(ctx
, input
->cd_raw
.iov_base
+ input
->cd_offset
,
125 input
->cd_length
, output
));
129 crypto_update_uio(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
130 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*))
132 zfs_uio_t
*uiop
= input
->cd_uio
;
133 off_t offset
= input
->cd_offset
;
134 size_t length
= input
->cd_length
;
138 ASSERT(input
!= output
);
140 if (zfs_uio_segflg(input
->cd_uio
) != UIO_SYSSPACE
) {
141 return (CRYPTO_ARGUMENTS_BAD
);
145 * Jump to the first iovec containing data to be
148 offset
= zfs_uio_index_at_offset(uiop
, offset
, &vec_idx
);
149 if (vec_idx
== zfs_uio_iovcnt(uiop
) && length
> 0) {
151 * The caller specified an offset that is larger than the
152 * total size of the buffers it provided.
154 return (CRYPTO_DATA_LEN_RANGE
);
158 * Now process the iovecs.
160 while (vec_idx
< zfs_uio_iovcnt(uiop
) && length
> 0) {
161 cur_len
= MIN(zfs_uio_iovlen(uiop
, vec_idx
) -
164 int rv
= (cipher
)(ctx
, zfs_uio_iovbase(uiop
, vec_idx
) + offset
,
167 if (rv
!= CRYPTO_SUCCESS
) {
175 if (vec_idx
== zfs_uio_iovcnt(uiop
) && length
> 0) {
177 * The end of the specified iovec's was reached but
178 * the length requested could not be processed, i.e.
179 * The caller requested to digest more data than it provided.
182 return (CRYPTO_DATA_LEN_RANGE
);
185 return (CRYPTO_SUCCESS
);