OCF: Remove support for asymmetric cryptographic operations.

There haven't been any non-obscure drivers that supported this
functionality and it has been impossible to test to ensure that it
still works.  The only known consumer of this interface was the engine
in OpenSSL < 1.1.  Modern OpenSSL versions do not include support for
this interface as it was not well-documented.

Reviewed by:	cem
Sponsored by:	Chelsio Communications
Differential Revision:	https://reviews.freebsd.org/D29736
This commit is contained in:
John Baldwin 2021-04-12 14:27:42 -07:00
parent 89df484739
commit 76681661be
15 changed files with 56 additions and 1347 deletions

View file

@ -40,6 +40,13 @@
# xargs -n1 | sort | uniq -d;
# done
# 20210412: Remove kernel asymmetric crypto
OLD_FILES+=usr/share/man/man9/crypto_asym.9
OLD_FILES+=usr/share/man/man9/crypto_kdispatch.9
OLD_FILES+=usr/share/man/man9/crypto_kdone.9
OLD_FILES+=usr/share/man/man9/crypto_kregister.9
OLD_FILES+=usr/share/man/man9/CRYPTODEV_KPROCESS.9
# 20210410: remove unused libexec/rc.d/archdep
OLD_FILES+=etc/rc.d/archdep

View file

@ -60,7 +60,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd November 24, 2020
.Dd April 12, 2021
.Dt CRYPTO 4
.Os
.Sh NAME
@ -93,53 +93,32 @@ then issue
calls on the descriptor.
User-mode access to
.Pa /dev/crypto
is controlled by two
is controlled by the
.Ic kern.cryptodevallowsoft
.Xr sysctl 8
variables:
.Ic kern.userasymcrypto
and
.Ic kern.cryptodevallowsoft .
.Pp
The
.Nm
device provides two distinct modes of operation: one mode for
symmetric-keyed cryptographic requests and digests, and a second mode for
both asymmetric-key (public-key/private-key) requests and
modular arithmetic (for Diffie-Hellman key exchange and other
cryptographic protocols).
The two modes are described separately below.
.Sh DEPRECATION NOTICE
The asymmetric-key operations supported by this interface will not be
present in
.Fx 14.0
and later.
variable.
If this variable is zero,
then user-mode sessions are only permitted to use cryptography coprocessors.
.Sh THEORY OF OPERATION
Regardless of whether symmetric-key or asymmetric-key operations are
to be performed, use of the device requires a basic series of steps:
Use of the device requires a basic series of steps:
.Bl -enum
.It
Open the
.Pa /dev/crypto
device.
.It
If any symmetric-keyed cryptographic or digest operations will be performed,
create a session with
Create a session with
.Dv CIOCGSESSION
or
.Dv CIOCGSESSION2 .
Most applications will require at least one symmetric session.
Applications will require at least one symmetric session.
Since cipher and MAC keys are tied to sessions, many
applications will require more.
Asymmetric operations do not use sessions.
.It
Submit requests, synchronously with
.Dv CIOCCRYPT
(symmetric),
.Dv CIOCCRYPTAEAD
(symmetric),
or
.Dv CIOCKEY
(asymmetric).
.Dv CIOCCRYPTAEAD .
.It
Optionally destroy a session with
.Dv CIOCFSESSION .
@ -151,22 +130,27 @@ This will automatically close any remaining sessions associated with the
file desriptor.
.El
.Sh SYMMETRIC-KEY OPERATION
The symmetric-key operation mode provides a context-based API
.Nm cryptodev
provides a context-based API
to traditional symmetric-key encryption (or privacy) algorithms,
or to keyed and unkeyed one-way hash (HMAC and MAC) algorithms.
The symmetric-key mode also permits encrypt-then-authenticate fused operation,
where the hardware performs both a privacy algorithm and an integrity-check
keyed and unkeyed one-way hash (HMAC and MAC) algorithms,
encrypt-then-authenticate (ETA) fused operations,
and authenticated encryption with additional data (AEAD) operations.
For ETA operations,
drivers perform both a privacy algorithm and an integrity-check
algorithm in a single pass over the data: either a fused
encrypt/HMAC-generate operation, or a fused HMAC-verify/decrypt operation.
Similarly, for AEAD operations,
drivers perform either an encrypt/MAC-generate operation
or a MAC-verify/decrypt operation.
.Pp
To use symmetric mode, you must first create a session specifying
the algorithm(s) and key(s) to use; then issue encrypt or decrypt
requests against the session.
The algorithm(s) and key(s) to use are specified when a session is
created.
Individual requests are able to specify per-request initialization vectors
or nonces.
.Ss Algorithms
For a list of supported algorithms, see
.Xr crypto 7
and
.Xr crypto 9 .
.Xr crypto 7 .
.Ss IOCTL Request Descriptions
.\"
.Bl -tag -width CIOCGSESSION
@ -216,11 +200,13 @@ privacy algorithm, integrity algorithm, and keys specified in
The special value 0 for either privacy or integrity
is reserved to indicate that the indicated operation (privacy or integrity)
is not desired for this session.
ETA sessions specify both privacy and integrity algorithms.
AEAD sessions specify only a privacy algorithm.
.Pp
Multiple sessions may be bound to a single file descriptor.
The session ID returned in
.Fa sessp-\*[Gt]ses
is supplied as a required field in the symmetric-operation structure
is supplied as a required field in the operation structure
.Fa crypt_op
for future encryption or hashing requests.
.\" .Pp
@ -229,7 +215,7 @@ for future encryption or hashing requests.
.\" .Nx
.\" extension.
.Pp
For non-zero symmetric-key privacy algorithms, the privacy algorithm
For non-zero privacy algorithms, the privacy algorithm
must be specified in
.Fa sessp-\*[Gt]cipher ,
the key length in
@ -290,7 +276,7 @@ struct crypt_op {
};
.Ed
Request a symmetric-key (or hash) operation.
Request an encryption/decryption (or hash) operation.
To encrypt, set
.Fa cr_op-\*[Gt]op
to
@ -344,75 +330,6 @@ to include in the authentication mode.
Destroys the session identified by
.Fa ses_id .
.El
.\"
.Sh ASYMMETRIC-KEY OPERATION
.Ss Asymmetric-key algorithms
Contingent upon hardware support, the following asymmetric
(public-key/private-key; or key-exchange subroutine) operations may
also be available:
.Pp
.Bl -column "CRK_DH_COMPUTE_KEY" "Input parameter" "Output parameter" -offset indent -compact
.It Em "Algorithm" Ta "Input parameter" Ta "Output parameter"
.It Em " " Ta "Count" Ta "Count"
.It Dv CRK_MOD_EXP Ta 3 Ta 1
.It Dv CRK_MOD_EXP_CRT Ta 6 Ta 1
.It Dv CRK_DSA_SIGN Ta 5 Ta 2
.It Dv CRK_DSA_VERIFY Ta 7 Ta 0
.It Dv CRK_DH_COMPUTE_KEY Ta 3 Ta 1
.El
.Pp
See below for discussion of the input and output parameter counts.
.Ss Asymmetric-key commands
.Bl -tag -width CIOCKEY
.It Dv CIOCASYMFEAT Fa int *feature_mask
Returns a bitmask of supported asymmetric-key operations.
Each of the above-listed asymmetric operations is present
if and only if the bit position numbered by the code for that operation
is set.
For example,
.Dv CRK_MOD_EXP
is available if and only if the bit
.Pq 1 \*[Lt]\*[Lt] Dv CRK_MOD_EXP
is set.
.It Dv CIOCKEY Fa struct crypt_kop *kop
.Bd -literal
struct crypt_kop {
u_int crk_op; /* e.g. CRK_MOD_EXP */
u_int crk_status; /* return status */
u_short crk_iparams; /* # of input params */
u_short crk_oparams; /* # of output params */
u_int crk_pad1;
struct crparam crk_param[CRK_MAXPARAM];
};
/* Bignum parameter, in packed bytes. */
struct crparam {
void * crp_p;
u_int crp_nbits;
};
.Ed
Performs an asymmetric-key operation from the list above.
The specific operation is supplied in
.Fa kop-\*[Gt]crk_op ;
final status for the operation is returned in
.Fa kop-\*[Gt]crk_status .
The number of input arguments and the number of output arguments
is specified in
.Fa kop-\*[Gt]crk_iparams
and
.Fa kop-\*[Gt]crk_iparams ,
respectively.
The field
.Fa crk_param[]
must be filled in with exactly
.Fa kop-\*[Gt]crk_iparams + kop-\*[Gt]crk_oparams
arguments, each encoded as a
.Fa struct crparam
(address, bitlength) pair.
.Pp
The semantics of these arguments are currently undocumented.
.El
.Sh SEE ALSO
.Xr aesni 4 ,
.Xr hifn 4 ,
@ -444,5 +361,3 @@ must follow whether privacy or integrity algorithms were specified for
session: if you request a
.No non- Ns Dv NULL
algorithm, you must supply a suitably-sized buffer.
.Pp
The scheme for passing arguments for asymmetric requests is baroque.

View file

@ -72,7 +72,6 @@ MAN= accept_filter.9 \
cr_seeothergids.9 \
cr_seeotheruids.9 \
crypto.9 \
crypto_asym.9 \
crypto_buffer.9 \
crypto_driver.9 \
crypto_request.9 \
@ -913,10 +912,6 @@ MLINKS+=cpuset.9 CPUSET_T_INITIALIZER.9 \
cpuset.9 CPU_COPY_STORE_REL.9
MLINKS+=critical_enter.9 critical.9 \
critical_enter.9 critical_exit.9
MLINKS+=crypto_asym.9 crypto_kdispatch.9 \
crypto_asym.9 crypto_kdone.9 \
crypto_asym.9 crypto_kregister.9 \
crypto_asym.9 CRYPTODEV_KPROCESS.9
MLINKS+=crypto_buffer.9 crypto_apply.9 \
crypto_buffer.9 crypto_apply_buf.9 \
crypto_buffer.9 crypto_buffer_contiguous_segment.9 \

View file

@ -17,7 +17,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd March 18, 2021
.Dd April 12, 2021
.Dt CRYPTO 9
.Os
.Sh NAME
@ -35,15 +35,10 @@ through the
device.
.Pp
.Nm
supports two modes of operation:
one mode for symmetric-keyed cryptographic requests and digest,
and a second mode for asymmetric-key requests and modular arithmetic.
.Ss Symmetric-Key Mode
Symmetric-key operations include encryption and decryption operations
supports encryption and decryption operations
using block and stream ciphers as well as computation and verification
of message authentication codes (MACs).
In this mode,
consumers allocate sessions to describe a transform as discussed in
Consumers allocate sessions to describe a transform as discussed in
.Xr crypto_session 9 .
Consumers then allocate request objects to describe each transformation
such as encrypting a network packet or decrypting a disk sector.
@ -56,18 +51,6 @@ consumers.
describes the interfaces drivers use to register with the framework,
helper routines the framework provides to faciliate request processing,
and the interfaces drivers are required to provide.
.Ss Asymmetric-Key Mode
Assymteric-key operations do not use sessions.
Instead,
these operations perform individual mathematical operations using a set
of input and output parameters.
These operations are described in
.Xr crypto_asym 9 .
Drivers that support asymmetric operations use additional interfaces
described in
.Xr crypto_asym 9
in addition to the base interfaces described in
.Xr crypto_driver 9 .
.Ss Callbacks
Since the consumers may not be associated with a process, drivers may
not
@ -83,10 +66,9 @@ Errors are reported to the callback function.
Session initialization does not use callbacks and returns errors
synchronously.
.Ss Session Migration
For symmetric-key operations,
a specific error code,
Operations may fail with a specific error code,
.Er EAGAIN ,
is used to indicate that a session handle has changed and that the
to indicate that a session handle has changed and that the
request may be re-submitted immediately with the new session.
The consumer should update its saved copy of the session handle
to the value of
@ -95,9 +77,6 @@ so that future requests use the new session.
.Ss Supported Algorithms
More details on some algorithms may be found in
.Xr crypto 7 .
These algorithms are used for symmetric-mode operations.
Asymmetric-mode operations support operations described in
.Xr crypto_asym 9 .
.Pp
The following authentication algorithms are supported:
.Pp
@ -156,7 +135,6 @@ most of the framework code
.Xr crypto 4 ,
.Xr ipsec 4 ,
.Xr crypto 7 ,
.Xr crypto_asym 9 ,
.Xr crypto_driver 9 ,
.Xr crypto_request 9 ,
.Xr crypto_session 9 ,

View file

@ -1,178 +0,0 @@
.\" Copyright (c) 2020, Chelsio Inc
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions are met:
.\"
.\" 1. Redistributions of source code must retain the above copyright notice,
.\" this list of conditions and the following disclaimer.
.\"
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" 3. Neither the name of the Chelsio Inc nor the names of its
.\" contributors may be used to endorse or promote products derived from
.\" this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
.\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" * Other names and brands may be claimed as the property of others.
.\"
.\" $FreeBSD$
.\"
.Dd March 27, 2020
.Dt CRYPTO_ASYM 9
.Os
.Sh NAME
.Nm crypto_asym
.Nd asymmetric cryptographic operations
.Sh SYNOPSIS
.In opencrypto/cryptodev.h
.Ft int
.Fn crypto_kdispatch "struct cryptkop *krp"
.Ft void
.Fn crypto_kdone "struct cryptkop *krp"
.Ft int
.Fn crypto_kregister "uint32_t driverid" "int kalg" "uint32_t flags"
.Ft int
.Fn CRYPTODEV_KPROCESS "device_t dev" "struct cryptop *krp" "int flags"
.Sh DESCRIPTION
The in-kernel cryptographic kernel framework supports asymmetric
requests (keying requests) in addition to symmetric operations.
There are currently no in-kernel users of these requests,
but applications can make requests of hardware drivers via the
.Pa /dev/crypto
device .
.Pp
Some APIs are shared with the framework's symmetric request support.
This manual describes the APIs and data structures unique to
asymmetric requests.
.Pp
.Ss Request Objects
A request is described by a
.Vt struct cryptkop
containing the following fields:
.Bl -tag -width "krp_callback"
.It Fa krp_op
Operation to perform.
Available operations include
.Dv CRK_MOD_EXP ,
.Dv CRK_MOD_EXP_CRT ,
.Dv CRK_DSA_SIGN ,
.Dv CRK_DSA_VERIFY ,
and
.Dv CRK_DH_COMPUTE_KEY .
.It Fa krp_status
Error status.
Either zero on success,
or an error if an operation fails.
Set by drivers prior to completing a request via
.Fn crypto_kdone .
.It Fa krp_iparams
Count of input parameters.
.It Fa krp_oparams
Count of output parameters.
.It Fa krp_crid
Requested device.
.It Fa krp_hid
Device used to complete the request.
.It Fa krp_param
Array of parameters.
The array contains the input parameters first followed by the output
parameters.
Each parameter is stored as a bignum.
Each bignum is described by a
.Vt struct crparam
containing the following fields:
.Bl -tag -width "crp_nbits"
.It Fa crp_p
Pointer to array of packed bytes.
.It Fa crp_nbits
Size of bignum in bits.
.El
.It Fa krp_callback
Callback function.
This must point to a callback function of type
.Vt void (*)(struct cryptkop *) .
The callback function should inspect
.Fa krp_status
to determine the status of the completed operation.
.El
.Pp
New requests should be initialized to zero before setting fields to
appropriate values.
Once the request has been populated,
it should be passed to
.Fn crypto_kdispatch .
.Pp
.Fn crypto_kdispatch
will choose a device driver to perform the operation described by
.Fa krp
and invoke that driver's
.Fn CRYPTO_KPROCESS
method.
.Ss Driver API
Drivers register support for asymmetric operations by calling
.Fn crypto_kregister
for each supported algorithm.
.Fa driverid
should be the value returned by an earlier call to
.Fn crypto_get_driverid .
.Fa kalg
should list one of the operations that can be set in
.Fa krp_op .
.Fa flags
is a bitmask of zero or more of the following values:
.Bl -tag -width "CRYPTO_ALG_FLAG_RNG_ENABLE"
.It Dv CRYPTO_ALG_FLAG_RNG_ENABLE
Device has a hardware RNG for DH/DSA.
.It Dv CRYPTO_ALG_FLAG_DSA_SHA
Device can compute a SHA digest of a message.
.El
.Pp
Drivers unregister with the framework via
.Fn crypto_unregister_all .
.Pp
Similar to
.Fn CRYPTO_PROCESS ,
.Fn CRYPTO_KPROCESS
should complete the request or schedule it for asynchronous
completion.
If this method is not able to complete a request due to insufficient
resources,
it can defer the request (and future asymmetric requests) by returning
.Dv ERESTART .
Once resources are available,
the driver should invoke
.Fn crypto_unblock
with
.Dv CRYPTO_ASYMQ
to resume processing of asymmetric requests.
.Pp
Once a request is completed,
the driver should set
.Fa krp_status
and then call
.Fn crypto_kdone .
.Sh RETURN VALUES
.Fn crypto_kdispatch ,
.Fn crypto_kregister ,
and
.Fn CRYPTODEV_KPROCESS
return zero on success or an error on failure.
.Sh SEE ALSO
.Xr crypto 7 ,
.Xr crypto 9 ,
.Xr crypto_driver 9 ,
.Xr crypto_request 9 ,
.Xr crypto_session 9

View file

@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd June 9, 2020
.Dd April 12, 2021
.Dt CRYPTO_DRIVER 9
.Os
.Sh NAME
@ -285,13 +285,10 @@ is the value returned by
.Fn crypto_get_driverid .
.Fa what
indicates which types of requests the driver is able to handle again:
.Bl -tag -width "CRYPTO_ASYMQ"
.Bl -tag -width "CRYPTO_SYMQ"
.It Dv CRYPTO_SYMQ
indicates that the driver is able to handle symmetric requests passed to
.Fn CRYPTODEV_PROCESS .
.It Dv CRYPTO_ASYMQ
indicates that the driver is able to handle asymmetric requests passed to
.Fn CRYPTODEV_KPROCESS .
.El
.Pp
.Pp

View file

@ -2252,7 +2252,7 @@ hifn_intr(void *arg)
HIFN_UNLOCK(sc);
if (sc->sc_needwakeup) { /* XXX check high watermark */
int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
int wakeup = sc->sc_needwakeup & CRYPTO_SYMQ;
#ifdef HIFN_DEBUG
if (hifn_debug)
device_printf(sc->sc_dev,

View file

@ -385,8 +385,6 @@ safe_attach(device_t dev)
#if 0
printf(" key");
sc->sc_flags |= SAFE_FLAGS_KEY;
crypto_kregister(sc->sc_cid, CRK_MOD_EXP, 0);
crypto_kregister(sc->sc_cid, CRK_MOD_EXP_CRT, 0);
#endif
}
if (sc->sc_devinfo & SAFE_DEVINFO_DES) {
@ -584,7 +582,7 @@ safe_intr(void *arg)
}
if (sc->sc_needwakeup) { /* XXX check high watermark */
int wakeup = sc->sc_needwakeup & (CRYPTO_SYMQ|CRYPTO_ASYMQ);
int wakeup = sc->sc_needwakeup & CRYPTO_SYMQ;
DPRINTF(("%s: wakeup crypto %x\n", __func__,
sc->sc_needwakeup));
sc->sc_needwakeup &= ~wakeup;

View file

@ -281,7 +281,7 @@ nlm_xlpsec_msgring_handler(int vc, int size, int code, int src_id,
atomic_add_int(&creditleft, sc->sec_msgsz);
if (creditleft >= (NLM_CRYPTO_LEFT_REQS)) {
crypto_unblock(sc->sc_cid, sc->sc_needwakeup);
sc->sc_needwakeup &= (~(CRYPTO_SYMQ | CRYPTO_ASYMQ));
sc->sc_needwakeup &= ~CRYPTO_SYMQ;
}
}
if (cmd->hash_dst_len != 0) {

View file

@ -98,8 +98,7 @@ SDT_PROVIDER_DEFINE(opencrypto);
/*
* Crypto drivers register themselves by allocating a slot in the
* crypto_drivers table with crypto_get_driverid() and then registering
* each asym algorithm they support with crypto_kregister().
* crypto_drivers table with crypto_get_driverid().
*/
static struct mtx crypto_drivers_mtx; /* lock on driver table */
#define CRYPTO_DRIVER_LOCK() mtx_lock(&crypto_drivers_mtx)
@ -118,13 +117,10 @@ struct cryptocap {
device_t cc_dev;
uint32_t cc_hid;
uint32_t cc_sessions; /* (d) # of sessions */
uint32_t cc_koperations; /* (d) # os asym operations */
uint8_t cc_kalg[CRK_ALGORITHM_MAX + 1];
int cc_flags; /* (d) flags */
#define CRYPTOCAP_F_CLEANUP 0x80000000 /* needs resource cleanup */
int cc_qblocked; /* (q) symmetric q blocked */
int cc_kqblocked; /* (q) asymmetric q blocked */
size_t cc_session_size;
volatile int cc_refs;
};
@ -139,16 +135,8 @@ struct crypto_session {
/* Driver softc follows. */
};
/*
* There are two queues for crypto requests; one for symmetric (e.g.
* cipher) operations and one for asymmetric (e.g. MOD)operations.
* A single mutex is used to lock access to both queues. We could
* have one per-queue but having one simplifies handling of block/unblock
* operations.
*/
static int crp_sleep = 0;
static TAILQ_HEAD(cryptop_q ,cryptop) crp_q; /* request queues */
static TAILQ_HEAD(,cryptkop) crp_kq;
static struct mtx crypto_q_mtx;
#define CRYPTO_Q_LOCK() mtx_lock(&crypto_q_mtx)
#define CRYPTO_Q_UNLOCK() mtx_unlock(&crypto_q_mtx)
@ -172,7 +160,6 @@ struct crypto_ret_worker {
TAILQ_HEAD(,cryptop) crp_ordered_ret_q; /* ordered callback queue for symetric jobs */
TAILQ_HEAD(,cryptop) crp_ret_q; /* callback queue for symetric jobs */
TAILQ_HEAD(,cryptkop) crp_ret_kq; /* callback queue for asym jobs */
uint32_t reorder_ops; /* total ordered sym jobs received */
uint32_t reorder_cur_seq; /* current sym job dispatched */
@ -201,16 +188,6 @@ SYSCTL_INT(_kern, OID_AUTO, crypto_workers_num, CTLFLAG_RDTUN,
static uma_zone_t cryptop_zone;
int crypto_userasymcrypto = 1;
SYSCTL_INT(_kern_crypto, OID_AUTO, asym_enable, CTLFLAG_RW,
&crypto_userasymcrypto, 0,
"Enable user-mode access to asymmetric crypto support");
#ifdef COMPAT_FREEBSD12
SYSCTL_INT(_kern, OID_AUTO, userasymcrypto, CTLFLAG_RW,
&crypto_userasymcrypto, 0,
"Enable/disable user-mode access to asymmetric crypto support");
#endif
int crypto_devallowsoft = 0;
SYSCTL_INT(_kern_crypto, OID_AUTO, allow_soft, CTLFLAG_RW,
&crypto_devallowsoft, 0,
@ -228,7 +205,6 @@ static struct proc *cryptoproc;
static void crypto_ret_proc(struct crypto_ret_worker *ret_worker);
static void crypto_destroy(void);
static int crypto_invoke(struct cryptocap *cap, struct cryptop *crp, int hint);
static int crypto_kinvoke(struct cryptkop *krp);
static void crypto_task_invoke(void *ctx, int pending);
static void crypto_batch_enqueue(struct cryptop *crp);
@ -308,8 +284,6 @@ cap_rele(struct cryptocap *cap)
KASSERT(cap->cc_sessions == 0,
("freeing crypto driver with active sessions"));
KASSERT(cap->cc_koperations == 0,
("freeing crypto driver with active key operations"));
free(cap, M_CRYPTO_DATA);
}
@ -324,7 +298,6 @@ crypto_init(void)
MTX_DEF|MTX_QUIET);
TAILQ_INIT(&crp_q);
TAILQ_INIT(&crp_kq);
mtx_init(&crypto_q_mtx, "crypto", "crypto op queues", MTX_DEF);
cryptop_zone = uma_zcreate("cryptop",
@ -358,7 +331,6 @@ crypto_init(void)
FOREACH_CRYPTO_RETW(ret_worker) {
TAILQ_INIT(&ret_worker->crp_ordered_ret_q);
TAILQ_INIT(&ret_worker->crp_ret_q);
TAILQ_INIT(&ret_worker->crp_ret_kq);
ret_worker->reorder_ops = 0;
ret_worker->reorder_cur_seq = 0;
@ -1114,43 +1086,6 @@ crypto_getcaps(int hid)
return (flags);
}
/*
* Register support for a key-related algorithm. This routine
* is called once for each algorithm supported a driver.
*/
int
crypto_kregister(uint32_t driverid, int kalg, uint32_t flags)
{
struct cryptocap *cap;
int err;
CRYPTO_DRIVER_LOCK();
cap = crypto_checkdriver(driverid);
if (cap != NULL &&
(CRK_ALGORITM_MIN <= kalg && kalg <= CRK_ALGORITHM_MAX)) {
/*
* XXX Do some performance testing to determine placing.
* XXX We probably need an auxiliary data structure that
* XXX describes relative performances.
*/
cap->cc_kalg[kalg] = flags | CRYPTO_ALG_FLAG_SUPPORTED;
if (bootverbose)
printf("crypto: %s registers key alg %u flags %u\n"
, device_get_nameunit(cap->cc_dev)
, kalg
, flags
);
gone_in_dev(cap->cc_dev, 14, "asymmetric crypto");
err = 0;
} else
err = EINVAL;
CRYPTO_DRIVER_UNLOCK();
return err;
}
/*
* Unregister all algorithms associated with a crypto driver.
* If there are pending sessions using it, leave enough information
@ -1177,7 +1112,7 @@ crypto_unregister_all(uint32_t driverid)
* XXX: This doesn't do anything to kick sessions that
* have no pending operations.
*/
while (cap->cc_sessions != 0 || cap->cc_koperations != 0)
while (cap->cc_sessions != 0)
mtx_sleep(cap, &crypto_drivers_mtx, 0, "cryunreg", 0);
CRYPTO_DRIVER_UNLOCK();
cap_rele(cap);
@ -1200,8 +1135,6 @@ crypto_unblock(uint32_t driverid, int what)
if (cap != NULL) {
if (what & CRYPTO_SYMQ)
cap->cc_qblocked = 0;
if (what & CRYPTO_ASYMQ)
cap->cc_kqblocked = 0;
if (crp_sleep)
wakeup_one(&crp_q);
err = 0;
@ -1499,189 +1432,6 @@ crypto_batch_enqueue(struct cryptop *crp)
CRYPTO_Q_UNLOCK();
}
/*
* Add an asymetric crypto request to a queue,
* to be processed by the kernel thread.
*/
int
crypto_kdispatch(struct cryptkop *krp)
{
int error;
CRYPTOSTAT_INC(cs_kops);
krp->krp_cap = NULL;
error = crypto_kinvoke(krp);
if (error == ERESTART) {
CRYPTO_Q_LOCK();
TAILQ_INSERT_TAIL(&crp_kq, krp, krp_next);
if (crp_sleep)
wakeup_one(&crp_q);
CRYPTO_Q_UNLOCK();
error = 0;
}
return error;
}
/*
* Verify a driver is suitable for the specified operation.
*/
static __inline int
kdriver_suitable(const struct cryptocap *cap, const struct cryptkop *krp)
{
return (cap->cc_kalg[krp->krp_op] & CRYPTO_ALG_FLAG_SUPPORTED) != 0;
}
/*
* Select a driver for an asym operation. The driver must
* support the necessary algorithm. The caller can constrain
* which device is selected with the flags parameter. The
* algorithm we use here is pretty stupid; just use the first
* driver that supports the algorithms we need. If there are
* multiple suitable drivers we choose the driver with the
* fewest active operations. We prefer hardware-backed
* drivers to software ones when either may be used.
*/
static struct cryptocap *
crypto_select_kdriver(const struct cryptkop *krp, int flags)
{
struct cryptocap *cap, *best;
int match, hid;
CRYPTO_DRIVER_ASSERT();
/*
* Look first for hardware crypto devices if permitted.
*/
if (flags & CRYPTOCAP_F_HARDWARE)
match = CRYPTOCAP_F_HARDWARE;
else
match = CRYPTOCAP_F_SOFTWARE;
best = NULL;
again:
for (hid = 0; hid < crypto_drivers_size; hid++) {
/*
* If there is no driver for this slot, or the driver
* is not appropriate (hardware or software based on
* match), then skip.
*/
cap = crypto_drivers[hid];
if (cap == NULL ||
(cap->cc_flags & match) == 0)
continue;
/* verify all the algorithms are supported. */
if (kdriver_suitable(cap, krp)) {
if (best == NULL ||
cap->cc_koperations < best->cc_koperations)
best = cap;
}
}
if (best != NULL)
return best;
if (match == CRYPTOCAP_F_HARDWARE && (flags & CRYPTOCAP_F_SOFTWARE)) {
/* sort of an Algol 68-style for loop */
match = CRYPTOCAP_F_SOFTWARE;
goto again;
}
return best;
}
/*
* Choose a driver for an asymmetric crypto request.
*/
static struct cryptocap *
crypto_lookup_kdriver(struct cryptkop *krp)
{
struct cryptocap *cap;
uint32_t crid;
/* If this request is requeued, it might already have a driver. */
cap = krp->krp_cap;
if (cap != NULL)
return (cap);
/* Use krp_crid to choose a driver. */
crid = krp->krp_crid;
if ((crid & (CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE)) == 0) {
cap = crypto_checkdriver(crid);
if (cap != NULL) {
/*
* Driver present, it must support the
* necessary algorithm and, if s/w drivers are
* excluded, it must be registered as
* hardware-backed.
*/
if (!kdriver_suitable(cap, krp) ||
(!crypto_devallowsoft &&
(cap->cc_flags & CRYPTOCAP_F_HARDWARE) == 0))
cap = NULL;
}
} else {
/*
* No requested driver; select based on crid flags.
*/
if (!crypto_devallowsoft) /* NB: disallow s/w drivers */
crid &= ~CRYPTOCAP_F_SOFTWARE;
cap = crypto_select_kdriver(krp, crid);
}
if (cap != NULL) {
krp->krp_cap = cap_ref(cap);
krp->krp_hid = cap->cc_hid;
}
return (cap);
}
/*
* Dispatch an asymmetric crypto request.
*/
static int
crypto_kinvoke(struct cryptkop *krp)
{
struct cryptocap *cap = NULL;
int error;
KASSERT(krp != NULL, ("%s: krp == NULL", __func__));
KASSERT(krp->krp_callback != NULL,
("%s: krp->crp_callback == NULL", __func__));
CRYPTO_DRIVER_LOCK();
cap = crypto_lookup_kdriver(krp);
if (cap == NULL) {
CRYPTO_DRIVER_UNLOCK();
krp->krp_status = ENODEV;
crypto_kdone(krp);
return (0);
}
/*
* If the device is blocked, return ERESTART to requeue it.
*/
if (cap->cc_kqblocked) {
/*
* XXX: Previously this set krp_status to ERESTART and
* invoked crypto_kdone but the caller would still
* requeue it.
*/
CRYPTO_DRIVER_UNLOCK();
return (ERESTART);
}
cap->cc_koperations++;
CRYPTO_DRIVER_UNLOCK();
error = CRYPTODEV_KPROCESS(cap->cc_dev, krp, 0);
if (error == ERESTART) {
CRYPTO_DRIVER_LOCK();
cap->cc_koperations--;
CRYPTO_DRIVER_UNLOCK();
return (error);
}
KASSERT(error == 0, ("error %d returned from crypto_kprocess", error));
return (0);
}
static void
crypto_task_invoke(void *ctx, int pending)
{
@ -1894,62 +1644,6 @@ crypto_done(struct cryptop *crp)
}
}
/*
* Invoke the callback on behalf of the driver.
*/
void
crypto_kdone(struct cryptkop *krp)
{
struct crypto_ret_worker *ret_worker;
struct cryptocap *cap;
if (krp->krp_status != 0)
CRYPTOSTAT_INC(cs_kerrs);
cap = krp->krp_cap;
if (cap != NULL) {
CRYPTO_DRIVER_LOCK();
KASSERT(cap->cc_koperations > 0, ("cc_koperations == 0"));
cap->cc_koperations--;
if (cap->cc_koperations == 0 &&
cap->cc_flags & CRYPTOCAP_F_CLEANUP)
wakeup(cap);
CRYPTO_DRIVER_UNLOCK();
krp->krp_cap = NULL;
cap_rele(cap);
}
ret_worker = CRYPTO_RETW(0);
CRYPTO_RETW_LOCK(ret_worker);
if (TAILQ_EMPTY(&ret_worker->crp_ret_kq))
wakeup_one(&ret_worker->crp_ret_q); /* shared wait channel */
TAILQ_INSERT_TAIL(&ret_worker->crp_ret_kq, krp, krp_next);
CRYPTO_RETW_UNLOCK(ret_worker);
}
int
crypto_getfeat(int *featp)
{
int hid, kalg, feat = 0;
CRYPTO_DRIVER_LOCK();
for (hid = 0; hid < crypto_drivers_size; hid++) {
const struct cryptocap *cap = crypto_drivers[hid];
if (cap == NULL ||
((cap->cc_flags & CRYPTOCAP_F_SOFTWARE) &&
!crypto_devallowsoft)) {
continue;
}
for (kalg = 0; kalg < CRK_ALGORITHM_MAX; kalg++)
if (cap->cc_kalg[kalg] & CRYPTO_ALG_FLAG_SUPPORTED)
feat |= 1 << kalg;
}
CRYPTO_DRIVER_UNLOCK();
*featp = feat;
return (0);
}
/*
* Terminate a thread at module unload. The process that
* initiated this is waiting for us to signal that we're gone;
@ -1975,7 +1669,6 @@ static void
crypto_proc(void)
{
struct cryptop *crp, *submit;
struct cryptkop *krp;
struct cryptocap *cap;
int result, hint;
@ -2046,46 +1739,7 @@ crypto_proc(void)
TAILQ_INSERT_HEAD(&crp_q, submit, crp_next);
CRYPTOSTAT_INC(cs_blocks);
}
}
/* As above, but for key ops */
TAILQ_FOREACH(krp, &crp_kq, krp_next) {
cap = krp->krp_cap;
if (cap->cc_flags & CRYPTOCAP_F_CLEANUP) {
/*
* Operation needs to be migrated,
* clear krp_cap so a new driver is
* selected.
*/
krp->krp_cap = NULL;
cap_rele(cap);
break;
}
if (!cap->cc_kqblocked)
break;
}
if (krp != NULL) {
TAILQ_REMOVE(&crp_kq, krp, krp_next);
CRYPTO_Q_UNLOCK();
result = crypto_kinvoke(krp);
CRYPTO_Q_LOCK();
if (result == ERESTART) {
/*
* The driver ran out of resources, mark the
* driver ``blocked'' for cryptkop's and put
* the request back in the queue. It would
* best to put the request back where we got
* it but that's hard so for now we put it
* at the front. This should be ok; putting
* it at the end does not work.
*/
krp->krp_cap->cc_kqblocked = 1;
TAILQ_INSERT_HEAD(&crp_kq, krp, krp_next);
CRYPTOSTAT_INC(cs_kblocks);
}
}
if (submit == NULL && krp == NULL) {
} else {
/*
* Nothing more to be processed. Sleep until we're
* woken because there are more ops to process.
@ -2120,7 +1774,6 @@ static void
crypto_ret_proc(struct crypto_ret_worker *ret_worker)
{
struct cryptop *crpt;
struct cryptkop *krpt;
CRYPTO_RETW_LOCK(ret_worker);
for (;;) {
@ -2141,19 +1794,13 @@ crypto_ret_proc(struct crypto_ret_worker *ret_worker)
TAILQ_REMOVE(&ret_worker->crp_ret_q, crpt, crp_next);
}
krpt = TAILQ_FIRST(&ret_worker->crp_ret_kq);
if (krpt != NULL)
TAILQ_REMOVE(&ret_worker->crp_ret_kq, krpt, krp_next);
if (crpt != NULL || krpt != NULL) {
if (crpt != NULL) {
CRYPTO_RETW_UNLOCK(ret_worker);
/*
* Run callbacks unlocked.
*/
if (crpt != NULL)
crpt->crp_callback(crpt);
if (krpt != NULL)
krpt->krp_callback(krpt);
CRYPTO_RETW_LOCK(ret_worker);
} else {
/*
@ -2178,25 +1825,21 @@ db_show_drivers(void)
{
int hid;
db_printf("%12s %4s %4s %8s %2s %2s\n"
db_printf("%12s %4s %8s %2s\n"
, "Device"
, "Ses"
, "Kops"
, "Flags"
, "QB"
, "KB"
);
for (hid = 0; hid < crypto_drivers_size; hid++) {
const struct cryptocap *cap = crypto_drivers[hid];
if (cap == NULL)
continue;
db_printf("%-12s %4u %4u %08x %2u %2u\n"
db_printf("%-12s %4u %08x %2u\n"
, device_get_nameunit(cap->cc_dev)
, cap->cc_sessions
, cap->cc_koperations
, cap->cc_flags
, cap->cc_qblocked
, cap->cc_kqblocked
);
}
}
@ -2239,41 +1882,6 @@ DB_SHOW_COMMAND(crypto, db_show_crypto)
}
}
}
DB_SHOW_COMMAND(kcrypto, db_show_kcrypto)
{
struct cryptkop *krp;
struct crypto_ret_worker *ret_worker;
db_show_drivers();
db_printf("\n");
db_printf("%4s %5s %4s %4s %8s %4s %8s\n",
"Op", "Status", "#IP", "#OP", "CRID", "HID", "Callback");
TAILQ_FOREACH(krp, &crp_kq, krp_next) {
db_printf("%4u %5u %4u %4u %08x %4u %8p\n"
, krp->krp_op
, krp->krp_status
, krp->krp_iparams, krp->krp_oparams
, krp->krp_crid, krp->krp_hid
, krp->krp_callback
);
}
ret_worker = CRYPTO_RETW(0);
if (!TAILQ_EMPTY(&ret_worker->crp_ret_q)) {
db_printf("%4s %5s %8s %4s %8s\n",
"Op", "Status", "CRID", "HID", "Callback");
TAILQ_FOREACH(krp, &ret_worker->crp_ret_kq, krp_next) {
db_printf("%4u %5u %08x %4u %8p\n"
, krp->krp_op
, krp->krp_status
, krp->krp_crid, krp->krp_hid
, krp->krp_callback
);
}
}
}
#endif
int crypto_modevent(module_t mod, int type, void *unused);

View file

@ -127,25 +127,9 @@ struct crypt_aead32 {
uint32_t iv;
};
struct crparam32 {
uint32_t crp_p;
u_int crp_nbits;
};
struct crypt_kop32 {
u_int crk_op;
u_int crk_status;
u_short crk_iparams;
u_short crk_oparams;
u_int crk_crid;
struct crparam32 crk_param[CRK_MAXPARAM];
};
#define CIOCGSESSION32 _IOWR('c', 101, struct session_op32)
#define CIOCCRYPT32 _IOWR('c', 103, struct crypt_op32)
#define CIOCKEY32 _IOWR('c', 104, struct crypt_kop32)
#define CIOCGSESSION232 _IOWR('c', 106, struct session2_op32)
#define CIOCKEY232 _IOWR('c', 107, struct crypt_kop32)
#define CIOCCRYPTAEAD32 _IOWR('c', 109, struct crypt_aead32)
static void
@ -253,50 +237,6 @@ crypt_aead_to_32(const struct crypt_aead *from, struct crypt_aead32 *to)
PTROUT_CP(*from, *to, tag);
PTROUT_CP(*from, *to, iv);
}
static void
crparam_from_32(const struct crparam32 *from, struct crparam *to)
{
PTRIN_CP(*from, *to, crp_p);
CP(*from, *to, crp_nbits);
}
static void
crparam_to_32(const struct crparam *from, struct crparam32 *to)
{
PTROUT_CP(*from, *to, crp_p);
CP(*from, *to, crp_nbits);
}
static void
crypt_kop_from_32(const struct crypt_kop32 *from, struct crypt_kop *to)
{
int i;
CP(*from, *to, crk_op);
CP(*from, *to, crk_status);
CP(*from, *to, crk_iparams);
CP(*from, *to, crk_oparams);
CP(*from, *to, crk_crid);
for (i = 0; i < CRK_MAXPARAM; i++)
crparam_from_32(&from->crk_param[i], &to->crk_param[i]);
}
static void
crypt_kop_to_32(const struct crypt_kop *from, struct crypt_kop32 *to)
{
int i;
CP(*from, *to, crk_op);
CP(*from, *to, crk_status);
CP(*from, *to, crk_iparams);
CP(*from, *to, crk_oparams);
CP(*from, *to, crk_crid);
for (i = 0; i < CRK_MAXPARAM; i++)
crparam_to_32(&from->crk_param[i], &to->crk_param[i]);
}
#endif
static void
@ -356,11 +296,6 @@ SYSCTL_BOOL(_kern_crypto, OID_AUTO, cryptodev_separate_aad, CTLFLAG_RW,
&use_separate_aad, 0,
"Use separate AAD buffer for /dev/crypto requests.");
static struct timeval warninterval = { .tv_sec = 60, .tv_usec = 0 };
SYSCTL_TIMEVAL_SEC(_kern, OID_AUTO, cryptodev_warn_interval, CTLFLAG_RW,
&warninterval,
"Delay in seconds between warnings of deprecated /dev/crypto algorithms");
/*
* Check a crypto identifier to see if it requested
* a software device/driver. This can be done either
@ -1208,131 +1143,6 @@ cryptodev_aead(struct csession *cse, struct crypt_aead *caead)
return (error);
}
static void
cryptodevkey_cb(struct cryptkop *krp)
{
wakeup_one(krp);
}
static int
cryptodev_key(struct crypt_kop *kop)
{
struct cryptkop *krp = NULL;
int error = EINVAL;
int in, out, size, i;
if (kop->crk_iparams + kop->crk_oparams > CRK_MAXPARAM) {
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EFBIG);
}
in = kop->crk_iparams;
out = kop->crk_oparams;
switch (kop->crk_op) {
case CRK_MOD_EXP:
if (in == 3 && out == 1)
break;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EINVAL);
case CRK_MOD_EXP_CRT:
if (in == 6 && out == 1)
break;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EINVAL);
case CRK_DSA_SIGN:
if (in == 5 && out == 2)
break;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EINVAL);
case CRK_DSA_VERIFY:
if (in == 7 && out == 0)
break;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EINVAL);
case CRK_DH_COMPUTE_KEY:
if (in == 3 && out == 1)
break;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EINVAL);
default:
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EINVAL);
}
krp = malloc(sizeof(*krp), M_XDATA, M_WAITOK | M_ZERO);
krp->krp_op = kop->crk_op;
krp->krp_status = kop->crk_status;
krp->krp_iparams = kop->crk_iparams;
krp->krp_oparams = kop->crk_oparams;
krp->krp_crid = kop->crk_crid;
krp->krp_status = 0;
krp->krp_callback = cryptodevkey_cb;
for (i = 0; i < CRK_MAXPARAM; i++) {
if (kop->crk_param[i].crp_nbits > 65536) {
/* Limit is the same as in OpenBSD */
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto fail;
}
krp->krp_param[i].crp_nbits = kop->crk_param[i].crp_nbits;
}
for (i = 0; i < krp->krp_iparams + krp->krp_oparams; i++) {
size = (krp->krp_param[i].crp_nbits + 7) / 8;
if (size == 0)
continue;
krp->krp_param[i].crp_p = malloc(size, M_XDATA, M_WAITOK);
if (i >= krp->krp_iparams)
continue;
error = copyin(kop->crk_param[i].crp_p, krp->krp_param[i].crp_p, size);
if (error) {
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto fail;
}
}
error = crypto_kdispatch(krp);
if (error) {
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto fail;
}
error = tsleep(krp, PSOCK, "crydev", 0);
if (error) {
/* XXX can this happen? if so, how do we recover? */
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto fail;
}
kop->crk_crid = krp->krp_hid; /* device that did the work */
if (krp->krp_status != 0) {
error = krp->krp_status;
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto fail;
}
for (i = krp->krp_iparams; i < krp->krp_iparams + krp->krp_oparams; i++) {
size = (krp->krp_param[i].crp_nbits + 7) / 8;
if (size == 0)
continue;
error = copyout(krp->krp_param[i].crp_p, kop->crk_param[i].crp_p, size);
if (error) {
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
goto fail;
}
}
fail:
if (krp) {
kop->crk_status = krp->krp_status;
for (i = 0; i < CRK_MAXPARAM; i++) {
if (krp->krp_param[i].crp_p)
free(krp->krp_param[i].crp_p, M_XDATA);
}
free(krp, M_XDATA);
}
return (error);
}
static int
cryptodev_find(struct crypt_find_op *find)
{
@ -1390,13 +1200,11 @@ static int
crypto_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
struct thread *td)
{
static struct timeval keywarn, featwarn;
struct fcrypt *fcr;
struct csession *cse;
struct session2_op *sop;
struct crypt_op *cop;
struct crypt_aead *caead;
struct crypt_kop *kop;
uint32_t ses;
int error = 0;
union {
@ -1404,7 +1212,6 @@ crypto_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
#ifdef COMPAT_FREEBSD32
struct crypt_op copc;
struct crypt_aead aeadc;
struct crypt_kop kopc;
#endif
} thunk;
#ifdef COMPAT_FREEBSD32
@ -1443,17 +1250,6 @@ crypto_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
data = (void *)&thunk.aeadc;
crypt_aead_from_32((struct crypt_aead32 *)data32, &thunk.aeadc);
break;
case CIOCKEY32:
case CIOCKEY232:
cmd32 = cmd;
data32 = data;
if (cmd == CIOCKEY32)
cmd = CIOCKEY;
else
cmd = CIOCKEY2;
data = (void *)&thunk.kopc;
crypt_kop_from_32((struct crypt_kop32 *)data32, &thunk.kopc);
break;
}
#endif
@ -1504,46 +1300,6 @@ crypto_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
error = cryptodev_op(cse, cop);
cse_free(cse);
break;
case CIOCKEY:
case CIOCKEY2:
if (ratecheck(&keywarn, &warninterval))
gone_in(14,
"Asymmetric crypto operations via /dev/crypto");
if (!crypto_userasymcrypto) {
SDT_PROBE1(opencrypto, dev, ioctl, error, __LINE__);
return (EPERM); /* XXX compat? */
}
kop = (struct crypt_kop *)data;
if (cmd == CIOCKEY) {
/* NB: crypto core enforces s/w driver use */
kop->crk_crid =
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE;
}
mtx_lock(&Giant);
error = cryptodev_key(kop);
mtx_unlock(&Giant);
break;
case CIOCASYMFEAT:
if (ratecheck(&featwarn, &warninterval))
gone_in(14,
"Asymmetric crypto features via /dev/crypto");
if (!crypto_userasymcrypto) {
/*
* NB: if user asym crypto operations are
* not permitted return "no algorithms"
* so well-behaved applications will just
* fallback to doing them in software.
*/
*(int *)data = 0;
} else {
error = crypto_getfeat((int *)data);
if (error)
SDT_PROBE1(opencrypto, dev, ioctl, error,
__LINE__);
}
break;
case CIOCFINDDEV:
error = cryptodev_find((struct crypt_find_op *)data);
break;
@ -1581,10 +1337,6 @@ crypto_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
if (error == 0)
crypt_aead_to_32((void *)data, data32);
break;
case CIOCKEY32:
case CIOCKEY232:
crypt_kop_to_32((void *)data, data32);
break;
}
#endif
return (error);

View file

@ -192,11 +192,6 @@
#define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \
(x) <= CRYPTO_ALGORITHM_MAX)
/* Algorithm flags */
#define CRYPTO_ALG_FLAG_SUPPORTED 0x01 /* Algorithm is supported */
#define CRYPTO_ALG_FLAG_RNG_ENABLE 0x02 /* Has HW RNG for DH/DSA */
#define CRYPTO_ALG_FLAG_DSA_SHA 0x04 /* Can do SHA on msg */
/*
* Crypto driver/device flags. They can set in the crid
* parameter when creating a session or submitting a key
@ -289,43 +284,10 @@ struct crypt_find_op {
char name[32]; /* device/driver name */
};
/* bignum parameter, in packed bytes, ... */
struct crparam {
void *crp_p;
u_int crp_nbits;
};
#define CRK_MAXPARAM 8
struct crypt_kop {
u_int crk_op; /* ie. CRK_MOD_EXP or other */
u_int crk_status; /* return status */
u_short crk_iparams; /* # of input parameters */
u_short crk_oparams; /* # of output parameters */
u_int crk_crid; /* NB: only used by CIOCKEY2 (rw) */
struct crparam crk_param[CRK_MAXPARAM];
};
#define CRK_ALGORITM_MIN 0
#define CRK_MOD_EXP 0
#define CRK_MOD_EXP_CRT 1
#define CRK_DSA_SIGN 2
#define CRK_DSA_VERIFY 3
#define CRK_DH_COMPUTE_KEY 4
#define CRK_ALGORITHM_MAX 4 /* Keep updated - see below */
#define CRF_MOD_EXP (1 << CRK_MOD_EXP)
#define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT)
#define CRF_DSA_SIGN (1 << CRK_DSA_SIGN)
#define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY)
#define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY)
#define CIOCGSESSION _IOWR('c', 101, struct session_op)
#define CIOCFSESSION _IOW('c', 102, uint32_t)
#define CIOCCRYPT _IOWR('c', 103, struct crypt_op)
#define CIOCKEY _IOWR('c', 104, struct crypt_kop)
#define CIOCASYMFEAT _IOR('c', 105, uint32_t)
#define CIOCGSESSION2 _IOWR('c', 106, struct session2_op)
#define CIOCKEY2 _IOWR('c', 107, struct crypt_kop)
#define CIOCFINDDEV _IOWR('c', 108, struct crypt_find_op)
#define CIOCCRYPTAEAD _IOWR('c', 109, struct crypt_aead)
@ -602,20 +564,6 @@ crypto_use_output_uio(struct cryptop *crp, struct uio *uio)
*/
#define CRYPTO_HINT_MORE 0x1 /* more ops coming shortly */
struct cryptkop {
TAILQ_ENTRY(cryptkop) krp_next;
u_int krp_op; /* ie. CRK_MOD_EXP or other */
u_int krp_status; /* return status */
u_short krp_iparams; /* # of input parameters */
u_short krp_oparams; /* # of output parameters */
u_int krp_crid; /* desired device, etc. */
uint32_t krp_hid; /* device used */
struct crparam krp_param[CRK_MAXPARAM]; /* kvm */
void (*krp_callback)(struct cryptkop *);
struct cryptocap *krp_cap;
};
uint32_t crypto_ses2hid(crypto_session_t crypto_session);
uint32_t crypto_ses2caps(crypto_session_t crypto_session);
void *crypto_get_driver_session(crypto_session_t crypto_session);
@ -640,19 +588,14 @@ extern int32_t crypto_get_driverid(device_t dev, size_t session_size,
extern int crypto_find_driver(const char *);
extern device_t crypto_find_device_byhid(int hid);
extern int crypto_getcaps(int hid);
extern int crypto_kregister(uint32_t, int, uint32_t);
extern int crypto_unregister_all(uint32_t driverid);
extern int crypto_dispatch(struct cryptop *crp);
#define CRYPTO_ASYNC_ORDERED 0x1 /* complete in order dispatched */
extern int crypto_dispatch_async(struct cryptop *crp, int flags);
extern void crypto_dispatch_batch(struct cryptopq *crpq, int flags);
extern int crypto_kdispatch(struct cryptkop *);
#define CRYPTO_SYMQ 0x1
#define CRYPTO_ASYMQ 0x2
extern int crypto_unblock(uint32_t, int);
extern void crypto_done(struct cryptop *crp);
extern void crypto_kdone(struct cryptkop *);
extern int crypto_getfeat(int *);
extern void crypto_destroyreq(struct cryptop *crp);
extern void crypto_initreq(struct cryptop *crp, crypto_session_t cses);
@ -660,7 +603,6 @@ extern void crypto_freereq(struct cryptop *crp);
extern struct cryptop *crypto_getreq(crypto_session_t cses, int how);
extern int crypto_usercrypto; /* userland may do crypto requests */
extern int crypto_userasymcrypto; /* userland may do asym crypto reqs */
extern int crypto_devallowsoft; /* only use hardware crypto */
#ifdef SYSCTL_DECL

View file

@ -116,9 +116,9 @@ METHOD void freesession {
} DEFAULT null_freesession;
/**
* @brief Perform a symmetric crypto operation
* @brief Perform a crypto operation
*
* The crypto framework invokes this method for each symmetric crypto
* The crypto framework invokes this method for each crypto
* operation performed on a session. A reference to the containing
* session is stored as a member of 'struct cryptop'. This routine
* should not block, but queue the operation if necessary.
@ -145,35 +145,3 @@ METHOD int process {
struct cryptop *op;
int flags;
};
/**
* @brief Perform an asymmetric crypto operation
*
* The crypto framework invokes this method for each asymmetric crypto
* operation. Each asymmetric crypto operation should be
* self-contained and is not assicated with any persistent session.
* This routine should not block, but queue the operation if
* necessary.
*
* This method may return ERESTART to indicate that any internal
* queues are full so the operation should be queued in the crypto
* framework and retried in the future.
*
* To report errors with a crypto operation, 'krp_status' should be set
* and the operation completed by calling 'crypto_kdone'. This method
* should then return zero.
*
* @param dev the crypto driver device
* @param op crypto operation to perform
* @param flags set to CRYPTO_HINT_MORE if additional asymmetric
* crypto operations are queued for this driver;
* otherwise set to zero.
*
* @retval 0 success
* @retval ERESTART internal queue is full
*/
METHOD int kprocess {
device_t dev;
struct cryptkop *op;
int flags;
};

View file

@ -26,7 +26,7 @@
# SUCH DAMAGE.
#
PROGS= cryptocheck cryptotest cryptokeytest cryptostats \
PROGS= cryptocheck cryptotest cryptostats \
hifnstats ipsecstats safestats
MAN=
BINDIR?= /usr/local/bin
@ -34,9 +34,6 @@ BINDIR?= /usr/local/bin
# cryptocheck: test symmetric crypto functions
LIBADD.cryptocheck+= crypto util
# cryptokeytest: test asymmetric crypto functions
LIBADD.cryptokeytest+= crypto
# cryptostats: dump statistics kept by the core crypto code
# hifnstats: print statistics kept by the HIFN driver
# safestats: statistics kept by the SafeNet driver

View file

@ -1,270 +0,0 @@
/* $FreeBSD$ */
/*
* The big num stuff is a bit broken at the moment and I've not yet fixed it.
* The symtom is that odd size big nums will fail. Test code below (it only
* uses modexp currently).
*
* --Jason L. Wright
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <crypto/cryptodev.h>
#include <err.h>
#include <fcntl.h>
#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/bn.h>
#include <openssl/err.h>
int crid = CRYPTO_FLAG_HARDWARE;
int verbose = 0;
static int
devcrypto(void)
{
static int fd = -1;
if (fd < 0) {
fd = open(_PATH_DEV "crypto", O_RDWR, 0);
if (fd < 0)
err(1, _PATH_DEV "crypto");
if (fcntl(fd, F_SETFD, 1) == -1)
err(1, "fcntl(F_SETFD) (devcrypto)");
}
return fd;
}
static int
crlookup(const char *devname)
{
struct crypt_find_op find;
find.crid = -1;
strlcpy(find.name, devname, sizeof(find.name));
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
err(1, "ioctl(CIOCFINDDEV)");
return find.crid;
}
static const char *
crfind(int crid)
{
static struct crypt_find_op find;
bzero(&find, sizeof(find));
find.crid = crid;
if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1)
err(1, "ioctl(CIOCFINDDEV)");
return find.name;
}
/*
* Convert a little endian byte string in 'p' that is 'plen' bytes long to a
* BIGNUM. A new BIGNUM is allocated. Returns NULL on failure.
*/
static BIGNUM *
le_to_bignum(BIGNUM *res, const void *p, int plen)
{
res = BN_lebin2bn(p, plen, res);
if (res == NULL)
ERR_print_errors_fp(stderr);
return (res);
}
/*
* Convert a BIGNUM to a little endian byte string. Space for BN_num_bytes(n)
* is allocated.
* Returns NULL on failure.
*/
static void *
bignum_to_le(const BIGNUM *n)
{
int blen, error;
void *rd;
blen = BN_num_bytes(n);
if (blen == 0)
return (NULL);
rd = malloc(blen);
if (rd == NULL)
return (NULL);
error = BN_bn2lebinpad(n, rd, blen);
if (error < 0) {
ERR_print_errors_fp(stderr);
free(rd);
return (NULL);
}
return (rd);
}
static int
UB_mod_exp(BIGNUM *res, const BIGNUM *a, const BIGNUM *b, const BIGNUM *c)
{
struct crypt_kop kop;
void *ale, *ble, *cle;
int crypto_fd = devcrypto();
if ((ale = bignum_to_le(a)) == NULL)
err(1, "bignum_to_le, a");
if ((ble = bignum_to_le(b)) == NULL)
err(1, "bignum_to_le, b");
if ((cle = bignum_to_le(c)) == NULL)
err(1, "bignum_to_le, c");
bzero(&kop, sizeof(kop));
kop.crk_op = CRK_MOD_EXP;
kop.crk_iparams = 3;
kop.crk_oparams = 1;
kop.crk_crid = crid;
kop.crk_param[0].crp_p = ale;
kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8;
kop.crk_param[1].crp_p = ble;
kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8;
kop.crk_param[2].crp_p = cle;
kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8;
kop.crk_param[3].crp_p = cle;
kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8;
if (ioctl(crypto_fd, CIOCKEY2, &kop) == -1)
err(1, "CIOCKEY2");
if (verbose)
printf("device = %s\n", crfind(kop.crk_crid));
explicit_bzero(ale, BN_num_bytes(a));
free(ale);
explicit_bzero(ble, BN_num_bytes(b));
free(ble);
if (kop.crk_status != 0) {
printf("error %d\n", kop.crk_status);
explicit_bzero(cle, BN_num_bytes(c));
free(cle);
return (-1);
} else {
res = le_to_bignum(res, cle, BN_num_bytes(c));
explicit_bzero(cle, BN_num_bytes(c));
free(cle);
if (res == NULL)
err(1, "le_to_bignum");
return (0);
}
return (0);
}
static void
show_result(const BIGNUM *a, const BIGNUM *b, const BIGNUM *c,
const BIGNUM *sw, const BIGNUM *hw)
{
printf("\n");
printf("A = ");
BN_print_fp(stdout, a);
printf("\n");
printf("B = ");
BN_print_fp(stdout, b);
printf("\n");
printf("C = ");
BN_print_fp(stdout, c);
printf("\n");
printf("sw= ");
BN_print_fp(stdout, sw);
printf("\n");
printf("hw= ");
BN_print_fp(stdout, hw);
printf("\n");
printf("\n");
}
static void
testit(void)
{
BIGNUM *a, *b, *c, *r1, *r2;
BN_CTX *ctx;
ctx = BN_CTX_new();
a = BN_new();
b = BN_new();
c = BN_new();
r1 = BN_new();
r2 = BN_new();
BN_pseudo_rand(a, 1023, 0, 0);
BN_pseudo_rand(b, 1023, 0, 0);
BN_pseudo_rand(c, 1024, 0, 0);
if (BN_cmp(a, c) > 0) {
BIGNUM *rem = BN_new();
BN_mod(rem, a, c, ctx);
UB_mod_exp(r2, rem, b, c);
BN_free(rem);
} else {
UB_mod_exp(r2, a, b, c);
}
BN_mod_exp(r1, a, b, c, ctx);
if (BN_cmp(r1, r2) != 0) {
show_result(a, b, c, r1, r2);
}
BN_free(r2);
BN_free(r1);
BN_free(c);
BN_free(b);
BN_free(a);
BN_CTX_free(ctx);
}
static void
usage(const char* cmd)
{
printf("usage: %s [-d dev] [-v] [count]\n", cmd);
printf("count is the number of bignum ops to do\n");
printf("\n");
printf("-d use specific device\n");
printf("-v be verbose\n");
exit(-1);
}
int
main(int argc, char *argv[])
{
int c, i;
while ((c = getopt(argc, argv, "d:v")) != -1) {
switch (c) {
case 'd':
crid = crlookup(optarg);
break;
case 'v':
verbose = 1;
break;
default:
usage(argv[0]);
}
}
argc -= optind, argv += optind;
for (i = 0; i < 1000; i++) {
fprintf(stderr, "test %d\n", i);
testit();
}
return (0);
}