Skip to contentSkip to conversation

MPI module

RFC In review Pierre Habouzit 3 participants 7 messages Jan 30, 2009 – Feb 7, 2009

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

RFC 1/1 MPI module

Hi,

First let's talk about my endgame, and then my questions.

My endgame is simple, I'd like to see an in-kernel SSL/TLS implementation in Linux happen. There are many reasons to want that, ranging from performance reasons (waking the userland each time you perform a handshake isn't particularly nice, and it's easy to make system-wide session caches) to really cool features being enabled:
- you can send "secure" file descriptors around through Unix Sockets, or prepare a "secure" socket, let it be your stdin/stdout pair and exec a service knowing nothing about SSL (think inetd-like stuff) ;
- you can deploy secure services where the actual server knows nothing

    about the certificate that is used ;
  - you can have a system-wide service dealing with peer certificate
    validations and have a real system-wide policy in this regard ;

- you could even think of some netfilter stuff to enforce security on a given socket, even if the service behind the socket knows nothing about it (bye bye stunnel)...

Nowadays, the kernel has most of what we need cipher-wise for TLS/SSL. Only the key-exchange protocols and the very TLS protocol are lacking. I'm currently addressing the former issue, namely, bringing RSA and Diffie-Hellman to the kernel.

I'm quite new to the kernel cryptographic layer, hence I'm posting a really early patch so that I can get some comments about style or choices I made that are bad for the kernel. This first patch is a concise implementation of primitives needed to implement RSA and DHM key-exchange protocols. I've not tested it yet, it's likely to contain bugs.

Though, I have a few questions.

(1) I need arch-specific headers to propose optimized assembly code for the MPI multiplications. The API header is <crypto/bignum.h> though there is no asm-generic/crypto/bignum.h header. Should I create such a header or is using asm-generic/bignum.h (which is what the patch does atm) correct ?

(2) The SSL library I based my work upon provides an SSE2 implementation of the MPI multiplication, though I'm unsure how I should enable it. For now it's guarded behind a #ifdef __HAVE_SSE2 which doesn't exist. I imagine options are either detecting if the compilation target has SSE2, or some kind of runtime test, but I'm unsure what the kernel ways are in that regard.

(3) I'm creating a module, but I'm unsure if that should not just be yes-or-no stuff. I don't know what the policy is in that regard.

I believe that the code is quite readable, though if anything looks wrong, please tell me :)

PS: wrt my endgame, I'm for now really concentrating on the crypto
stuff, IOW bringing RSA and Diffie-Hellman in.

I don't intend to bring x509 and certificate validation _into_ the kernel, it makes no sense to me, this can be delegated to userland easily.

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org

From: Pierre Habouzit <[email protected]>
Subject: [PATCH] crypto: add multiple precision APIs

Adds CONFIG_CRYPTO_BIGNUM to provide mpi_* APIs.

This introduces the multiple precision integers, through the struct mpi type. MPI instances are just a bunch of unsigned longs (or limbs), in little endian order, which is a rather usual representation.

Though, MPI instances have to respect a couple of invariants, the most importants being:
* at any time the length (number of least significant limbs) of the MPI

    is known;

* at any time, all allocated limbs after the most significant limb must be set to 0.

Many mpi_* APIs use that fact to compute a valid result (see for example mpi_sbits or mpi_is_zero).

---
 arch/x86/include/asm/bignum.h    |   11 +
 arch/x86/include/asm/bignum_32.h |  127 ++++++
 arch/x86/include/asm/bignum_64.h |   51 +++
 crypto/Kconfig                   |    6 +
 crypto/Makefile                  |    1 +
 crypto/bignum.c                  |  805 ++++++++++++++++++++++++++++++++++++++
 include/asm-generic/bignum.h     |   80 ++++
 include/crypto/bignum.h          |  209 ++++++++++
 8 files changed, 1290 insertions(+), 0 deletions(-)
 create mode 100644 arch/x86/include/asm/bignum.h
 create mode 100644 arch/x86/include/asm/bignum_32.h
 create mode 100644 arch/x86/include/asm/bignum_64.h
 create mode 100644 crypto/bignum.c
 create mode 100644 include/asm-generic/bignum.h
 create mode 100644 include/crypto/bignum.h
arch/x86/include/asm/bignum.h new file +11 -0
new file mode 100644
index 0000000..e33da47
@@ -0,0 +1,11 @@
+#ifndef _ASM_X86_BIGNUM_H
+#define _ASM_X86_BIGNUM_H
+
+#ifdef CONFIG_X86_32
+# include "bignum_32.h"
+#else
+# include "bignum_64.h"
+#endif
+#include <asm-generic/bignum.h>
+
+#endif
arch/x86/include/asm/bignum_32.h new file +127 -0

127 lines not on this page · raw message

arch/x86/include/asm/bignum_64.h new file +51 -0

51 lines not on this page · raw message

crypto/Kconfig +6 -0
index 8dde4fc..12a7d99 100644
@@ -29,6 +29,12 @@ config CRYPTO_FIPS
 	  certification.  You should say no unless you know what
 	  this is.
 
+config CRYPTO_BIGNUM
+        tristate "Big Number library"
+        help
+	  This option provides the APIs for multiple precision integer
+	  operations.
+
 config CRYPTO_ALGAPI
 	tristate
 	select CRYPTO_ALGAPI2
crypto/Makefile +1 -0
index 46b08bf..270cdea 100644
@@ -6,6 +6,7 @@ obj-$(CONFIG_CRYPTO) += crypto.o
 crypto-objs := api.o cipher.o digest.o compress.o
 
 obj-$(CONFIG_CRYPTO_FIPS) += fips.o
+obj-$(CONFIG_CRYPTO_BIGNUM) += bignum.o
 
 crypto_algapi-$(CONFIG_PROC_FS) += proc.o
 crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
crypto/bignum.c new file +805 -0

805 lines not on this page · raw message

include/asm-generic/bignum.h new file +80 -0

80 lines not on this page · raw message

include/crypto/bignum.h new file +209 -0

209 lines not on this page · raw message

Signature · 1 line
1.6.1.399.g0d272
maintainer
#1 lore raw
Quoted 17 lines · Pierre Habouzit

My endgame is simple, I'd like to see an in-kernel SSL/TLS implementation in Linux happen. There are many reasons to want that, ranging from performance reasons (waking the userland each time you perform a handshake isn't particularly nice, and it's easy to make system-wide session caches) to really cool features being enabled:
- you can send "secure" file descriptors around through Unix Sockets, or prepare a "secure" socket, let it be your stdin/stdout pair and exec a service knowing nothing about SSL (think inetd-like stuff) ;
- you can deploy secure services where the actual server knows nothing about the certificate that is used ;
- you can have a system-wide service dealing with peer certificate validations and have a real system-wide policy in this regard ;
- you could even think of some netfilter stuff to enforce security on a given socket, even if the service behind the socket knows nothing about it (bye bye stunnel)...

Quoted 4 lines

Nowadays, the kernel has most of what we need cipher-wise for TLS/SSL. Only the key-exchange protocols and the very TLS protocol are lacking. I'm currently addressing the former issue, namely, bringing RSA and Diffie-Hellman to the kernel.

Stop right there. There is absolutely no reason why you need to do the TLS stuff in kernel to achieve the goals you listed above.

What you should do is have user-space create the session, and then give the keys to the kernel to do the data-path. Please take a look at IPsec for an example of how the work is divided between user-space and the kernel.

Cheers,

Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
#2 lore raw
Quoted 23 lines · Herbert Xu
Quoted 17 lines · Pierre Habouzit

My endgame is simple, I'd like to see an in-kernel SSL/TLS implementation in Linux happen. There are many reasons to want that, ranging from performance reasons (waking the userland each time you perform a handshake isn't particularly nice, and it's easy to make system-wide session caches) to really cool features being enabled:
- you can send "secure" file descriptors around through Unix Sockets, or prepare a "secure" socket, let it be your stdin/stdout pair and exec a service knowing nothing about SSL (think inetd-like stuff) ;
- you can deploy secure services where the actual server knows nothing about the certificate that is used ;
- you can have a system-wide service dealing with peer certificate validations and have a real system-wide policy in this regard ;
- you could even think of some netfilter stuff to enforce security on a given socket, even if the service behind the socket knows nothing about it (bye bye stunnel)...

Quoted 4 lines

Nowadays, the kernel has most of what we need cipher-wise for TLS/SSL. Only the key-exchange protocols and the very TLS protocol are lacking. I'm currently addressing the former issue, namely, bringing RSA and Diffie-Hellman to the kernel.

Quoted 8 lines

Stop right there. There is absolutely no reason why you need to do the TLS stuff in kernel to achieve the goals you listed above.

What you should do is have user-space create the session, and then give the keys to the kernel to do the data-path. Please take a look at IPsec for an example of how the work is divided between user-space and the kernel.

So let me rephrase that to be sure we've understood each other. What you suggest is to have an IKE-like daemon dealing with the keys and all the handshakes, and that the kernel would only deal with the symmetric ciphers used on the data path. Is that right ?

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
maintainer
#3 lore raw
Quoted 5 lines · Pierre Habouzit

So let me rephrase that to be sure we've understood each other. What you suggest is to have an IKE-like daemon dealing with the keys and all the handshakes, and that the kernel would only deal with the symmetric ciphers used on the data path. Is that right ?

Either a daemon or a library in user-space should handle the hard work of negotiating the keys. You can leave the easy work of encrypting/decrypting the data to the kernel :)

Cheers,

Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
#4 lore raw

Hi,

I would like to add that you can even handle the TLS/DTLS/SSL packet formation in the kernel as well if you provide an algorithms that does just that. Right now, most user just use the kernel for the hashing and cipher parts. There is no reason that the current framework cannot handle processing the full packet in hardware. All you need is to create another algorithm name that is aead type. Then, from user space (using Linux CryptoAPI user space interface) creates that algorithms. The underlying CryptoAPI will call the appropriate function that provided by your driver and the result of the operation will be an TLS/DTLS/SSL packet formation.

We currently does this for testing our hardware for non-IPSec protocol.

-Loc

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Herbert Xu
Sent: Friday, January 30, 2009 4:41 AM
To: Pierre Habouzit
Cc: [email protected]
Subject: Re: [RFC] MPI module

Quoted 5 lines · Pierre Habouzit

So let me rephrase that to be sure we've understood each other. What you suggest is to have an IKE-like daemon dealing with the keys and all the handshakes, and that the kernel would only deal with the symmetric ciphers used on the data path. Is that right ?

Either a daemon or a library in user-space should handle the hard work of negotiating the keys. You can leave the easy work of encrypting/decrypting the data to the kernel :)

Cheers,

Signature · 8 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
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 linux-crypto" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#5 lore raw
Quoted 12 lines · Loc Ho

Hi,

I would like to add that you can even handle the TLS/DTLS/SSL packet formation in the kernel as well if you provide an algorithms that does just that. Right now, most user just use the kernel for the hashing and cipher parts. There is no reason that the current framework cannot handle processing the full packet in hardware. All you need is to create another algorithm name that is aead type. Then, from user space (using Linux CryptoAPI user space interface) creates that algorithms. The underlying CryptoAPI will call the appropriate function that provided by your driver and the result of the operation will be an TLS/DTLS/SSL packet formation.

Okay, this sounds nifty, though I'm not 100% sure I follow you. When you're talking about "Linux CryptoAPI userspace interface" are you talking about things like cryptodev[1] that aren't (AFAICT) merged into the mainline kernel ?

Or do you mean that I should write a new aead algorithm, plus provide a way (probably ioctl ?) to "activate" that algorithm on my socket once user-land has negociated the ciphers and similar stuff ?

Also, this has the drawback, unless I'm mistaken, that the program using the socket has to be aware it's using SSL/TLS/DTLS. Of course, when writing something doing SMTP with STARTTLS it has to be somehow aware of the SSL layer, since the handshake is delayed. But it would be quite sad to be unable to secure a socket without the user noticing it at any time. For example, it would be quite nifty to do through iptables something that would redirect a given port to another one and adding SSL at the same time (e.g. redirect 1.2.3.4:443 to 127.0.0.1:80 _and_ adding SSL on the top).

It makes sense to want to put the handshakes and negociations in user-space, and the system-wide ssl daemon for that task makes sense to me. So I was basically trying to figure out a clean way to "redirect" all non data SSL/TLS payloads (IOW handshakes and stuff like that) to the daemon, and the rest to the actual socket/application[2]. So either I'm wrong about what I'm trying to design, or I miss something in how your hint can help me.

Anyways, I would be delighted if you can give me more details about what you meant :)

[1] http://www.logix.cz/michal/devel/cryptodev/

[2] Which rises issues since unlike IPSec we have some programs _aware_ that they want to use SSL: it's okay to _have_ to write configuration for the system-wide daemon if you're securing something behind the original program's back. But I want that programs are still able to chose their certificate themselves and stuff like that, and it's somehow "hard" (as in racy and/or insecure) that a given program creates a socket, mark it as secure (e.g. using a setsockopt) and uploading informations about that new socket to the regulatory daemon (in the sense that anyone can claim that it possess that given socket, only the kernel really knows about it). But I assume those issues can be resolved later once I've accustomed myself with the kernel crypto a bit more.

Signature · 3 lines
·O·  Pierre Habouzit
··O                                                [email protected]
OOO                                                http://www.madism.org
#6 lore raw

Hi,

Sorry for the late response... See inline...

-Loc

-----Original Message-----
From: Pierre Habouzit [mailto:[email protected]]
Sent: Saturday, January 31, 2009 2:35 PM
To: Loc Ho
Cc: Herbert Xu; [email protected]
Subject: Re: [RFC] MPI module

Quoted 12 lines · Loc Ho

Hi,

I would like to add that you can even handle the TLS/DTLS/SSL packet formation in the kernel as well if you provide an algorithms that does just that. Right now, most user just use the kernel for the hashing and cipher parts. There is no reason that the current framework cannot handle processing the full packet in hardware. All you need is to create another algorithm name that is aead type. Then, from user space (using Linux CryptoAPI user space interface) creates that algorithms. The underlying CryptoAPI will call the appropriate function that provided by your driver and the result of the operation will be an TLS/DTLS/SSL packet formation.

Okay, this sounds nifty, though I'm not 100% sure I follow you. When you're talking about "Linux CryptoAPI userspace interface" are you talking about things like cryptodev[1] that aren't (AFAICT) merged into the mainline kernel ? [Loc Ho]
Yes... We use this to test various algorithms supported by our hardware.

Or do you mean that I should write a new aead algorithm, plus provide a way (probably ioctl ?) to "activate" that algorithm on my socket once user-land has negociated the ciphers and similar stuff ?
[Loc Ho]
Yes... You will need an aead type algorithm that does what you want. Let say you want to process "DTLS" algorithm. Then provide a driver implementation for DTLS processing. From User Space, you would create this algorithm and operate on this algorithm over Linux CryptoAPI User Space interface. You might have to change slight in the User space interface code - try and see.

Also, this has the drawback, unless I'm mistaken, that the program using the socket has to be aware it's using SSL/TLS/DTLS. Of course, when writing something doing SMTP with STARTTLS it has to be somehow aware of the SSL layer, since the handshake is delayed. But it would be quite sad to be unable to secure a socket without the user noticing it at any time. For example, it would be quite nifty to do through iptables something that would redirect a given port to another one and adding SSL at the same time (e.g. redirect 1.2.3.4:443 to 127.0.0.1:80 _and_ adding SSL on the top). [Loc Ho]
Yes... Unless you handle everything in the kernel (like IPSec), there is always a trade off. You could direct traffic to user space program and do all you processing and then inject back to the stack.

It makes sense to want to put the handshakes and negociations in user-space, and the system-wide ssl daemon for that task makes sense to me. So I was basically trying to figure out a clean way to "redirect" all non data SSL/TLS payloads (IOW handshakes and stuff like that) to the daemon, and the rest to the actual socket/application[2]. So either I'm wrong about what I'm trying to design, or I miss something in how your hint can help me. [Loc Ho]
Not sure what you referring here...

Anyways, I would be delighted if you can give me more details about what you meant :)

[1] http://www.logix.cz/michal/devel/cryptodev/

[2] Which rises issues since unlike IPSec we have some programs _aware_ that they want to use SSL: it's okay to _have_ to write configuration for the system-wide daemon if you're securing something behind the original program's back. But I want that programs are still able to chose their certificate themselves and stuff like that, and it's somehow "hard" (as in racy and/or insecure) that a given program creates a socket, mark it as secure (e.g. using a setsockopt) and uploading informations about that new socket to the regulatory daemon (in the sense that anyone can claim that it possess that given socket, only the kernel really knows about it). But I assume those issues can be resolved later once I've accustomed myself with the kernel crypto a bit more.

--
·O· Pierre Habouzit
··O [email protected]
OOO http://www.madism.org