[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20100907084213.GA4610@gondor.apana.org.au>
Date: Tue, 7 Sep 2010 16:42:13 +0800
From: Herbert Xu <herbert@...dor.apana.org.au>
To: Linux Crypto Mailing List <linux-crypto@...r.kernel.org>,
netdev@...r.kernel.org
Subject: RFC: Crypto API User-interface
Hi:
This is what I am proposing for the Crypto API user-interface.
Note that this is the interface for operations. There will be
a separate interface (most likely netlink) for configuring crypto
algorithms, e.g., picking a specific AES implementation as the
system default.
First of all let's have a quick look at what the user-space side
looks like for AEAD:
int op;
/* This fd corresponds to a tfm object. */
tfmfd = socket(AF_ALG, SOCK_STREAM, 0);
alg.type = "aead";
alg.name = "ccm(aes)";
bind(tfmfd, &alg, sizeof(alg));
setsockopt(tfmfd, SOL_ALG, ALG_AEAD_SET_KEY, key, keylen);
The idea here is that each tfm corresponds to a listening socket.
/* Each listen call generates one or more fds for input/output
* that behave like pipes.
*/
listen(tfmfd, 0);
/* fd for encryption/decryption */
opfd = accept(tfmfd, NULL, 0);
/* fd for associated data */
adfd = accept(tfmfd, NULL, 0);
Each session corresponds to one or more connections obtained from
that socket. The number depends on the number of inputs/outputs
of that particular type of operation. For most types, there will
be a s ingle connection/file descriptor that is used for both input
and output. AEAD is one of the few that require two inputs.
/* These may also be set through sendmsg(2) cmsgs. */
op = ALG_AEAD_OP_ENCRYPT;
setsockopt(opfd, SOL_ALG, ALG_AEAD_OP, op, sizeof(op));
setsockopt(opfd, SOL_ALG, ALG_AEAD_SET_IV, iv, ivlen);
/* Like pipes, larges writes will block!
* For AEAD, ensure the socket buffer is large enough.
* For ciphers, whenever the write blocks start reading.
* For hashes, writes should never block.
*/
write(opfd, plain, datalen);
write(adfd, ad, adlen);
/* The first read triggers the operation. */
read(opfd, crypt, datalen);
op = ALG_AEAD_OP_DECRYPT;
setsockopt(opfd, SOL_ALG, ALG_AEAD_OP, op, sizeof(op));
write(opfd, crypt, datalen);
write(adfd, ad, adlen);
/* Returns -1 with errno EBADMSG if auth fails */
read(defd, plain, datalen);
/* Zero-copy */
splice(cryptfd, NULL, opfd, NULL, datalen, SPLICE_F_MOVE|SPLIFE_F_MORE);
/* We allow writes to be split into multiple system calls. */
splice(cryptfd2, NULL, opfd, NULL, datalen, SPLICE_F_MOVE);
splice(adatafd, NULL, adfd, NULL, adlen, SPLICE_F_MOVE);
/* For now reading is copy-only, if and when vmsplice
* starts supporting zero-copy to user then we can do it
* as well.
*/
read(opfd, plain, datalen);
Ciphers/compression are pretty much the same sans adfd.
For hashes:
/* This fd corresponds to a tfm object. */
tfmfd = socket(AF_ALG, SOCK_STREAM, 0);
alg.type = "hash";
alg.name = "xcbc(aes)";
bind(tfmfd, &alg, sizeof(alg));
setsockopt(tfmfd, SOL_ALG, ALG_HASH_SET_KEY, key, keylen);
/* Each listen call generates one or more fds for input/output
* that behave like pipes.
*/
listen(tfmfd, 0);
/* fd for hashing */
opfd = accept(tfmfd, NULL, 0);
/* MSG_MORE prevents finalisation */
send(opfd, plain, datalen, MSG_MORE);
/* Reads partial hash state */
read(opfd, state, statelen);
/* Restore from a partial hash state */
send(opfd, state, statelen, MSG_OOB);
/* Finalise */
send(opfd, plain, 0, 0);
read(opfd, hash, hashlen);
Please comment.
Thanks,
--
Email: Herbert Xu <herbert@...dor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists