Re: RFC: Crypto API User-interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2010-09-07 at 16:42 +0800, Herbert Xu wrote: 
> 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);

This has much much higher overhead in terms of number of needed syscalls
than the previously proposed ioctl interface. Of course in case of large
data operation the overhead converges to just one or two (for AEAD) more
syscalls (1. ioctl vs. 2. write+read). But there will be many real
use-cases where all the setup of the fds will be done again and again.
And of course it adds an overhead in terms of number of file descriptors
needed for each crypto operation. Where the old interface had just
constant one fd overhead per lifetime of the process, this interface has
3 fds per crypto context in use.

> 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.
This is also serious performance penalty for now.

> 	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);
Note, that one of frequent hash operations is duplicating the internal
hash state. How this would be done with this API?

-- 
Tomas Mraz
No matter how far down the wrong road you've gone, turn back.
                                              Turkish proverb

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux