]>
git.proxmox.com Git - mirror_zfs.git/blob - module/icp/core/kcf_prov_lib.c
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 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, 'cmd', to the
37 * data in the uio structure.
40 crypto_uio_data(crypto_data_t
*data
, uchar_t
*buf
, int len
, cmd_type_t cmd
,
41 void *digest_ctx
, void (*update
)(void))
43 uio_t
*uiop
= data
->cd_uio
;
44 off_t offset
= data
->cd_offset
;
50 ASSERT(data
->cd_format
== CRYPTO_DATA_UIO
);
51 if (uiop
->uio_segflg
!= UIO_SYSSPACE
) {
52 return (CRYPTO_ARGUMENTS_BAD
);
56 * Jump to the first iovec containing data to be
59 for (vec_idx
= 0; vec_idx
< uiop
->uio_iovcnt
&&
60 offset
>= uiop
->uio_iov
[vec_idx
].iov_len
;
61 offset
-= uiop
->uio_iov
[vec_idx
++].iov_len
)
64 if (vec_idx
== uiop
->uio_iovcnt
&& length
> 0) {
66 * The caller specified an offset that is larger than
67 * the total size of the buffers it provided.
69 return (CRYPTO_DATA_LEN_RANGE
);
72 while (vec_idx
< uiop
->uio_iovcnt
&& length
> 0) {
73 cur_len
= MIN(uiop
->uio_iov
[vec_idx
].iov_len
-
76 datap
= (uchar_t
*)(uiop
->uio_iov
[vec_idx
].iov_base
+
80 bcopy(datap
, buf
, cur_len
);
84 bcopy(buf
, datap
, cur_len
);
88 if (bcmp(datap
, buf
, cur_len
))
89 return (CRYPTO_SIGNATURE_INVALID
);
93 case SHA1_DIGEST_DATA
:
94 case SHA2_DIGEST_DATA
:
96 return (CRYPTO_ARGUMENTS_BAD
);
104 if (vec_idx
== uiop
->uio_iovcnt
&& length
> 0) {
106 * The end of the specified iovec's was reached but
107 * the length requested could not be processed.
111 data
->cd_length
= len
;
112 return (CRYPTO_BUFFER_TOO_SMALL
);
114 return (CRYPTO_DATA_LEN_RANGE
);
118 return (CRYPTO_SUCCESS
);
122 crypto_put_output_data(uchar_t
*buf
, crypto_data_t
*output
, int len
)
124 switch (output
->cd_format
) {
125 case CRYPTO_DATA_RAW
:
126 if (output
->cd_raw
.iov_len
< len
) {
127 output
->cd_length
= len
;
128 return (CRYPTO_BUFFER_TOO_SMALL
);
130 bcopy(buf
, (uchar_t
*)(output
->cd_raw
.iov_base
+
131 output
->cd_offset
), len
);
134 case CRYPTO_DATA_UIO
:
135 return (crypto_uio_data(output
, buf
, len
,
136 COPY_TO_DATA
, NULL
, NULL
));
138 return (CRYPTO_ARGUMENTS_BAD
);
141 return (CRYPTO_SUCCESS
);
145 crypto_update_iov(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
146 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*),
147 void (*copy_block
)(uint8_t *, uint64_t *))
149 common_ctx_t
*common_ctx
= ctx
;
152 if (input
->cd_miscdata
!= NULL
) {
153 copy_block((uint8_t *)input
->cd_miscdata
,
154 &common_ctx
->cc_iv
[0]);
157 if (input
->cd_raw
.iov_len
< input
->cd_length
)
158 return (CRYPTO_ARGUMENTS_BAD
);
160 rv
= (cipher
)(ctx
, input
->cd_raw
.iov_base
+ input
->cd_offset
,
161 input
->cd_length
, (input
== output
) ? NULL
: output
);
167 crypto_update_uio(void *ctx
, crypto_data_t
*input
, crypto_data_t
*output
,
168 int (*cipher
)(void *, caddr_t
, size_t, crypto_data_t
*),
169 void (*copy_block
)(uint8_t *, uint64_t *))
171 common_ctx_t
*common_ctx
= ctx
;
172 uio_t
*uiop
= input
->cd_uio
;
173 off_t offset
= input
->cd_offset
;
174 size_t length
= input
->cd_length
;
178 if (input
->cd_miscdata
!= NULL
) {
179 copy_block((uint8_t *)input
->cd_miscdata
,
180 &common_ctx
->cc_iv
[0]);
183 if (input
->cd_uio
->uio_segflg
!= UIO_SYSSPACE
) {
184 return (CRYPTO_ARGUMENTS_BAD
);
188 * Jump to the first iovec containing data to be
191 for (vec_idx
= 0; vec_idx
< uiop
->uio_iovcnt
&&
192 offset
>= uiop
->uio_iov
[vec_idx
].iov_len
;
193 offset
-= uiop
->uio_iov
[vec_idx
++].iov_len
)
195 if (vec_idx
== uiop
->uio_iovcnt
&& length
> 0) {
197 * The caller specified an offset that is larger than the
198 * total size of the buffers it provided.
200 return (CRYPTO_DATA_LEN_RANGE
);
204 * Now process the iovecs.
206 while (vec_idx
< uiop
->uio_iovcnt
&& length
> 0) {
207 cur_len
= MIN(uiop
->uio_iov
[vec_idx
].iov_len
-
210 (cipher
)(ctx
, uiop
->uio_iov
[vec_idx
].iov_base
+ offset
,
211 cur_len
, (input
== output
) ? NULL
: output
);
218 if (vec_idx
== uiop
->uio_iovcnt
&& length
> 0) {
220 * The end of the specified iovec's was reached but
221 * the length requested could not be processed, i.e.
222 * The caller requested to digest more data than it provided.
225 return (CRYPTO_DATA_LEN_RANGE
);
228 return (CRYPTO_SUCCESS
);