All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds
@ 2016-06-06 20:54 Mat Martineau
  2016-06-06 20:54 ` [PATCH 02/11] main: Fix comment typo Mat Martineau
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 375 bytes --]

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 6e35752..cad1672 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,7 @@ unit/test-genl-msg
 unit/test-kdbus
 unit/test-dbus
 unit/test-dbus-message
+unit/test-dbus-message-fds
 unit/test-dbus-util
 unit/test-dbus-service
 unit/test-dbus-watch
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 02/11] main: Fix comment typo
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 03/11] unit: Free all memory allocated during the DH test Mat Martineau
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 560 bytes --]

---
 ell/main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ell/main.c b/ell/main.c
index 46e929a..f53ed9e 100644
--- a/ell/main.c
+++ b/ell/main.c
@@ -444,7 +444,7 @@ static void signal_handler(struct l_signal *signal, uint32_t signo,
  *
  * Run the main loop with signal handling for SIGINT and SIGTERM
  *
- * Returns: #EXIT_SCUCESS after successful execution or #EXIT_FAILURE in
+ * Returns: #EXIT_SUCCESS after successful execution or #EXIT_FAILURE in
  *          case of failure
  **/
 LIB_EXPORT
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 03/11] unit: Free all memory allocated during the DH test
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
  2016-06-06 20:54 ` [PATCH 02/11] main: Fix comment typo Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 04/11] unit: Script and config file for creating test certificates Mat Martineau
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 407 bytes --]

---
 unit/test-key.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/unit/test-key.c b/unit/test-key.c
index d655fed..53232da 100644
--- a/unit/test-key.c
+++ b/unit/test-key.c
@@ -328,6 +328,7 @@ static void test_dh(const void *data)
 	testkey_free_contents(&pub1);
 	testkey_free_contents(&priv2);
 	testkey_free_contents(&pub2);
+	l_free(secret);
 	l_free(buffer);
 }
 
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 04/11] unit: Script and config file for creating test certificates
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
  2016-06-06 20:54 ` [PATCH 02/11] main: Fix comment typo Mat Martineau
  2016-06-06 20:54 ` [PATCH 03/11] unit: Free all memory allocated during the DH test Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 05/11] unit: New set of " Mat Martineau
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2328 bytes --]

---
 unit/gencerts.cnf | 14 ++++++++++++++
 unit/gencerts.sh  | 19 +++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 unit/gencerts.cnf
 create mode 100755 unit/gencerts.sh

diff --git a/unit/gencerts.cnf b/unit/gencerts.cnf
new file mode 100644
index 0000000..46eb166
--- /dev/null
+++ b/unit/gencerts.cnf
@@ -0,0 +1,14 @@
+[ req ]
+distinguished_name = req_distinguished_name
+
+[ req_distinguished_name ]
+
+[ ca_ext ]
+basicConstraints = CA:TRUE,pathlen:0
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
+
+[ cert_ext ]
+basicConstraints = CA:FALSE
+subjectKeyIdentifier = hash
+authorityKeyIdentifier = keyid:always,issuer:always
diff --git a/unit/gencerts.sh b/unit/gencerts.sh
new file mode 100755
index 0000000..fb305d7
--- /dev/null
+++ b/unit/gencerts.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/sh
+
+echo "*** CA Certificate ***"
+openssl genrsa -out cert-ca-key.pem 2048
+openssl req -x509 -new -nodes -extensions ca_ext -config ./gencerts.cnf -subj '/O=International Union of Example Organizations/CN=Certificate issuer guy/emailAddress=ca(a)mail.example' -key cert-ca-key.pem -sha256 -days 10000 -out cert-ca.pem
+
+echo -e "\n*** Server Certificate ***"
+openssl genrsa -out cert-server-key.pem
+openssl req -new -extensions cert_ext -config ./gencerts.cnf -subj '/O=Foo Example Organization/CN=Foo Example Organization/emailAddress=foo(a)mail.example' -key cert-server-key.pem -out cert-server.csr
+openssl x509 -req -extensions cert_ext -extfile ./gencerts.cnf -in cert-server.csr -CA cert-ca.pem -CAkey cert-ca-key.pem -CAcreateserial -sha256 -days 10000 -out cert-server.pem
+openssl verify -CAfile cert-ca.pem cert-server.pem
+
+echo -e "\n*** Client Certificate ***"
+openssl genrsa -out cert-client-key.pem
+openssl req -new -extensions cert_ext -config ./gencerts.cnf -subj '/O=Bar Example Organization/CN=Bar Example Organization/emailAddress=bar(a)mail.example' -key cert-client-key.pem -out cert-client.csr
+openssl x509 -req -extensions cert_ext -extfile ./gencerts.cnf -in cert-client.csr -CA cert-ca.pem -CAkey cert-ca-key.pem -CAcreateserial -sha256 -days 10000 -out cert-client.pem
+openssl verify -CAfile cert-ca.pem cert-client.pem
+
+rm cert-ca.srl cert-client.csr cert-server.csr
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 05/11] unit: New set of test certificates
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (2 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 04/11] unit: Script and config file for creating test certificates Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 06/11] key: Add keyring APIs Mat Martineau
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 21342 bytes --]

These certificates were generated by gencerts.sh. The previous
certificates used MD5 hashes, which caused problems on systems with
weak ciphers disabled.
---
 unit/cert-ca-key.pem     | 50 ++++++++++++++++++++++++------------------------
 unit/cert-ca.pem         | 46 ++++++++++++++++++++++----------------------
 unit/cert-client-key.pem | 50 ++++++++++++++++++++++++------------------------
 unit/cert-client.pem     | 47 ++++++++++++++++++++++-----------------------
 unit/cert-server-key.pem | 50 ++++++++++++++++++++++++------------------------
 unit/cert-server.pem     | 47 ++++++++++++++++++++++-----------------------
 6 files changed, 144 insertions(+), 146 deletions(-)

diff --git a/unit/cert-ca-key.pem b/unit/cert-ca-key.pem
index f121d73..2f70ae5 100644
--- a/unit/cert-ca-key.pem
+++ b/unit/cert-ca-key.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+MIIEogIBAAKCAQEAo3GrGqW49h8kY2Wx/1kd5dIkYGazuWrX93ma9904hHBJNsvu
+V34QfHVln6wDpMZMwuvkfct09kl0rQpztJzA9YL4GMdmV6+6J6LiX1kMqLkNaJa+
+Ov+ECG5ypBRbSTYKpqFsc5wPOQf/N8brBiZS1v67va3fCwO6dgLeAf7dZ3Q70oUr
+mghbK8UnlC+wLShxCBAW8TUKg7B7M5Gea794CO9wH7NsFyAr963WVcLxrdL3xMHZ
+9hcscrljh35nCAc6sum1cTtWI651OGehr0Bhp2o2Exgr2mbo5TobqEW+fe4gc4ik
+0nzHGWiOVaszUcvpeeduGV3y6om93atffeKuxQIDAQABAoIBADilmsHfkh1rabcx
+deGkR2Jx1L28mqm2yCczdGxXtdDhAd8GCxMz1A7uuUv/2DtxpwUfsM+QhncdulyG
+9NcyRQZSYB5mbagSdZhrMb4OJP8NNAJ9zGyyRlaNwRnxHDphiot6AxaGjhgcF26D
+eM1m1utA2lzBOD6fCi8Ai2VxqdbCul0bl6uU6paIXzXd2Gk8m68V0AO8oJRy2AER
+eFxvrf/u+JFyMiYKY2qlJ2+3MJRT1IWDaLwdHUdp6b9n7t7nIbQ8xW45OuDZ/x3q
+rgOZO5+jC5Zfxjg8Vg5cqwigdWibYIemGduZTPpwIv8sU2BWI0QhIQViYk2jbI3f
+8uCGuvkCgYEA1F71RlSOM5lHgpzHIL/IVfxEC3Ja4V0Bp9AbepQeMPo4l7tSqEVT
+sn+xyIX7B+zUUDiNKyaADNQ1qQwGmMZWgfqFRYszG3a2XtNRtpoCQy7T0+Ef+Iwv
+9bwoHYkCRwwYwM14ymYL4Gvt/dmQzgTzr2CfWYu5hbMQfg/ABFO7aDcCgYEAxQWK
+Bq/MFvz25W51fuo4LMRTHygPvM5fhVRXoC4wBp3cuzgZOU0pFGeuTv2q6/2rwtRz
+dQsUAibl0IM/j/dIKzbGeO0l0DZ7nZNAkSP+OT16Gmh7M/WIDLbYlk4zMQOZLQg+
+fxcWTTho8Y4H7aTrHvTIcHKlCewwcGk46Wql6uMCgYB0rS8IUtBFnQLiyYvFfFhu
+lUg1GcDAbD7KmdVfBR2JPw/0nOAOvvf665kbWDDQ69bBtDAq8t4LLlPE6mx9ZwqE
+IsUxrgaIIjKT6nnMXtS7YHDUyays+ygmVBeeEnYD3quC0eB5IpOH2wRIIU4jQik3
+w1gI9HEa+YQoHjMarX4bBQKBgEmVmQiITgRj9F6aU73UAqkNpjHjx4Tv2xMz/gow
+VfWSricqe5lALVCWrK6J5XWAZ887g+e5/H4VQw4OhwXhCI5DRftSLyZFwwOGRL4w
+oDmGsXz9es5cLLT68Yepq0rqGiKMirLyz3yFzgQx1No4FyyXpekBmIxNL4Y8dmoP
+T+qbAoGAUEe21rOM2NXw4b6Lu06eGb1STWrHmOmZI3XmvqO2u9JK9UG8P9rYqndw
+P3NaHDRwLly9efejr95RuSS54q+PMeR/BQ72ckYnWQEFuhUOTUH1BscgKysqopM2
+x2gzIZt0rdVkkiC4dRe2OjvB8OJqqYQ3iTFuZ1KdchkxIZ6xAhQ=
 -----END RSA PRIVATE KEY-----
diff --git a/unit/cert-ca.pem b/unit/cert-ca.pem
index 724f852..8b882a9 100644
--- a/unit/cert-ca.pem
+++ b/unit/cert-ca.pem
@@ -1,26 +1,26 @@
 -----BEGIN CERTIFICATE-----
-MIIEVDCCAzygAwIBAgIJAIOyXTOJrYsaMA0GCSqGSIb3DQEBCwUAMHgxNTAzBgNV
-BAoTLEludGVybmF0aW9uYWwgVW5pb24gb2YgRXhhbXBsZSBPcmdhbml6YXRpb25z
-MR8wHQYDVQQDExZDZXJ0aWZpY2F0ZSBpc3N1ZXIgZ3V5MR4wHAYJKoZIhvcNAQkB
-Fg9jYUBtYWlsLmV4YW1wbGUwHhcNMTUwNzIxMjIzMDU4WhcNMTcwNzIwMjIzMDU4
-WjB4MTUwMwYDVQQKEyxJbnRlcm5hdGlvbmFsIFVuaW9uIG9mIEV4YW1wbGUgT3Jn
-YW5pemF0aW9uczEfMB0GA1UEAxMWQ2VydGlmaWNhdGUgaXNzdWVyIGd1eTEeMBwG
+MIIEVDCCAzygAwIBAgIJAJmt2W7CutHvMA0GCSqGSIb3DQEBCwUAMHgxNTAzBgNV
+BAoMLEludGVybmF0aW9uYWwgVW5pb24gb2YgRXhhbXBsZSBPcmdhbml6YXRpb25z
+MR8wHQYDVQQDDBZDZXJ0aWZpY2F0ZSBpc3N1ZXIgZ3V5MR4wHAYJKoZIhvcNAQkB
+Fg9jYUBtYWlsLmV4YW1wbGUwHhcNMTYwNTE3MjEyMDQ2WhcNNDMxMDAzMjEyMDQ2
+WjB4MTUwMwYDVQQKDCxJbnRlcm5hdGlvbmFsIFVuaW9uIG9mIEV4YW1wbGUgT3Jn
+YW5pemF0aW9uczEfMB0GA1UEAwwWQ2VydGlmaWNhdGUgaXNzdWVyIGd1eTEeMBwG
 CSqGSIb3DQEJARYPY2FAbWFpbC5leGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEAyz0GzVnm43TnX8Gl2aK1XknC4hhnw9MdJsEgOy3XJWYo8ijo
-9YxJTuxPIFc0bz8wJYj7JO/Z7GuRsybNt4pq80ILU0LB5VSnO/yZdpEv01gfgMUk
-2aCxIwZrnnQ3owHUq6x0+amlZD5NuWmPGE8TYUTXZILHRlLac6NP7fq1bHtT+CT4
-/HIivb9lgGg/tPuMac5nFxdXyal4coVAmoQa+s8kAlbiFDEVwSMlWkh7IXf/8acx
-31UOgD8XbNdo2HGrpN0TFkPX3qwLSq1CBApu4oX2PJ8/BemRbmsWZvAIxlHUyySa
-J5zg3bxQaX/nS9nre65SXXN1DEVmPMymMxb7yQIDAQABo4HgMIHdMB0GA1UdDgQW
-BBQwJusAXVPeEDyctL5+1/gVROm4vTCBqgYDVR0jBIGiMIGfgBQwJusAXVPeEDyc
-tL5+1/gVROm4vaF8pHoweDE1MDMGA1UEChMsSW50ZXJuYXRpb25hbCBVbmlvbiBv
-ZiBFeGFtcGxlIE9yZ2FuaXphdGlvbnMxHzAdBgNVBAMTFkNlcnRpZmljYXRlIGlz
-c3VlciBndXkxHjAcBgkqhkiG9w0BCQEWD2NhQG1haWwuZXhhbXBsZYIJAIOyXTOJ
-rYsaMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBADKZwqldI8Il
-9ZgA4bhbEarcopiUUC3RMiH9cvy1rXDgYoSbC5RX2x6ptCIXDLfuAsTk+Qcl90KZ
-xno2zrKjjB7QUeb5kdZAwuZ0IoqgLWPxvdayVUDHT/7B/rNFH2ExmKR4Qz2k+gxb
-d5fUYQecRajfDQjOGhhoiDzJBq/GERXnJ2/WEOr3gFdOQ3QLFzTLjFRFlq+cxbm7
-OmBt+f2wTaX1l/EMGbxdvLfD96VbDihAl6yIsK2hNYNghW032nJjFDs7pOqneRue
-sCSbyRp2O8rBT8IPkn2e3QQl/zrdEv5FLnqrhSaB80bLJi/HGixkFkvvp+ZsWIBd
-NQZHpZyYJ+Y=
+AQ8AMIIBCgKCAQEAo3GrGqW49h8kY2Wx/1kd5dIkYGazuWrX93ma9904hHBJNsvu
+V34QfHVln6wDpMZMwuvkfct09kl0rQpztJzA9YL4GMdmV6+6J6LiX1kMqLkNaJa+
+Ov+ECG5ypBRbSTYKpqFsc5wPOQf/N8brBiZS1v67va3fCwO6dgLeAf7dZ3Q70oUr
+mghbK8UnlC+wLShxCBAW8TUKg7B7M5Gea794CO9wH7NsFyAr963WVcLxrdL3xMHZ
+9hcscrljh35nCAc6sum1cTtWI651OGehr0Bhp2o2Exgr2mbo5TobqEW+fe4gc4ik
+0nzHGWiOVaszUcvpeeduGV3y6om93atffeKuxQIDAQABo4HgMIHdMA8GA1UdEwQI
+MAYBAf8CAQAwHQYDVR0OBBYEFO+M3tJAELTnseUqZyP4vl5X7SmUMIGqBgNVHSME
+gaIwgZ+AFO+M3tJAELTnseUqZyP4vl5X7SmUoXykejB4MTUwMwYDVQQKDCxJbnRl
+cm5hdGlvbmFsIFVuaW9uIG9mIEV4YW1wbGUgT3JnYW5pemF0aW9uczEfMB0GA1UE
+AwwWQ2VydGlmaWNhdGUgaXNzdWVyIGd1eTEeMBwGCSqGSIb3DQEJARYPY2FAbWFp
+bC5leGFtcGxlggkAma3ZbsK60e8wDQYJKoZIhvcNAQELBQADggEBAA/Yb9jB94OF
+swbyCrA6Qe53YGC4dfqrKGRThtGKTrH0XcM2x2qLIIbiNDogwhRqlUW8iNY6Dm2k
+43mJzNsYhy7Nt3IJFCguTJFilfGzQnBtK8wCr/C9qsj//BESOIlo/TDZ2Ho4ixcJ
+n+FTnN34F6JJ0DIvA6tNBe1kUFSrbubL8ygNWJ9BKMebEzokGNGCGFNr70DlQj2o
+1EOMMOkj0gWO0WegAYFLojzag3l+uvU59YE+/fbZ2iclyvbF7IutQ5M9g5TnQE6F
+f+qFKR5+bhlJwry6vLl/6ulihkvF3y1bm7zae62zbFaZRU6PJUl1DtXiA23ZTm9T
+VDivqs07R84=
 -----END CERTIFICATE-----
diff --git a/unit/cert-client-key.pem b/unit/cert-client-key.pem
index b8f88cf..345432a 100644
--- a/unit/cert-client-key.pem
+++ b/unit/cert-client-key.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/unit/cert-client.pem b/unit/cert-client.pem
index 6b0fccf..3bd14fa 100644
--- a/unit/cert-client.pem
+++ b/unit/cert-client.pem
@@ -1,26 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEbzCCA1egAwIBAgIJAIOyXTOJrYsbMA0GCSqGSIb3DQEBBAUAMHgxNTAzBgNV
-BAoTLEludGVybmF0aW9uYWwgVW5pb24gb2YgRXhhbXBsZSBPcmdhbml6YXRpb25z
-MR8wHQYDVQQDExZDZXJ0aWZpY2F0ZSBpc3N1ZXIgZ3V5MR4wHAYJKoZIhvcNAQkB
-Fg9jYUBtYWlsLmV4YW1wbGUwIBcNMTUwNzIxMjIzMTE4WhgPMjExNTA2MjcyMjMx
-MThaMGcxITAfBgNVBAoTGEJhciBFeGFtcGxlIE9yZ2FuaXphdGlvbjEhMB8GA1UE
-AxMYQmFyIEV4YW1wbGUgT3JnYW5pemF0aW9uMR8wHQYJKoZIhvcNAQkBFhBiYXJA
-bWFpbC5leGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApmgm
-9gy2iv2QqjzXom8XlT34Vp5XV0QWHwaWmIYuCAYpw5A2Y5cYNULg4M3BjsrjjmMV
-G9xncQ4WJHETkAs+l2d2cIqyvzmsRJ5EakeeQuxPbX+OE4XTVUWK7U8MtFbioynO
-7fy4FXYOvG0rG9BUAocuaMgBVJZC0TIQsD+LPQizMMwlgmkcK2dy0MAD7q4ouvIr
-Wxdnn/JfcQernbl1s/ThLiFFxA+7s/QzP1zxm9nKaGSiITteqrwKPkPiRjlQPM3I
-a8i3nvskMlyZTVgEU4z0ZmoQ9T+odZ94vhR4VGib0Xr27sn1Ejhlcl3+0Lt/v086
-hkhPSZ7nV5kjzOWy5wIDAQABo4IBCTCCAQUwCQYDVR0TBAIwADAsBglghkgBhvhC
-AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFICx
-nSSUXhyrxVVOqUv/f3vZfTBoMIGqBgNVHSMEgaIwgZ+AFDAm6wBdU94QPJy0vn7X
-+BVE6bi9oXykejB4MTUwMwYDVQQKEyxJbnRlcm5hdGlvbmFsIFVuaW9uIG9mIEV4
-YW1wbGUgT3JnYW5pemF0aW9uczEfMB0GA1UEAxMWQ2VydGlmaWNhdGUgaXNzdWVy
-IGd1eTEeMBwGCSqGSIb3DQEJARYPY2FAbWFpbC5leGFtcGxlggkAg7JdM4mtixow
-DQYJKoZIhvcNAQEEBQADggEBADqzKUMa7JZr9e7d8zmWj/kBP47XzXDl/3LZXHGT
-mbdhB/j73BICEK4+2WAF8d8uKLz3zYXOXgq72l6arcPPJjyA7Q8MKfXPCIkCe1Oy
-0oEUtTeiwrsT9cPGHXcbYInNZZ0GSw/w1nYoYTsmJeLV8dakY78bdvGjHjjYlUTU
-OWC7V4HuIBq2ablHJ/i54vS+k4iN4XIppLBwXytNEnu2l5QEz+29ZIEhTlvhhIR+
-D+DiPgNBxNGlPJH0m20qpErW6as/+UXKNQgadQbZ16gjmzCoZQJxUhT/WKqPhLhK
-ApzmXLQwarIjHW2qmy4I4VXUeqe5PFT2638qshylw+Qxeug=
+MIIEPTCCAyWgAwIBAgIJAPk7rut4SWQCMA0GCSqGSIb3DQEBCwUAMHgxNTAzBgNV
+BAoMLEludGVybmF0aW9uYWwgVW5pb24gb2YgRXhhbXBsZSBPcmdhbml6YXRpb25z
+MR8wHQYDVQQDDBZDZXJ0aWZpY2F0ZSBpc3N1ZXIgZ3V5MR4wHAYJKoZIhvcNAQkB
+Fg9jYUBtYWlsLmV4YW1wbGUwHhcNMTYwNTE3MjEyMDQ3WhcNNDMxMDAzMjEyMDQ3
+WjBnMSEwHwYDVQQKDBhCYXIgRXhhbXBsZSBPcmdhbml6YXRpb24xITAfBgNVBAMM
+GEJhciBFeGFtcGxlIE9yZ2FuaXphdGlvbjEfMB0GCSqGSIb3DQEJARYQYmFyQG1h
+aWwuZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOE5D/lU
+haTC3xL281ttZPRURXlKJqLwcHGXQSuQm6wwYWtAhLyMLEHrryE0oChKdw3eV7Nn
+/IODxvk1S8uIuKfHWuNd5qX/yu7CjCWvyim2CSJHF24rQFmb9ePoddOZnDMMAIz7
+PC325JVhbr/LSBLbqhZ0smHy1HKyrzzHHzKU4YcTH/3+3H4MHZwnNZfbfG5qhRZG
+Nuu/8t+AWVcEocPRGYZpzWJNq6AAzojAHSSOxxiscBMiuQ+BdofPw9XhwpS+Fstk
+rvF8J9FfZj5U3FOm/EgOQn8efnrUL231PqB1R9PIKYv/938p3iDMIi0ETiKi5ced
+WV8m2PcykPdNOKMCAwEAAaOB2jCB1zAJBgNVHRMEAjAAMB0GA1UdDgQWBBTs9eey
+OkMw3uiPpDOa3b9KErbEfzCBqgYDVR0jBIGiMIGfgBTvjN7SQBC057HlKmcj+L5e
+V+0plKF8pHoweDE1MDMGA1UECgwsSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBFeGFt
+cGxlIE9yZ2FuaXphdGlvbnMxHzAdBgNVBAMMFkNlcnRpZmljYXRlIGlzc3VlciBn
+dXkxHjAcBgkqhkiG9w0BCQEWD2NhQG1haWwuZXhhbXBsZYIJAJmt2W7CutHvMA0G
+CSqGSIb3DQEBCwUAA4IBAQA8MxPjU2h5gwntQeSs8eeaEUILMkoU6JSDS4s5Hex5
+xYMLfcSoPPI0E6ahvKtWkSM0UZThyWsulSDTI1EgAiebjms06m1Ogh9V+0VbcOlQ
+D/k3+fSRIiyY+v3J/h8ArUby+m5O2g1TgECr/nZl4avoAI0RpBi3lH6tC8GQYdbc
+SA6hpNCM/dY3LWtAo2W6mdE8+RlCuTj4VZiQ1g6GE77t6XwDFL6vQBzLLXrinvXK
+Ha+IssV5sGdpH9bVFWIJV2q3OZuv3HLhQfGmeUrGyWVcokQQ8d6kRwg65Zb1+KT2
+bNlVKhPAMBk4ayEocpqFIfqfCKDjGdPUruIh8IVDc684
 -----END CERTIFICATE-----
diff --git a/unit/cert-server-key.pem b/unit/cert-server-key.pem
index efb3922..961a4e8 100644
--- a/unit/cert-server-key.pem
+++ b/unit/cert-server-key.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/unit/cert-server.pem b/unit/cert-server.pem
index 7f54b7a..4050d78 100644
--- a/unit/cert-server.pem
+++ b/unit/cert-server.pem
@@ -1,26 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIEbzCCA1egAwIBAgIJAIOyXTOJrYscMA0GCSqGSIb3DQEBBAUAMHgxNTAzBgNV
-BAoTLEludGVybmF0aW9uYWwgVW5pb24gb2YgRXhhbXBsZSBPcmdhbml6YXRpb25z
-MR8wHQYDVQQDExZDZXJ0aWZpY2F0ZSBpc3N1ZXIgZ3V5MR4wHAYJKoZIhvcNAQkB
-Fg9jYUBtYWlsLmV4YW1wbGUwIBcNMTUwNzIxMjIzMTUxWhgPMjExNTA2MjcyMjMx
-NTFaMGcxITAfBgNVBAoTGEZvbyBFeGFtcGxlIE9yZ2FuaXphdGlvbjEhMB8GA1UE
-AxMYRm9vIEV4YW1wbGUgT3JnYW5pemF0aW9uMR8wHQYJKoZIhvcNAQkBFhBmb29A
-bWFpbC5leGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw52f
-x0CLmdfz2JzBse6CfzTJqYljq3j6W4z3XsGz3qFtmi1eZsPY9ZNj9jpA9+vvRNRG
-+VXfkF27OVIkyiwkdN6zeVtY7PdmAQjoSv1Akwr18Mrh2mnGeKcN2+27PBglARl0
-uS7IWIGcGdHEV4idin54ExtMm7d/OW2H8WvUeMJ/vE4t0BagPAMJosOtlIO0Qzlf
-YsOuPfTxh2G4viRnw6vqD0My1jut68BqrwWJfO/h35OkhYj7sdWmWni38v2j8sbs
-/6YH3mR7YkmWijfGLlVke/tkOjx2PlItT7PIjwDOkHxsUu0yZCsEuh3w+wzuVv/B
-yzyW3K/0eAkF3ov6dQIDAQABo4IBCTCCAQUwCQYDVR0TBAIwADAsBglghkgBhvhC
-AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFL2v
-/nxaoNJQM65oOfksgwHMOgy2MIGqBgNVHSMEgaIwgZ+AFDAm6wBdU94QPJy0vn7X
-+BVE6bi9oXykejB4MTUwMwYDVQQKEyxJbnRlcm5hdGlvbmFsIFVuaW9uIG9mIEV4
-YW1wbGUgT3JnYW5pemF0aW9uczEfMB0GA1UEAxMWQ2VydGlmaWNhdGUgaXNzdWVy
-IGd1eTEeMBwGCSqGSIb3DQEJARYPY2FAbWFpbC5leGFtcGxlggkAg7JdM4mtixow
-DQYJKoZIhvcNAQEEBQADggEBAECllH+Ph+sxeYlYR4Xn/QcvBNhMW5p8jtWt0KJ+
-drpnqGz428LojEm8E2i+ab6jIDcEEzDTnDZqcszpkIAKNhNhjJyREAoYpg0EXtW8
-1SQ6rLuZwE+mkG7yGUISRN/fn9RGKkDBdDCOeeKjEkklBLijejSwTJQiai1xdIsg
-KuQpqUX5iy++MS9gL/8BeFVGgqY5MJXWXNXryjnqy7gdhUc1YHwzJbG95rAFuo/v
-yP1NTqnduchiBXbFxLPTMenpe0cGfBdfDVR39hsFZSEMnCohc+WpYSF2PPxq58iw
-zdfAwPzGdSLU/F0knKRVxtAJ7/Paz6Mvv5bTYe8i8EfbLtU=
+MIIEPTCCAyWgAwIBAgIJAPk7rut4SWQBMA0GCSqGSIb3DQEBCwUAMHgxNTAzBgNV
+BAoMLEludGVybmF0aW9uYWwgVW5pb24gb2YgRXhhbXBsZSBPcmdhbml6YXRpb25z
+MR8wHQYDVQQDDBZDZXJ0aWZpY2F0ZSBpc3N1ZXIgZ3V5MR4wHAYJKoZIhvcNAQkB
+Fg9jYUBtYWlsLmV4YW1wbGUwHhcNMTYwNTE3MjEyMDQ3WhcNNDMxMDAzMjEyMDQ3
+WjBnMSEwHwYDVQQKDBhGb28gRXhhbXBsZSBPcmdhbml6YXRpb24xITAfBgNVBAMM
+GEZvbyBFeGFtcGxlIE9yZ2FuaXphdGlvbjEfMB0GCSqGSIb3DQEJARYQZm9vQG1h
+aWwuZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANMAkF6m
+2ijGibGr9InrTqtvOBJtw+PR2XNtBWGkbHaBgcZzkMdgr/i5emtIrM7pauMrncHA
+XTcnj9lGJsORRqEFp11c3swGO8A74KmxPv58hmqPs7GC/1lOygOTXiAh/bEmzjwj
+4VjfRrKTDETC0X4j/jY3eLefY6kCc5fJ7uqwuPBhwbyTGAwZke5/vGKyyqFvmcS6
+pMGa9WR7lwj+66jfhlfaofkoDhVP7NTNIyXiXlturvN5FLsedh5ePd42HCp/RPiu
+7tloVklpjQ6ACFPvWcy21Si/oCS+NpERvVqq65Qcnh6b4npGlDxLViQeEmQgleDy
+qrIPfdqXK18u67UCAwEAAaOB2jCB1zAJBgNVHRMEAjAAMB0GA1UdDgQWBBT2PrfY
+tgczgomZNumPfn/iOTDWzDCBqgYDVR0jBIGiMIGfgBTvjN7SQBC057HlKmcj+L5e
+V+0plKF8pHoweDE1MDMGA1UECgwsSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBFeGFt
+cGxlIE9yZ2FuaXphdGlvbnMxHzAdBgNVBAMMFkNlcnRpZmljYXRlIGlzc3VlciBn
+dXkxHjAcBgkqhkiG9w0BCQEWD2NhQG1haWwuZXhhbXBsZYIJAJmt2W7CutHvMA0G
+CSqGSIb3DQEBCwUAA4IBAQByzcvGtzUZgP5SxajdH6zElBxpN8pZ024LwJukdtv/
+YIygVYgA6J7QIaQwTVmMSl0zFyc/KUd0NIe285F2Krk8oOODIbuekthILl5c7k7o
+4srp3qli8JJSDpCRFzGOqzjSpTCS47DchiNkY0TwvxAd8QZgSij6TIwRb9A6sy/T
+2ssY7rfQdz5bdr2kfjD2zVaTZSGGM92VtuxQ9eQgGVVexCroEvdD63VXJGX6cF4Q
+nZWFxXTZVRacjrMR+ZSRXbvYF7Rf7unhfJb9mUsW6FJ1GuFB96JU0Klnc3cQiz6y
+PlwquuzrXpckLW9MpoONShvAqw40OytGzwjxbJXonUgi
 -----END CERTIFICATE-----
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 06/11] key: Add keyring APIs
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (3 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 05/11] unit: New set of " Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 07/11] unit: Keyring tests Mat Martineau
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 5765 bytes --]

There are two types of keyrings: "simple" and "trusted asymmetric".

Simple keyrings do not validate keys as they are linked. Trusted
asymmetric keyrings have a "trust keyring" designated at allocation
time. Only RSA keys that are signed by an RSA key in the trust keyring
may be linked to a trusted asymmetric keyring.
---
 ell/key.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 ell/key.h |  15 +++++++++
 2 files changed, 116 insertions(+), 10 deletions(-)

diff --git a/ell/key.c b/ell/key.c
index b0afc2f..adeac04 100644
--- a/ell/key.c
+++ b/ell/key.c
@@ -44,13 +44,18 @@ struct keyctl_dh_params {
 };
 #endif
 
-static int32_t keyring_base;
+static int32_t internal_keyring;
 
 struct l_key {
 	int type;
 	int32_t serial;
 };
 
+struct l_keyring {
+	int type;
+	int32_t serial;
+};
+
 static const char * const key_type_names[] = {
 	[L_KEY_RAW] = "user",
 	[L_KEY_ASYMMETRIC] = "asymmetric",
@@ -77,6 +82,16 @@ static long kernel_revoke_key(int32_t serial)
 	return syscall(__NR_keyctl, KEYCTL_REVOKE, serial);
 }
 
+static long kernel_link_key(int32_t key_serial, int32_t ring_serial)
+{
+	return syscall(__NR_keyctl, KEYCTL_LINK, key_serial, ring_serial);
+}
+
+static long kernel_unlink_key(int32_t key_serial, int32_t ring_serial)
+{
+	return syscall(__NR_keyctl, KEYCTL_UNLINK, key_serial, ring_serial);
+}
+
 static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
 			      void *payload, size_t len)
 {
@@ -87,13 +102,13 @@ static long kernel_dh_compute(int32_t private, int32_t prime, int32_t base,
 	return syscall(__NR_keyctl, KEYCTL_DH_COMPUTE, &params, payload, len);
 }
 
-static bool setup_keyring_base(void)
+static bool setup_internal_keyring(void)
 {
-	keyring_base = kernel_add_key("keyring", "ell-keyring", 0, 0,
-					KEY_SPEC_THREAD_KEYRING);
+	internal_keyring = kernel_add_key("keyring", "ell-internal", NULL, 0,
+						KEY_SPEC_THREAD_KEYRING);
 
-	if (keyring_base <= 0) {
-		keyring_base = 0;
+	if (internal_keyring <= 0) {
+		internal_keyring = 0;
 		return false;
 	}
 
@@ -112,15 +127,14 @@ LIB_EXPORT struct l_key *l_key_new(enum l_key_type type, const void *payload,
 	if (unlikely((size_t)type >= L_ARRAY_SIZE(key_type_names)))
 		return NULL;
 
-	if (!keyring_base && !setup_keyring_base()) {
+	if (!internal_keyring && !setup_internal_keyring())
 		return NULL;
-	}
 
 	key = l_new(struct l_key, 1);
 	key->type = type;
-	description = l_strdup_printf("ell-%p", key);
+	description = l_strdup_printf("ell-key-%p", key);
 	key->serial = kernel_add_key(key_type_names[type], description, payload,
-					payload_length, keyring_base);
+					payload_length, internal_keyring);
 	l_free(description);
 
 	if (key->serial < 0) {
@@ -210,3 +224,80 @@ LIB_EXPORT bool l_key_compute_dh_secret(struct l_key *other_public,
 {
 	return compute_common(other_public, private, prime, payload, len);
 }
+
+LIB_EXPORT struct l_keyring *l_keyring_new(enum l_keyring_type type,
+						const struct l_keyring *trusted)
+{
+	struct l_keyring *keyring;
+	char *description;
+	char *payload = NULL;
+	size_t payload_length = 0;
+
+	if (!internal_keyring && !setup_internal_keyring())
+		return NULL;
+
+	if (type == L_KEYRING_TRUSTED_ASYM) {
+		if (!trusted)
+			return NULL;
+
+		payload = l_strdup_printf(
+			"restrict_type=asymmetric "
+			"restrict_by=signature_keyring "
+			"restrict_key=%d",
+			trusted->serial);
+		payload_length = strlen(payload);
+	} else if (type != L_KEYRING_SIMPLE) {
+		/* Unsupported type */
+		return NULL;
+	}
+
+	keyring = l_new(struct l_keyring, 1);
+	keyring->type = type;
+	description = l_strdup_printf("ell-keyring-%p", keyring);
+	keyring->serial = kernel_add_key("keyring", description, payload,
+						payload_length,
+						internal_keyring);
+	l_free(description);
+	l_free(payload);
+
+	if (keyring->serial < 0) {
+		l_free(keyring);
+		keyring = NULL;
+	}
+
+	return keyring;
+}
+
+LIB_EXPORT void l_keyring_free(struct l_keyring *keyring)
+{
+	if (unlikely(!keyring))
+		return;
+
+	kernel_revoke_key(keyring->serial);
+
+	l_free(keyring);
+}
+
+bool l_keyring_link(struct l_keyring *keyring, const struct l_key *key)
+{
+	long error;
+
+	if (unlikely(!keyring) || unlikely(!key))
+		return false;
+
+	error = kernel_link_key(key->serial, keyring->serial);
+
+	return error == 0;
+}
+
+bool l_keyring_unlink(struct l_keyring *keyring, const struct l_key *key)
+{
+	long error;
+
+	if (unlikely(!keyring) || unlikely(!key))
+		return false;
+
+	error = kernel_unlink_key(key->serial, keyring->serial);
+
+	return error == 0;
+}
diff --git a/ell/key.h b/ell/key.h
index 7d48c4d..5d981f1 100644
--- a/ell/key.h
+++ b/ell/key.h
@@ -31,12 +31,18 @@ extern "C" {
 #include <stdbool.h>
 
 struct l_key;
+struct l_keyring;
 
 enum l_key_type {
 	L_KEY_RAW = 0,
 	L_KEY_ASYMMETRIC
 };
 
+enum l_keyring_type {
+	L_KEYRING_SIMPLE = 0,
+	L_KEYRING_TRUSTED_ASYM
+};
+
 struct l_key *l_key_new(enum l_key_type type, const void *payload,
 			size_t payload_length);
 
@@ -54,6 +60,15 @@ bool l_key_compute_dh_public(struct l_key *generator, struct l_key *private,
 bool l_key_compute_dh_secret(struct l_key *other_public, struct l_key *private,
 			     struct l_key *prime, void *payload, size_t *len);
 
+struct l_keyring *l_keyring_new(enum l_keyring_type type,
+				const struct l_keyring *trust);
+
+void l_keyring_free(struct l_keyring *keyring);
+
+bool l_keyring_link(struct l_keyring *keyring, const struct l_key *key);
+
+bool l_keyring_unlink(struct l_keyring *keyring, const struct l_key *key);
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 07/11] unit: Keyring tests
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (4 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 06/11] key: Add keyring APIs Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 08/11] cipher: Update for current kernel akcipher interface Mat Martineau
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2372 bytes --]

---
 unit/test-key.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 71 insertions(+)

diff --git a/unit/test-key.c b/unit/test-key.c
index 53232da..df1e13b 100644
--- a/unit/test-key.c
+++ b/unit/test-key.c
@@ -332,6 +332,74 @@ static void test_dh(const void *data)
 	l_free(buffer);
 }
 
+static void test_simple_keyring(const void *data)
+{
+	struct l_keyring *ring;
+	struct l_key *key1;
+	struct l_key *key2;
+	bool success;
+
+	ring = l_keyring_new(L_KEYRING_SIMPLE, NULL);
+	assert(ring);
+
+	key1 = l_key_new(L_KEY_RAW, "1", 1);
+	key2 = l_key_new(L_KEY_RAW, "2", 1);
+
+	success = l_keyring_link(ring, key1);
+	assert(success);
+	success = l_keyring_link(ring, key2);
+	assert(success);
+
+	l_key_free(key1);
+	success = l_keyring_unlink(ring, key2);
+	assert(success);
+	l_keyring_free(ring);
+	l_key_free(key2);
+}
+
+static void test_trusted_keyring(const void *data)
+{
+	struct l_keyring *ring;
+	struct l_keyring *trust;
+	uint8_t *cacert;
+	size_t cacertlen;
+	uint8_t *cert;
+	size_t certlen;
+	struct l_key *cakey;
+	struct l_key *key;
+	bool success;
+
+	cacert = l_pem_load_certificate(TESTDATADIR "/cert-ca.pem", &cacertlen);
+	assert(cacert);
+	cert = l_pem_load_certificate(TESTDATADIR "/cert-server.pem",
+					&certlen);
+	assert(cert);
+
+	cakey = l_key_new(L_KEY_ASYMMETRIC, cacert, cacertlen);
+	assert(cakey);
+	key = l_key_new(L_KEY_ASYMMETRIC, cert, certlen);
+	assert(key);
+
+	trust = l_keyring_new(L_KEYRING_SIMPLE, NULL);
+	assert(trust);
+	ring = l_keyring_new(L_KEYRING_TRUSTED_ASYM, trust);
+	assert(ring);
+
+	success = l_keyring_link(ring, key);
+	assert(!success);
+	success = l_keyring_link(trust, cakey);
+	assert(success);
+	success = l_keyring_link(ring, key);
+	assert(success);
+
+	l_keyring_free(trust);
+	l_keyring_free(ring);
+	l_key_free(cakey);
+	l_key_free(key);
+	l_free(cacert);
+	l_free(cert);
+}
+
 int main(int argc, char *argv[])
 {
 	l_test_init(&argc, &argv);
@@ -343,5 +411,8 @@ int main(int argc, char *argv[])
 	l_test_add("Diffie-Hellman 1", test_dh, &dh_valid1);
 	l_test_add("Diffie-Hellman 2", test_dh, &dh_valid2);
 
+	l_test_add("simple keyring", test_simple_keyring, NULL);
+	l_test_add("trusted keyring", test_trusted_keyring, NULL);
+
 	return l_test_run();
 }
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (5 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 07/11] unit: Keyring tests Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 23:55   ` Denis Kenzior
  2016-06-07 17:51   ` Denis Kenzior
  2016-06-06 20:54 ` [PATCH 09/11] unit: Update for akcipher changes Mat Martineau
                   ` (3 subsequent siblings)
  10 siblings, 2 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 16238 bytes --]

There are some significant differences in the current iteration of
kernel AF_ALG akcipher support:
 * Kernel handles padding
 * Kernel accepts DER-encoded certs as-is (no need to extract values)
 * Must explicitly set private or public key
---
 ell/cipher-private.h |   3 -
 ell/cipher.c         | 300 +++++++++++++--------------------------------------
 ell/tls.c            |  43 +++-----
 3 files changed, 85 insertions(+), 261 deletions(-)

diff --git a/ell/cipher-private.h b/ell/cipher-private.h
index 7d115f6..77ddd06 100644
--- a/ell/cipher-private.h
+++ b/ell/cipher-private.h
@@ -20,9 +20,6 @@
  *
  */
 
-uint8_t *extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
-			size_t *out_len);
-
 #define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | (tag))
 
 #define ASN1_CLASS_UNIVERSAL	0
diff --git a/ell/cipher.c b/ell/cipher.c
index 671071b..04bbd82 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -78,6 +78,10 @@ struct af_alg_iv {
 #define SOL_ALG 279
 #endif
 
+#ifndef ALG_SET_PUBKEY
+#define ALG_SET_PUBKEY	6
+#endif
+
 #define is_valid_type(type)  ((type) <= L_CIPHER_DES3_EDE_CBC)
 
 struct l_cipher {
@@ -87,10 +91,11 @@ struct l_cipher {
 };
 
 static int create_alg(const char *alg_type, const char *alg_name,
-				const void *key, size_t key_length)
+			const void *key, size_t key_length, bool public)
 {
 	struct sockaddr_alg salg;
 	int sk;
+	int keyopt;
 	int ret;
 
 	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
@@ -107,7 +112,8 @@ static int create_alg(const char *alg_type, const char *alg_name,
 		return -1;
 	}
 
-	if (setsockopt(sk, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
+	keyopt = public ? ALG_SET_PUBKEY : ALG_SET_KEY;
+	if (setsockopt(sk, SOL_ALG, keyopt, key, key_length) < 0) {
 		close(sk);
 		return -1;
 	}
@@ -149,11 +155,13 @@ LIB_EXPORT struct l_cipher *l_cipher_new(enum l_cipher_type type,
 		break;
 	}
 
-	cipher->encrypt_sk = create_alg("skcipher", alg_name, key, key_length);
+	cipher->encrypt_sk = create_alg("skcipher", alg_name, key, key_length,
+					false);
 	if (cipher->encrypt_sk < 0)
 		goto error_free;
 
-	cipher->decrypt_sk = create_alg("skcipher", alg_name, key, key_length);
+	cipher->decrypt_sk = create_alg("skcipher", alg_name, key, key_length,
+					false);
 	if (cipher->decrypt_sk < 0)
 		goto error_close;
 
@@ -178,7 +186,8 @@ LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
 }
 
 static bool operate_cipher(int sk, __u32 operation,
-				const void *in, void *out, size_t len)
+				const void *in, void *out, size_t len_in,
+				size_t len_out)
 {
 	char c_msg_buf[CMSG_SPACE(sizeof(operation))];
 	struct msghdr msg;
@@ -198,7 +207,7 @@ static bool operate_cipher(int sk, __u32 operation,
 	memcpy(CMSG_DATA(c_msg), &operation, sizeof(operation));
 
 	iov.iov_base = (void *) in;
-	iov.iov_len = len;
+	iov.iov_len = len_in;
 
 	msg.msg_iov = &iov;
 	msg.msg_iovlen = 1;
@@ -206,7 +215,7 @@ static bool operate_cipher(int sk, __u32 operation,
 	if (sendmsg(sk, &msg, 0) < 0)
 		return false;
 
-	if (read(sk, out, len) < 0)
+	if (read(sk, out, len_out) < 0)
 		return false;
 
 	return true;
@@ -221,7 +230,8 @@ LIB_EXPORT bool l_cipher_encrypt(struct l_cipher *cipher,
 	if (unlikely(!in) || unlikely(!out))
 		return false;
 
-	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, out, len);
+	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, out, len,
+				len);
 }
 
 LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
@@ -233,7 +243,8 @@ LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
 	if (unlikely(!in) || unlikely(!out))
 		return false;
 
-	return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, len);
+	return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, len,
+				len);
 }
 
 LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
@@ -275,6 +286,7 @@ LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
 struct l_asymmetric_cipher {
 	struct l_cipher cipher;
 	int key_size;
+	bool public_key;
 };
 
 static inline int parse_asn1_definite_length(const uint8_t **buf,
@@ -334,20 +346,31 @@ static bool parse_rsa_key(struct l_asymmetric_cipher *cipher, const void *key,
 	 * and cache the size of the modulus n for later use.
 	 * (RFC3279)
 	 */
+	size_t seq_length;
 	size_t n_length;
+	uint8_t *seq;
 	uint8_t *der;
 	uint8_t tag;
+	bool pubkey = true;
 
 	if (key_length < 8)
 		return false;
 
 	/* Unpack the outer SEQUENCE */
-	der = der_find_elem((uint8_t *) key, key_length, 0, &tag, &n_length);
-	if (!der || tag != ASN1_ID_SEQUENCE)
+	seq = der_find_elem((uint8_t *) key, key_length, 0, &tag, &seq_length);
+	if (!seq || tag != ASN1_ID_SEQUENCE)
 		return false;
 
-	/* Take first INTEGER as the modulus */
-	der = der_find_elem(der, n_length, 0, &tag, &n_length);
+	/* First INTEGER may be a 1-byte version (for private key) or
+	 * the modulus (public key)
+	 */
+	der = der_find_elem(seq, seq_length, 0, &tag, &n_length);
+	if (der && tag == ASN1_ID_INTEGER && n_length == 1) {
+		/* Found version number, implies this is a private key. */
+		der = der_find_elem(seq, seq_length, 1, &tag, &n_length);
+		pubkey = false;
+	}
+
 	if (!der || tag != ASN1_ID_INTEGER || n_length < 4)
 		return false;
 
@@ -358,95 +381,11 @@ static bool parse_rsa_key(struct l_asymmetric_cipher *cipher, const void *key,
 	}
 
 	cipher->key_size = n_length;
+	cipher->public_key = pubkey;
 
 	return true;
 }
 
-static void write_asn1_definite_length(uint8_t **buf, size_t len)
-{
-	int n;
-
-	if (len < 0x80) {
-		*(*buf)++ = len;
-
-		return;
-	}
-
-	for (n = 1; len >> (n * 8); n++);
-	*(*buf)++ = 0x80 | n;
-
-	while (n--)
-		*(*buf)++ = len >> (n * 8);
-}
-
-/*
- * Extract a ASN1 RsaKey-formatted public+private key structure in the
- * form used in the kernel.  It is simpler than the PKCS#1 form as it only
- * contains the N, E and D integers and also correctly parses as a PKCS#1
- * RSAPublicKey.
- */
-uint8_t *extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
-			size_t *out_len)
-{
-	uint8_t *key, *ptr, *ver, *n, *e, *d;
-	uint8_t tag;
-	size_t ver_len, n_len, e_len, d_len;
-	int pos;
-
-	/* Unpack the outer SEQUENCE */
-	pkcs1_key = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag,
-					&pkcs1_key_len);
-	if (!pkcs1_key || tag != ASN1_ID_SEQUENCE)
-		return NULL;
-
-	/* Check if the version element if present */
-	ver = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag, &ver_len);
-	if (!ver || tag != ASN1_ID_INTEGER)
-		return NULL;
-
-	pos = (ver_len == 1 && ver[0] == 0x00) ? 1 : 0;
-
-	n = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 0, &tag, &n_len);
-	if (!n || tag != ASN1_ID_INTEGER)
-		return NULL;
-
-	e = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 1, &tag, &e_len);
-	if (!e || tag != ASN1_ID_INTEGER)
-		return NULL;
-
-	d = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 2, &tag, &d_len);
-	if (!d || tag != ASN1_ID_INTEGER)
-		return NULL;
-
-	/* New SEQUENCE length including tags and lengths */
-	*out_len = 1 + (n_len >= 0x80 ? n_len >= 0x100 ? 3 : 2 : 1) + n_len +
-		1 + (e_len >= 0x80 ? e_len >= 0x100 ? 3 : 2 : 1) + e_len +
-		1 + (d_len >= 0x80 ? d_len >= 0x100 ? 3 : 2 : 1) + d_len;
-	ptr = key = l_malloc(*out_len +
-		1 + (*out_len >= 0x80 ? *out_len >= 0x100 ? 3 : 2 : 1));
-
-	*ptr++ = ASN1_ID_SEQUENCE;
-	write_asn1_definite_length(&ptr, *out_len);
-
-	*ptr++ = ASN1_ID_INTEGER;
-	write_asn1_definite_length(&ptr, n_len);
-	memcpy(ptr, n, n_len);
-	ptr += n_len;
-
-	*ptr++ = ASN1_ID_INTEGER;
-	write_asn1_definite_length(&ptr, e_len);
-	memcpy(ptr, e, e_len);
-	ptr += e_len;
-
-	*ptr++ = ASN1_ID_INTEGER;
-	write_asn1_definite_length(&ptr, d_len);
-	memcpy(ptr, d, d_len);
-	ptr += d_len;
-
-	*out_len = ptr - key;
-	return key;
-}
-
 LIB_EXPORT struct l_asymmetric_cipher *l_asymmetric_cipher_new(
 					enum l_asymmetric_cipher_type type,
 					const void *key, size_t key_length)
@@ -473,14 +412,18 @@ LIB_EXPORT struct l_asymmetric_cipher *l_asymmetric_cipher_new(
 	}
 
 	cipher->cipher.encrypt_sk = create_alg("akcipher", alg_name,
-						key, key_length);
+						key, key_length,
+						cipher->public_key);
 	if (cipher->cipher.encrypt_sk < 0)
 		goto error_free;
 
-	cipher->cipher.decrypt_sk = create_alg("akcipher", alg_name,
-						key, key_length);
-	if (cipher->cipher.decrypt_sk < 0)
-		goto error_close;
+	if (!cipher->public_key) {
+		cipher->cipher.decrypt_sk = create_alg("akcipher", alg_name,
+							key, key_length,
+							cipher->public_key);
+		if (cipher->cipher.decrypt_sk < 0)
+			goto error_close;
+	}
 
 	return cipher;
 
@@ -508,151 +451,52 @@ LIB_EXPORT int l_asymmetric_cipher_get_key_size(
 	return cipher->key_size;
 }
 
-static void getrandom_nonzero(uint8_t *buf, int len)
-{
-	while (len--) {
-		l_getrandom(buf, 1);
-		while (buf[0] == 0)
-			l_getrandom(buf, 1);
-
-		buf++;
-	}
-}
-
-LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *cipher,
+LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *acipher,
 					const void *in, void *out,
 					size_t len_in, size_t len_out)
 {
-	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
-		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
-		uint8_t buf[cipher->key_size];
-		int ps_len = cipher->key_size - len_in - 3;
-
-		if (len_in > (size_t) cipher->key_size - 11)
-			return false;
-		if (len_out != (size_t) cipher->key_size)
-			return false;
-
-		buf[0] = 0x00;
-		buf[1] = 0x02;
-		getrandom_nonzero(buf + 2, ps_len);
-		buf[ps_len + 2] = 0x00;
-		memcpy(buf + ps_len + 3, in, len_in);
-
-		if (!l_cipher_encrypt(&cipher->cipher, buf, out,
-					cipher->key_size))
-			return false;
-	}
+	if (unlikely(!acipher))
+		return false;
 
-	return true;
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	return operate_cipher(acipher->cipher.encrypt_sk, ALG_OP_ENCRYPT,
+				in, out, len_in, len_out);
 }
 
-LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *cipher,
+LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *acipher,
 					const void *in, void *out,
 					size_t len_in, size_t len_out)
 {
-	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
-		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
-		uint8_t buf[cipher->key_size];
-		int pos;
-
-		if (len_in != (size_t) cipher->key_size)
-			return false;
-
-		if (!l_cipher_decrypt(&cipher->cipher, in, buf,
-					cipher->key_size))
-			return false;
-
-		if (buf[0] != 0x00)
-			return false;
-		if (buf[1] != 0x02)
-			return false;
-
-		for (pos = 2; pos < cipher->key_size; pos++)
-			if (buf[pos] == 0)
-				break;
-		if (pos < 10 || pos == cipher->key_size)
-			return false;
-
-		pos++;
-		if (len_out != (size_t) cipher->key_size - pos)
-			return false;
-
-		memcpy(out, buf + pos, cipher->key_size - pos);
-	}
+	if (unlikely(!acipher))
+		return false;
 
-	return true;
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	return operate_cipher(acipher->cipher.decrypt_sk, ALG_OP_DECRYPT,
+				in, out, len_in, len_out);
 }
 
 LIB_EXPORT bool l_asymmetric_cipher_sign(struct l_asymmetric_cipher *cipher,
 					const void *in, void *out,
 					size_t len_in, size_t len_out)
 {
-	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
-		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
-		uint8_t buf[cipher->key_size];
-		int ps_len = cipher->key_size - len_in - 3;
-
-		if (len_in > (size_t) cipher->key_size - 11)
-			return false;
-		if (len_out != (size_t) cipher->key_size)
-			return false;
-
-		buf[0] = 0x00;
-		buf[1] = 0x01;
-		memset(buf + 2, 0xff, ps_len);
-		buf[ps_len + 2] = 0x00;
-		memcpy(buf + ps_len + 3, in, len_in);
-
-		/*
-		 * The RSA signing operation uses the same primitive as
-		 * decryption so just call decrypt for now.
-		 */
-		if (!l_cipher_decrypt(&cipher->cipher, buf, out,
-					cipher->key_size))
-			return false;
-	}
-
-	return true;
+	/*
+	 * The RSA signing operation uses the same primitive as
+	 * decryption so just call decrypt for now.
+	 */
+	return l_asymmetric_cipher_decrypt(cipher, in, out, len_in, len_out);
 }
 
 LIB_EXPORT bool l_asymmetric_cipher_verify(struct l_asymmetric_cipher *cipher,
 					const void *in, void *out,
 					size_t len_in, size_t len_out)
 {
-	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
-		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
-		uint8_t buf[cipher->key_size];
-		int pos;
-
-		if (len_in != (size_t) cipher->key_size)
-			return false;
-
-		/*
-		 * The RSA verify operation uses the same primitive as
-		 * encryption so just call encrypt.
-		 */
-		if (!l_cipher_encrypt(&cipher->cipher, in, buf,
-					cipher->key_size))
-			return false;
-
-		if (buf[0] != 0x00)
-			return false;
-		if (buf[1] != 0x01)
-			return false;
-
-		for (pos = 2; pos < cipher->key_size; pos++)
-			if (buf[pos] != 0xff)
-				break;
-		if (pos < 10 || pos == cipher->key_size || buf[pos] != 0)
-			return false;
-
-		pos++;
-		if (len_out != (size_t) cipher->key_size - pos)
-			return false;
-
-		memcpy(out, buf + pos, cipher->key_size - pos);
-	}
-
-	return true;
+	/*
+	 * The RSA verify operation uses the same primitive as
+	 * encryption so just call encrypt.
+	 */
+	return l_asymmetric_cipher_encrypt(cipher, in, out, len_in, len_out);
 }
diff --git a/ell/tls.c b/ell/tls.c
index e47e8bf..6896a05 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -918,8 +918,8 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
 				tls_get_hash_t get_hash)
 {
 	struct l_asymmetric_cipher *rsa_privkey;
-	uint8_t *privkey, *privkey_short;
-	size_t key_size, short_size;
+	uint8_t *privkey;
+	size_t key_size;
 	bool result;
 	const struct tls_hash_algorithm *hash_type;
 	uint8_t hash[HANDSHAKE_HASH_MAX_SIZE];
@@ -943,19 +943,9 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
 		return false;
 	}
 
-	privkey_short = extract_rsakey(privkey, key_size, &short_size);
-	tls_free_key(privkey, key_size);
-
-	if (!privkey_short) {
-		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
-				TLS_ALERT_BAD_CERT);
-
-		return false;
-	}
-
 	rsa_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
-						privkey_short, short_size);
-	tls_free_key(privkey_short, short_size);
+						privkey, key_size);
+	tls_free_key(privkey, key_size);
 
 	if (!rsa_privkey) {
 		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
@@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t len,
 		 */
 	}
 
-	digest_info = alloca(expected_len);
+	if (expected_len > key_size)
+		goto err_free_rsa;
+
+	digest_info = alloca(key_size);
 
 	result = l_asymmetric_cipher_verify(rsa_client_pubkey, in + 4,
 						digest_info,
-						key_size, expected_len);
+						key_size, key_size);
 
 	l_asymmetric_cipher_free(rsa_client_pubkey);
 
@@ -1741,8 +1734,8 @@ static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
 {
 	uint8_t pre_master_secret[48], random_secret[46];
 	struct l_asymmetric_cipher *rsa_server_privkey;
-	uint8_t *privkey, *privkey_short;
-	size_t key_size, short_size;
+	uint8_t *privkey;
+	size_t key_size;
 	bool result;
 
 	if (!tls->priv_key_path) {
@@ -1762,19 +1755,9 @@ static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
 		return;
 	}
 
-	privkey_short = extract_rsakey(privkey, key_size, &short_size);
-	tls_free_key(privkey, key_size);
-
-	if (!privkey_short) {
-		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
-				TLS_ALERT_BAD_CERT);
-
-		return;
-	}
-
 	rsa_server_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
-						privkey_short, short_size);
-	tls_free_key(privkey_short, short_size);
+							privkey, key_size);
+	tls_free_key(privkey, key_size);
 
 	if (!rsa_server_privkey) {
 		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 09/11] unit: Update for akcipher changes
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (6 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 08/11] cipher: Update for current kernel akcipher interface Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 10/11] cipher: Return result length from asymmetric cipher operations Mat Martineau
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 9241 bytes --]

New private key, and no need to extract key elements.
---
 unit/test-cipher.c | 130 +++++++++++++++++++++++------------------------------
 1 file changed, 55 insertions(+), 75 deletions(-)

diff --git a/unit/test-cipher.c b/unit/test-cipher.c
index 3dc2fe0..2527dcc 100644
--- a/unit/test-cipher.c
+++ b/unit/test-cipher.c
@@ -124,96 +124,76 @@ static void test_arc4(const void *data)
 }
 
 /*
- * openssl genrsa 1024 | openssl rsa -outform DER | \
- *	hexdump -v -e '"0x" 1/1 "%02x" ", "'
+ * openssl genrsa 1024 | openssl rsa -outform DER | xxd -i
  */
 static uint8_t rsa_priv_key[] = {
-	0x30, 0x82, 0x02, 0x5c, /* SEQUENCE */
-	0x02, 0x01, /* INTEGER - version */
-	0x00,
-	0x02, 0x81, 0x81, /* INTEGER - n */
-	0x00, 0xbe, 0x8c, 0xe7, 0x6c, 0x7d, 0x97, 0xbd, 0x63, 0xf6, 0x00, 0x65,
-	0x34, 0x23, 0xd9, 0xc6, 0xce, 0x6d, 0x1b, 0x30, 0x8f, 0xfa, 0x9b, 0x8e,
-	0xbe, 0x97, 0x01, 0x10, 0x5b, 0x49, 0x7c, 0xba, 0xd5, 0x47, 0x5e, 0xb0,
-	0x62, 0x24, 0xd9, 0xb0, 0xe2, 0x35, 0x5b, 0x05, 0xeb, 0x0a, 0x69, 0xc9,
-	0x5c, 0x02, 0x6d, 0xf2, 0x89, 0x6d, 0xab, 0xaa, 0x43, 0x53, 0x52, 0xaa,
-	0xed, 0xc9, 0xb6, 0x98, 0x17, 0x8a, 0x38, 0x9a, 0x80, 0x5b, 0xd1, 0x70,
-	0xc7, 0xc9, 0x16, 0x1f, 0x34, 0xb3, 0x27, 0x40, 0xa2, 0x39, 0xbe, 0xf8,
-	0x01, 0xfa, 0x9e, 0x04, 0x9f, 0x58, 0xc1, 0xa1, 0x19, 0x78, 0xcf, 0xfe,
-	0x9c, 0x76, 0x43, 0xba, 0x69, 0x05, 0x67, 0x9a, 0xfc, 0xc4, 0x56, 0xbb,
-	0xc1, 0x7f, 0xdb, 0xf0, 0xb9, 0x31, 0x2c, 0x4f, 0xc2, 0xd9, 0x42, 0xf6,
-	0x3d, 0x1b, 0x48, 0x31, 0x88, 0xc2, 0xb5, 0xb9, 0xa5,
-	0x02, 0x03, /* INTEGER - e */
-	0x01, 0x00, 0x01,
-	0x02, 0x81, 0x80, /* INTEGER - d */
-	0x0b, 0x34, 0xa2, 0x0f, 0x61, 0x3b, 0x61, 0x29, 0xd5, 0xb7, 0xa4, 0x3b,
-	0xf2, 0xb7, 0xc5, 0xd7, 0x31, 0xd7, 0x5d, 0x7d, 0xba, 0x11, 0x17, 0xcd,
-	0xe1, 0x77, 0x70, 0x8c, 0xcd, 0xbf, 0x86, 0x05, 0x30, 0xd3, 0x42, 0xb0,
-	0x22, 0xd6, 0xa2, 0x6e, 0x4b, 0x10, 0xf5, 0x42, 0x23, 0x34, 0xa1, 0x60,
-	0xc5, 0xcb, 0xcd, 0x6d, 0x83, 0x83, 0x8a, 0xd9, 0xb6, 0xb6, 0xaf, 0xd2,
-	0x98, 0x00, 0x22, 0xe5, 0x75, 0x67, 0xbe, 0x0b, 0x95, 0xe7, 0x76, 0xee,
-	0x22, 0x03, 0xdd, 0x49, 0x02, 0x86, 0xd7, 0x2b, 0x96, 0xee, 0xb1, 0x1e,
-	0x49, 0x02, 0xdf, 0xa9, 0x2e, 0x0f, 0x71, 0x33, 0xb5, 0xc6, 0x37, 0xb5,
-	0x6b, 0x58, 0xa1, 0xbb, 0x1c, 0xb9, 0xa2, 0x33, 0x70, 0x01, 0xca, 0xd4,
-	0xae, 0x96, 0xc3, 0x7d, 0x36, 0xc2, 0xe7, 0x50, 0x33, 0x17, 0xcc, 0xdc,
-	0x28, 0x7c, 0x7b, 0xdf, 0x25, 0x06, 0x57, 0xa9,
-	0x02, 0x41, /* INTEGER - p */
-	0x00, 0xf1, 0xec, 0x4f, 0xdf, 0xb7, 0x05, 0x2e, 0xdd, 0x1c, 0x85, 0x9d,
-	0x99, 0xb7, 0x60, 0x8c, 0x9b, 0x47, 0x1c, 0x04, 0x2f, 0x6f, 0x8a, 0xd5,
-	0x89, 0x1c, 0x2e, 0xe2, 0x0d, 0x68, 0x9c, 0xf6, 0xb0, 0x09, 0x32, 0x70,
-	0x06, 0x9f, 0x52, 0x7e, 0xc5, 0x46, 0x93, 0x60, 0x57, 0x77, 0xa8, 0xd3,
-	0x92, 0xbb, 0x24, 0x9c, 0x24, 0x35, 0x14, 0x99, 0x62, 0xe2, 0xce, 0xa2,
-	0x9b, 0x62, 0xd3, 0xe0, 0x0f,
-	0x02, 0x41, /* INTEGER - q */
-	0x00, 0xc9, 0xa3, 0x58, 0x17, 0x03, 0xfb, 0x19, 0x06, 0xa4, 0x75, 0xfb,
-	0xa2, 0xb3, 0x84, 0x2a, 0x7f, 0xf7, 0x66, 0x80, 0xb5, 0xd6, 0xda, 0xcf,
-	0xb2, 0x9e, 0x4f, 0x0a, 0xd3, 0xcd, 0xa5, 0x94, 0xc4, 0x80, 0x53, 0xc6,
-	0xbf, 0x7e, 0xe0, 0x2c, 0xc0, 0x71, 0xdb, 0x9c, 0xe0, 0x92, 0x66, 0x41,
-	0x6b, 0x64, 0x9e, 0x7a, 0xf3, 0xe7, 0x45, 0x15, 0x3f, 0xe4, 0xbc, 0xc1,
-	0x91, 0x40, 0x2a, 0x57, 0x0b,
-	0x02, 0x41, /* INTEGER - d mod (p - 1) */
-	0x00, 0x88, 0x9f, 0x4f, 0x00, 0x65, 0x68, 0x9c, 0xed, 0xac, 0x14, 0xdd,
-	0x4b, 0x19, 0x1f, 0x82, 0x68, 0x92, 0xc1, 0x04, 0xb0, 0x11, 0x4b, 0x13,
-	0x8a, 0xaa, 0x0a, 0xe4, 0x08, 0x74, 0x82, 0xe8, 0x61, 0xc3, 0xdf, 0xe3,
-	0x1a, 0x2a, 0x51, 0xb9, 0x5c, 0x09, 0x9e, 0x63, 0x33, 0x22, 0x55, 0x8a,
-	0x9e, 0x7b, 0xe7, 0x91, 0xf2, 0x74, 0xb3, 0x9c, 0x68, 0x16, 0xf4, 0x61,
-	0x2a, 0x65, 0xa6, 0x88, 0x0b,
-	0x02, 0x40, /* INTEGER - d mod (q - 1) */
-	0x56, 0x3c, 0xab, 0x07, 0x24, 0xe7, 0xb6, 0x5b, 0x55, 0xe9, 0x33, 0xd6,
-	0xf1, 0x09, 0xfc, 0x97, 0x40, 0x3b, 0x31, 0x9f, 0x13, 0xa5, 0xff, 0xa0,
-	0x77, 0xfe, 0x7c, 0x35, 0xfb, 0xc4, 0xee, 0x6c, 0x60, 0x29, 0xf4, 0x5d,
-	0xa0, 0x28, 0xc6, 0x5b, 0x04, 0x17, 0x15, 0xf0, 0x22, 0x0c, 0xe3, 0xbb,
-	0xc7, 0x8b, 0xd4, 0x30, 0x0e, 0x60, 0x48, 0x67, 0x4c, 0x2f, 0xc2, 0x65,
-	0x99, 0xd8, 0xc1, 0xe3,
-	0x02, 0x40, /* INTEGER - inv q mod p */
-	0x12, 0x89, 0x47, 0x76, 0xb6, 0xbb, 0x18, 0x64, 0xc3, 0x19, 0xe7, 0xa9,
-	0x93, 0xce, 0xec, 0xd6, 0x4b, 0xaa, 0xad, 0x46, 0x4f, 0x24, 0x0d, 0xf3,
-	0xbf, 0xc2, 0x7c, 0x95, 0x3e, 0xc9, 0x27, 0x8a, 0x4b, 0xbc, 0x9e, 0x56,
-	0x2a, 0x8c, 0x07, 0x5f, 0xb6, 0x07, 0x21, 0xb7, 0xc9, 0xae, 0x8c, 0x58,
-	0x04, 0x65, 0x02, 0xa2, 0x08, 0x03, 0x40, 0xf3, 0x71, 0x8c, 0x89, 0xf7,
-	0xaa, 0xb0, 0x6a, 0x75,
+	0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xe1,
+	0xec, 0x78, 0x3c, 0x5f, 0x62, 0x74, 0x1e, 0x6d, 0x1d, 0x44, 0xac, 0x40,
+	0xb3, 0xec, 0x01, 0x96, 0x01, 0x8a, 0xfe, 0xcf, 0x5d, 0xc5, 0xe6, 0x0c,
+	0x36, 0x03, 0x2c, 0x4e, 0x84, 0x8f, 0x51, 0xf3, 0xc5, 0x32, 0x4f, 0xc4,
+	0x73, 0x22, 0x92, 0x30, 0x7c, 0x75, 0xd7, 0x4b, 0xae, 0xc6, 0xd0, 0x59,
+	0x6b, 0xd8, 0x46, 0x79, 0xbc, 0x6a, 0x6e, 0xde, 0x27, 0x11, 0x2f, 0xde,
+	0x84, 0xe3, 0x64, 0x84, 0x07, 0x82, 0x83, 0xbf, 0x90, 0xf5, 0x80, 0x6f,
+	0x63, 0x3a, 0xd1, 0x74, 0xd5, 0x6d, 0x2f, 0xde, 0xdc, 0xea, 0xab, 0xe5,
+	0x20, 0x7d, 0x26, 0x3e, 0x20, 0x99, 0x97, 0x41, 0x47, 0x81, 0x04, 0x7e,
+	0x53, 0x5c, 0xb2, 0xa9, 0xe0, 0x3d, 0x72, 0x37, 0x85, 0xcc, 0x5c, 0xda,
+	0x04, 0x96, 0xfa, 0x02, 0xc2, 0x23, 0x8b, 0x20, 0x5d, 0xe1, 0x2a, 0x69,
+	0xec, 0xcd, 0xce, 0x85, 0xc2, 0xf5, 0x49, 0x02, 0x03, 0x01, 0x00, 0x01,
+	0x02, 0x81, 0x81, 0x00, 0xa5, 0x31, 0x72, 0xf9, 0x32, 0x05, 0x9b, 0x42,
+	0x64, 0x26, 0x72, 0x80, 0x41, 0x0f, 0x4e, 0x12, 0x1a, 0xcd, 0x26, 0x05,
+	0x0b, 0x3b, 0x55, 0xe8, 0xd0, 0x24, 0xee, 0x4d, 0x07, 0x5c, 0x86, 0x2f,
+	0x36, 0x3f, 0x8a, 0x7a, 0x28, 0xfa, 0xc6, 0xdc, 0x7d, 0xf7, 0x83, 0x72,
+	0xd9, 0x34, 0x02, 0xcb, 0x75, 0x97, 0x15, 0x9c, 0xf2, 0x86, 0x82, 0x8c,
+	0x6e, 0x83, 0xc2, 0x5d, 0x6e, 0x27, 0x5c, 0xdc, 0x52, 0xb8, 0x8d, 0xa8,
+	0x0d, 0x09, 0xcf, 0x69, 0xae, 0x61, 0x0e, 0xcb, 0x6a, 0x76, 0xac, 0xdd,
+	0x85, 0xda, 0x9c, 0xac, 0x2b, 0xf0, 0xf6, 0x2e, 0x2e, 0x4d, 0x9b, 0xc7,
+	0x67, 0xc2, 0xfa, 0x7b, 0x0e, 0x68, 0xf7, 0x1e, 0x03, 0x28, 0xea, 0x0e,
+	0x9a, 0xd6, 0xc3, 0x28, 0x3d, 0xde, 0x11, 0x26, 0xb1, 0x95, 0xf6, 0x10,
+	0x2f, 0x81, 0xa5, 0x60, 0x2c, 0x4f, 0x37, 0x5c, 0x2a, 0xd2, 0x30, 0x01,
+	0x02, 0x41, 0x00, 0xf2, 0x80, 0xa2, 0x57, 0x5c, 0xe0, 0x41, 0x82, 0x00,
+	0xac, 0x0b, 0xbd, 0xad, 0x98, 0x04, 0x33, 0x49, 0x64, 0x0b, 0x94, 0x94,
+	0xc3, 0xd7, 0xd9, 0xfe, 0x1f, 0xa3, 0xd1, 0x83, 0x42, 0x3a, 0x2d, 0xaf,
+	0xc5, 0x4c, 0xa4, 0x1b, 0xe4, 0x1c, 0x9c, 0x17, 0x8e, 0x28, 0xe9, 0xa5,
+	0xd4, 0xbd, 0x9a, 0xce, 0x6e, 0x33, 0xb4, 0xaf, 0xce, 0x13, 0xd2, 0xab,
+	0x0c, 0x4b, 0x34, 0x0d, 0x03, 0x87, 0xa1, 0x02, 0x41, 0x00, 0xee, 0x7f,
+	0x9b, 0xb4, 0x3c, 0x21, 0x76, 0xf2, 0x0c, 0xdf, 0xb6, 0xea, 0xc9, 0x31,
+	0xd4, 0xeb, 0x8f, 0x46, 0x41, 0x9b, 0xc1, 0x60, 0x4f, 0x50, 0x54, 0x32,
+	0xd2, 0xf4, 0xfd, 0xd0, 0xc8, 0x58, 0x6d, 0x17, 0x4e, 0xac, 0x5f, 0x9e,
+	0xb7, 0xd4, 0xfc, 0xce, 0xe0, 0x92, 0x0e, 0x1d, 0xd1, 0xa7, 0x54, 0xd3,
+	0x98, 0xca, 0x5b, 0x9c, 0x41, 0x68, 0xbf, 0x0d, 0x1b, 0xe2, 0xdb, 0xa6,
+	0xec, 0xa9, 0x02, 0x40, 0x0b, 0xc1, 0x72, 0x9d, 0x3b, 0x92, 0x5f, 0x7a,
+	0x96, 0xdf, 0xc0, 0x3d, 0xf4, 0xb1, 0x5e, 0xda, 0xc1, 0x9f, 0x08, 0xf4,
+	0xad, 0xf5, 0x84, 0x7c, 0x3b, 0xd6, 0x7a, 0xd1, 0x88, 0x44, 0x68, 0x9f,
+	0x98, 0x5a, 0xbf, 0x29, 0x61, 0x74, 0xc0, 0x72, 0x4c, 0xae, 0x06, 0x8b,
+	0xb5, 0x0f, 0x48, 0x15, 0xbe, 0x16, 0x17, 0x89, 0x95, 0xd0, 0x2e, 0xa3,
+	0xd2, 0xc8, 0xe8, 0xc8, 0x60, 0x2d, 0x20, 0xa1, 0x02, 0x41, 0x00, 0xdb,
+	0x39, 0xbf, 0x14, 0xf8, 0x24, 0xc6, 0xa2, 0x0d, 0xc5, 0x61, 0xed, 0x05,
+	0x0d, 0x62, 0x2b, 0x38, 0xe2, 0x9a, 0x92, 0x22, 0x39, 0x76, 0x0e, 0x5f,
+	0xa6, 0xec, 0x14, 0xb8, 0x6e, 0x3e, 0x8a, 0x51, 0x94, 0x98, 0x03, 0x88,
+	0x4d, 0x6b, 0xab, 0x42, 0xca, 0xa2, 0xd0, 0x7e, 0x5b, 0x58, 0x88, 0x98,
+	0x47, 0x7b, 0xed, 0x9e, 0x31, 0xce, 0x4a, 0x0b, 0x3b, 0x70, 0x83, 0xa1,
+	0xe6, 0x19, 0x29, 0x02, 0x41, 0x00, 0x9c, 0x88, 0xbb, 0x56, 0x6b, 0x4a,
+	0x81, 0x2c, 0xb3, 0x70, 0xdc, 0xf5, 0x65, 0x45, 0xd4, 0xed, 0xdd, 0xc3,
+	0xdc, 0xc5, 0x27, 0xa3, 0xa0, 0x66, 0x5c, 0x51, 0xeb, 0x52, 0x8c, 0x8d,
+	0x4e, 0xa6, 0x8f, 0x42, 0x5d, 0xb8, 0xa4, 0xa4, 0x26, 0xf3, 0xd6, 0xe5,
+	0x01, 0x6b, 0x51, 0x8a, 0xa4, 0xee, 0xec, 0xff, 0x71, 0x8c, 0xbb, 0xba,
+	0x05, 0x3e, 0x55, 0x14, 0xd9, 0xe4, 0xa4, 0x7f, 0xb7, 0x4f
 };
 
 static void test_rsa(const void *data)
 {
 	struct l_asymmetric_cipher *cipher;
 	char buf[128];
-	uint8_t *short_key;
-	size_t short_key_len;
-
-	short_key = extract_rsakey(rsa_priv_key, sizeof(rsa_priv_key),
-					&short_key_len);
 
 	cipher = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
-						short_key, short_key_len);
-	l_free(short_key);
-
+						rsa_priv_key,
+						sizeof(rsa_priv_key));
 	assert(cipher);
 	assert(l_asymmetric_cipher_encrypt(cipher, FIXED_STR, buf, 100, 128));
 
 	assert(memcmp(FIXED_STR, buf, 100));
 
-	assert(l_asymmetric_cipher_decrypt(cipher, buf, buf, 128, 100));
+	assert(l_asymmetric_cipher_decrypt(cipher, buf, buf, 128, 128));
 
 	assert(!memcmp(FIXED_STR, buf, 100));
 
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 10/11] cipher: Return result length from asymmetric cipher operations
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (7 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 09/11] unit: Update for akcipher changes Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-06 20:54 ` [PATCH 11/11] tls: Free cert memory after sending cert Mat Martineau
  2016-06-07 17:54 ` [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Denis Kenzior
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 13841 bytes --]

Short reads from AF_ALG akcipher sockets return an error rather than a
partial buffer so it's important to provide both an output buffer
length (which is typically longer than the expected data), and to find
out how many bytes were read.
---
 ell/cipher.c       | 64 +++++++++++++++++++++++-----------------
 ell/cipher.h       | 16 +++++-----
 ell/tls-private.h  |  2 +-
 ell/tls.c          | 86 ++++++++++++++++++++++++++++++++++++------------------
 unit/test-cipher.c |  8 +++--
 5 files changed, 109 insertions(+), 67 deletions(-)

diff --git a/ell/cipher.c b/ell/cipher.c
index 04bbd82..04316d8 100644
--- a/ell/cipher.c
+++ b/ell/cipher.c
@@ -78,6 +78,13 @@ struct af_alg_iv {
 #define SOL_ALG 279
 #endif
 
+#ifndef ALG_OP_SIGN
+#define ALG_OP_SIGN	2
+#endif
+#ifndef ALG_OP_VERIFY
+#define ALG_OP_VERIFY	3
+#endif
+
 #ifndef ALG_SET_PUBKEY
 #define ALG_SET_PUBKEY	6
 #endif
@@ -185,7 +192,7 @@ LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
 	l_free(cipher);
 }
 
-static bool operate_cipher(int sk, __u32 operation,
+static ssize_t operate_cipher(int sk, __u32 operation,
 				const void *in, void *out, size_t len_in,
 				size_t len_out)
 {
@@ -215,10 +222,7 @@ static bool operate_cipher(int sk, __u32 operation,
 	if (sendmsg(sk, &msg, 0) < 0)
 		return false;
 
-	if (read(sk, out, len_out) < 0)
-		return false;
-
-	return true;
+	return read(sk, out, len_out);
 }
 
 LIB_EXPORT bool l_cipher_encrypt(struct l_cipher *cipher,
@@ -451,9 +455,9 @@ LIB_EXPORT int l_asymmetric_cipher_get_key_size(
 	return cipher->key_size;
 }
 
-LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *acipher,
-					const void *in, void *out,
-					size_t len_in, size_t len_out)
+LIB_EXPORT ssize_t l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *acipher,
+						const void *in, void *out,
+						size_t len_in, size_t len_out)
 {
 	if (unlikely(!acipher))
 		return false;
@@ -465,9 +469,9 @@ LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *acipher,
 				in, out, len_in, len_out);
 }
 
-LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *acipher,
-					const void *in, void *out,
-					size_t len_in, size_t len_out)
+LIB_EXPORT ssize_t l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *acipher,
+						const void *in, void *out,
+						size_t len_in, size_t len_out)
 {
 	if (unlikely(!acipher))
 		return false;
@@ -479,24 +483,30 @@ LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *acipher,
 				in, out, len_in, len_out);
 }
 
-LIB_EXPORT bool l_asymmetric_cipher_sign(struct l_asymmetric_cipher *cipher,
-					const void *in, void *out,
-					size_t len_in, size_t len_out)
+LIB_EXPORT ssize_t l_asymmetric_cipher_sign(struct l_asymmetric_cipher *acipher,
+						const void *in, void *out,
+						size_t len_in, size_t len_out)
 {
-	/*
-	 * The RSA signing operation uses the same primitive as
-	 * decryption so just call decrypt for now.
-	 */
-	return l_asymmetric_cipher_decrypt(cipher, in, out, len_in, len_out);
+	if (unlikely(!acipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	return operate_cipher(acipher->cipher.decrypt_sk, ALG_OP_SIGN,
+				in, out, len_in, len_out);
 }
 
-LIB_EXPORT bool l_asymmetric_cipher_verify(struct l_asymmetric_cipher *cipher,
-					const void *in, void *out,
-					size_t len_in, size_t len_out)
+LIB_EXPORT ssize_t l_asymmetric_cipher_verify(struct l_asymmetric_cipher *acipher,
+						const void *in, void *out,
+						size_t len_in, size_t len_out)
 {
-	/*
-	 * The RSA verify operation uses the same primitive as
-	 * encryption so just call encrypt.
-	 */
-	return l_asymmetric_cipher_encrypt(cipher, in, out, len_in, len_out);
+	if (unlikely(!acipher))
+		return false;
+
+	if (unlikely(!in) || unlikely(!out))
+		return false;
+
+	return operate_cipher(acipher->cipher.encrypt_sk, ALG_OP_VERIFY,
+				in, out, len_in, len_out);
 }
diff --git a/ell/cipher.h b/ell/cipher.h
index 329f667..a65903e 100644
--- a/ell/cipher.h
+++ b/ell/cipher.h
@@ -64,21 +64,21 @@ void l_asymmetric_cipher_free(struct l_asymmetric_cipher *cipher);
 
 int l_asymmetric_cipher_get_key_size(struct l_asymmetric_cipher *cipher);
 
-bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *cipher,
+ssize_t l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *cipher,
 					const void *in, void *out,
 					size_t len_in, size_t len_out);
 
-bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *cipher,
+ssize_t l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *cipher,
 					const void *in, void *out,
 					size_t len_in, size_t len_out);
 
-bool l_asymmetric_cipher_sign(struct l_asymmetric_cipher *cipher,
-				const void *in, void *out,
-				size_t len_in, size_t len_out);
+ssize_t l_asymmetric_cipher_sign(struct l_asymmetric_cipher *cipher,
+					const void *in, void *out,
+					size_t len_in, size_t len_out);
 
-bool l_asymmetric_cipher_verify(struct l_asymmetric_cipher *cipher,
-				const void *in, void *out,
-				size_t len_in, size_t len_out);
+ssize_t l_asymmetric_cipher_verify(struct l_asymmetric_cipher *cipher,
+					const void *in, void *out,
+					size_t len_in, size_t len_out);
 
 #ifdef __cplusplus
 }
diff --git a/ell/tls-private.h b/ell/tls-private.h
index 184f2ae..9ea1554 100644
--- a/ell/tls-private.h
+++ b/ell/tls-private.h
@@ -65,7 +65,7 @@ struct tls_key_exchange_algorithm {
 	void (*handle_client_key_exchange)(struct l_tls *tls,
 						const uint8_t *buf, size_t len);
 
-	bool (*sign)(struct l_tls *tls, uint8_t **out,
+	bool (*sign)(struct l_tls *tls, uint8_t **out, size_t len,
 			tls_get_hash_t get_hash);
 	bool (*verify)(struct l_tls *tls, const uint8_t *in, size_t len,
 			tls_get_hash_t get_hash);
diff --git a/ell/tls.c b/ell/tls.c
index 6896a05..e1630c3 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -274,7 +274,7 @@ static bool tls_send_rsa_client_key_xchg(struct l_tls *tls);
 static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
 						const uint8_t *buf, size_t len);
 
-static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
+static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out, size_t len,
 				tls_get_hash_t get_hash);
 static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t len,
 				tls_get_hash_t get_hash);
@@ -856,10 +856,10 @@ static bool tls_send_rsa_client_key_xchg(struct l_tls *tls)
 {
 	uint8_t buf[1024 + 32];
 	uint8_t *ptr = buf + TLS_HANDSHAKE_HEADER_SIZE;
-	uint8_t pre_master_secret[48];
+	uint8_t *pre_master_secret;
 	struct l_asymmetric_cipher *rsa_server_pubkey;
 	int key_size;
-	bool result;
+	ssize_t bytes_encrypted;
 
 	if (!tls->peer_pubkey) {
 		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
@@ -867,10 +867,6 @@ static bool tls_send_rsa_client_key_xchg(struct l_tls *tls)
 		return false;
 	}
 
-	pre_master_secret[0] = (uint8_t) (TLS_VERSION >> 8);
-	pre_master_secret[1] = (uint8_t) (TLS_VERSION >> 0);
-	l_getrandom(pre_master_secret + 2, 46);
-
 	/* Fill in the RSA Client Key Exchange body */
 
 	rsa_server_pubkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
@@ -892,16 +888,23 @@ static bool tls_send_rsa_client_key_xchg(struct l_tls *tls)
 		return false;
 	}
 
+	pre_master_secret = l_malloc(key_size);
+
+	pre_master_secret[0] = (uint8_t) (TLS_VERSION >> 8);
+	pre_master_secret[1] = (uint8_t) (TLS_VERSION >> 0);
+	l_getrandom(pre_master_secret + 2, 46);
+
 	l_put_be16(key_size, ptr);
-	result = l_asymmetric_cipher_encrypt(rsa_server_pubkey,
-						pre_master_secret, ptr + 2,
-						48, key_size);
+	bytes_encrypted = l_asymmetric_cipher_encrypt(rsa_server_pubkey,
+							pre_master_secret,
+							ptr + 2, 48, key_size);
 	ptr += key_size + 2;
 
 	l_asymmetric_cipher_free(rsa_server_pubkey);
 
-	if (!result) {
+	if (bytes_encrypted != key_size) {
 		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
+		l_free(pre_master_secret);
 
 		return false;
 	}
@@ -910,22 +913,30 @@ static bool tls_send_rsa_client_key_xchg(struct l_tls *tls)
 
 	tls_generate_master_secret(tls, pre_master_secret, 48);
 	memset(pre_master_secret, 0, 48);
+	l_free(pre_master_secret);
 
 	return true;
 }
 
-static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
+static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out, size_t len,
 				tls_get_hash_t get_hash)
 {
 	struct l_asymmetric_cipher *rsa_privkey;
 	uint8_t *privkey;
 	size_t key_size;
 	bool result;
+	ssize_t sign_output_len;
 	const struct tls_hash_algorithm *hash_type;
 	uint8_t hash[HANDSHAKE_HASH_MAX_SIZE];
 	uint8_t sign_input[HANDSHAKE_HASH_MAX_SIZE * 2 + 32];
 	size_t sign_input_len;
 
+	if (len < 2) {
+		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
+
+		return false;
+	}
+
 	if (!tls->priv_key_path) {
 		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
 				TLS_ALERT_BAD_CERT);
@@ -965,16 +976,25 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
 
 		*(*out)++ = hash_type->tls_id;
 		*(*out)++ = 1;	/* RSA_sign */
+		len -= 2;
 	} else {
 		get_hash(tls, 1, sign_input + 0, NULL, NULL);	/* MD5 */
 		get_hash(tls, 2, sign_input + 16, NULL, NULL);	/* SHA1 */
 		sign_input_len = 36;
 	}
 
-	l_put_be16(key_size, *out);
-	result = l_asymmetric_cipher_sign(rsa_privkey, sign_input, *out + 2,
-						sign_input_len, key_size);
-	*out += key_size + 2;
+	if (len >= key_size + 2) {
+		l_put_be16(key_size, *out);
+		sign_output_len = l_asymmetric_cipher_sign(rsa_privkey,
+							   sign_input, *out + 2,
+							   sign_input_len,
+							   key_size);
+		*out += sign_output_len + 2;
+		result = sign_output_len == (ssize_t)key_size;
+	} else {
+		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
+		result = false;
+	}
 
 	l_asymmetric_cipher_free(rsa_privkey);
 
@@ -986,7 +1006,7 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t len,
 {
 	struct l_asymmetric_cipher *rsa_client_pubkey;
 	size_t key_size;
-	bool result;
+	ssize_t verify_bytes;
 	uint8_t hash[HANDSHAKE_HASH_MAX_SIZE];
 	size_t hash_len;
 	enum l_checksum_type hash_type;
@@ -1073,13 +1093,14 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t len,
 
 	digest_info = alloca(key_size);
 
-	result = l_asymmetric_cipher_verify(rsa_client_pubkey, in + 4,
-						digest_info,
-						key_size, key_size);
+	verify_bytes = l_asymmetric_cipher_verify(rsa_client_pubkey, in + 4,
+							digest_info, key_size,
+							key_size);
 
 	l_asymmetric_cipher_free(rsa_client_pubkey);
 
-	if (!result || memcmp(digest_info, expected, expected_len)) {
+	if (verify_bytes != (ssize_t)expected_len ||
+		memcmp(digest_info, expected, expected_len)) {
 		tls_disconnect(tls, TLS_ALERT_DECRYPT_ERROR, 0);
 
 		return false;
@@ -1139,7 +1160,8 @@ static bool tls_send_certificate_verify(struct l_tls *tls)
 	/* Fill in the Certificate Verify body */
 
 	if (!tls->pending.cipher_suite->key_xchg->sign(tls, &ptr,
-						tls_get_handshake_hash_by_id))
+					2048 - TLS_HANDSHAKE_HEADER_SIZE,
+					tls_get_handshake_hash_by_id))
 		return false;
 
 	/* Stop maintaining handshake message hashes other than SHA256. */
@@ -1732,11 +1754,12 @@ static void tls_handle_server_hello_done(struct l_tls *tls,
 static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
 						const uint8_t *buf, size_t len)
 {
-	uint8_t pre_master_secret[48], random_secret[46];
+	uint8_t *pre_master_secret;
+	uint8_t random_secret[46];
 	struct l_asymmetric_cipher *rsa_server_privkey;
 	uint8_t *privkey;
 	size_t key_size;
-	bool result;
+	ssize_t bytes_decrypted;
 
 	if (!tls->priv_key_path) {
 		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
@@ -1785,9 +1808,12 @@ static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
 		return;
 	}
 
-	result = l_asymmetric_cipher_decrypt(rsa_server_privkey, buf + 2,
-						pre_master_secret,
-						key_size, 48);
+	pre_master_secret = l_malloc(key_size);
+
+	bytes_decrypted = l_asymmetric_cipher_decrypt(rsa_server_privkey,
+							buf + 2,
+							pre_master_secret,
+							key_size, key_size);
 	l_asymmetric_cipher_free(rsa_server_privkey);
 
 	/*
@@ -1805,12 +1831,14 @@ static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
 	pre_master_secret[0] = tls->client_version >> 8;
 	pre_master_secret[1] = tls->client_version >> 0;
 
-	if (!result)
+	if (bytes_decrypted != 48)
 		memcpy(pre_master_secret + 2, random_secret, 46);
 
 	tls_generate_master_secret(tls, pre_master_secret, 48);
-	memset(pre_master_secret, 0, 48);
+	memset(pre_master_secret, 0, key_size);
 	memset(random_secret, 0, 46);
+
+	l_free(pre_master_secret);
 }
 
 static bool tls_get_prev_digest_by_id(struct l_tls *tls, uint8_t hash_id,
diff --git a/unit/test-cipher.c b/unit/test-cipher.c
index 2527dcc..23021bf 100644
--- a/unit/test-cipher.c
+++ b/unit/test-cipher.c
@@ -184,16 +184,20 @@ static void test_rsa(const void *data)
 {
 	struct l_asymmetric_cipher *cipher;
 	char buf[128];
+	ssize_t encrypted, decrypted;
 
 	cipher = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
 						rsa_priv_key,
 						sizeof(rsa_priv_key));
 	assert(cipher);
-	assert(l_asymmetric_cipher_encrypt(cipher, FIXED_STR, buf, 100, 128));
+	encrypted = l_asymmetric_cipher_encrypt(cipher, FIXED_STR, buf,
+						100, 128);
+	assert(encrypted == 128);
 
 	assert(memcmp(FIXED_STR, buf, 100));
 
-	assert(l_asymmetric_cipher_decrypt(cipher, buf, buf, 128, 128));
+	decrypted = l_asymmetric_cipher_decrypt(cipher, buf, buf, 128, 128);
+	assert(decrypted == 100);
 
 	assert(!memcmp(FIXED_STR, buf, 100));
 
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 11/11] tls: Free cert memory after sending cert
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (8 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 10/11] cipher: Return result length from asymmetric cipher operations Mat Martineau
@ 2016-06-06 20:54 ` Mat Martineau
  2016-06-07 17:54 ` [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Denis Kenzior
  10 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-06 20:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 334 bytes --]

---
 ell/tls.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ell/tls.c b/ell/tls.c
index e1630c3..59fe0d0 100644
--- a/ell/tls.c
+++ b/ell/tls.c
@@ -727,6 +727,8 @@ static bool tls_send_certificate(struct l_tls *tls)
 	if (cert)
 		tls->cert_sent = true;
 
+	l_free(cert);
+
 	return true;
 }
 
-- 
2.8.3


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-06 20:54 ` [PATCH 08/11] cipher: Update for current kernel akcipher interface Mat Martineau
@ 2016-06-06 23:55   ` Denis Kenzior
  2016-06-07 17:51   ` Denis Kenzior
  1 sibling, 0 replies; 24+ messages in thread
From: Denis Kenzior @ 2016-06-06 23:55 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 444 bytes --]

Hi Mat,

On 06/06/2016 03:54 PM, Mat Martineau wrote:
> There are some significant differences in the current iteration of
> kernel AF_ALG akcipher support:
>   * Kernel handles padding

Are you sure?  Talking with Andrew a while ago, he didn't think this was 
the case.  My impression was that it was implemented as a template.

The unit test we have for L_CIPHER_RSA_PKCS1_V1_5 is not really reliable 
either.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-06 20:54 ` [PATCH 08/11] cipher: Update for current kernel akcipher interface Mat Martineau
  2016-06-06 23:55   ` Denis Kenzior
@ 2016-06-07 17:51   ` Denis Kenzior
  2016-06-07 19:10     ` Mat Martineau
  2016-06-07 21:47     ` Andrzej Zaborowski
  1 sibling, 2 replies; 24+ messages in thread
From: Denis Kenzior @ 2016-06-07 17:51 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 18196 bytes --]

Hi Mat,

On 06/06/2016 03:54 PM, Mat Martineau wrote:
> There are some significant differences in the current iteration of
> kernel AF_ALG akcipher support:
>   * Kernel handles padding
>   * Kernel accepts DER-encoded certs as-is (no need to extract values)
>   * Must explicitly set private or public key
> ---
>   ell/cipher-private.h |   3 -
>   ell/cipher.c         | 300 +++++++++++++--------------------------------------
>   ell/tls.c            |  43 +++-----
>   3 files changed, 85 insertions(+), 261 deletions(-)
>
> diff --git a/ell/cipher-private.h b/ell/cipher-private.h
> index 7d115f6..77ddd06 100644
> --- a/ell/cipher-private.h
> +++ b/ell/cipher-private.h
> @@ -20,9 +20,6 @@
>    *
>    */
>
> -uint8_t *extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
> -			size_t *out_len);
> -
>   #define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | (tag))
>
>   #define ASN1_CLASS_UNIVERSAL	0
> diff --git a/ell/cipher.c b/ell/cipher.c
> index 671071b..04bbd82 100644
> --- a/ell/cipher.c
> +++ b/ell/cipher.c
> @@ -78,6 +78,10 @@ struct af_alg_iv {
>   #define SOL_ALG 279
>   #endif
>
> +#ifndef ALG_SET_PUBKEY
> +#define ALG_SET_PUBKEY	6
> +#endif
> +

So we don't put #ifdef guards around
ALG_SET_KEY, SET_IV, SET_OP.  Why is this different? Should we have 
guards around all of these?

>   #define is_valid_type(type)  ((type) <= L_CIPHER_DES3_EDE_CBC)
>
>   struct l_cipher {
> @@ -87,10 +91,11 @@ struct l_cipher {
>   };
>
>   static int create_alg(const char *alg_type, const char *alg_name,
> -				const void *key, size_t key_length)
> +			const void *key, size_t key_length, bool public)
>   {
>   	struct sockaddr_alg salg;
>   	int sk;
> +	int keyopt;
>   	int ret;
>
>   	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
> @@ -107,7 +112,8 @@ static int create_alg(const char *alg_type, const char *alg_name,
>   		return -1;
>   	}
>
> -	if (setsockopt(sk, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
> +	keyopt = public ? ALG_SET_PUBKEY : ALG_SET_KEY;
> +	if (setsockopt(sk, SOL_ALG, keyopt, key, key_length) < 0) {
>   		close(sk);
>   		return -1;
>   	}
> @@ -149,11 +155,13 @@ LIB_EXPORT struct l_cipher *l_cipher_new(enum l_cipher_type type,
>   		break;
>   	}
>
> -	cipher->encrypt_sk = create_alg("skcipher", alg_name, key, key_length);
> +	cipher->encrypt_sk = create_alg("skcipher", alg_name, key, key_length,
> +					false);
>   	if (cipher->encrypt_sk < 0)
>   		goto error_free;
>
> -	cipher->decrypt_sk = create_alg("skcipher", alg_name, key, key_length);
> +	cipher->decrypt_sk = create_alg("skcipher", alg_name, key, key_length,
> +					false);
>   	if (cipher->decrypt_sk < 0)
>   		goto error_close;
>
> @@ -178,7 +186,8 @@ LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
>   }
>
>   static bool operate_cipher(int sk, __u32 operation,
> -				const void *in, void *out, size_t len)
> +				const void *in, void *out, size_t len_in,
> +				size_t len_out)
>   {
>   	char c_msg_buf[CMSG_SPACE(sizeof(operation))];
>   	struct msghdr msg;
> @@ -198,7 +207,7 @@ static bool operate_cipher(int sk, __u32 operation,
>   	memcpy(CMSG_DATA(c_msg), &operation, sizeof(operation));
>
>   	iov.iov_base = (void *) in;
> -	iov.iov_len = len;
> +	iov.iov_len = len_in;
>
>   	msg.msg_iov = &iov;
>   	msg.msg_iovlen = 1;
> @@ -206,7 +215,7 @@ static bool operate_cipher(int sk, __u32 operation,
>   	if (sendmsg(sk, &msg, 0) < 0)
>   		return false;
>
> -	if (read(sk, out, len) < 0)
> +	if (read(sk, out, len_out) < 0)
>   		return false;
>
>   	return true;
> @@ -221,7 +230,8 @@ LIB_EXPORT bool l_cipher_encrypt(struct l_cipher *cipher,
>   	if (unlikely(!in) || unlikely(!out))
>   		return false;
>
> -	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, out, len);
> +	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, out, len,
> +				len);
>   }
>
>   LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
> @@ -233,7 +243,8 @@ LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
>   	if (unlikely(!in) || unlikely(!out))
>   		return false;
>
> -	return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, len);
> +	return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, len,
> +				len);
>   }
>
>   LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
> @@ -275,6 +286,7 @@ LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t *iv,
>   struct l_asymmetric_cipher {
>   	struct l_cipher cipher;
>   	int key_size;
> +	bool public_key;
>   };
>
>   static inline int parse_asn1_definite_length(const uint8_t **buf,
> @@ -334,20 +346,31 @@ static bool parse_rsa_key(struct l_asymmetric_cipher *cipher, const void *key,
>   	 * and cache the size of the modulus n for later use.
>   	 * (RFC3279)
>   	 */
> +	size_t seq_length;
>   	size_t n_length;
> +	uint8_t *seq;
>   	uint8_t *der;
>   	uint8_t tag;
> +	bool pubkey = true;

I'm a bit unsure that we really want to know this information.  What is 
it's use actually?  We should always implicitly know what type of 
certificate we are giving to l_asymmetric_cipher_new, so it might just 
need to be a parameter.

>
>   	if (key_length < 8)
>   		return false;
>
>   	/* Unpack the outer SEQUENCE */
> -	der = der_find_elem((uint8_t *) key, key_length, 0, &tag, &n_length);
> -	if (!der || tag != ASN1_ID_SEQUENCE)
> +	seq = der_find_elem((uint8_t *) key, key_length, 0, &tag, &seq_length);
> +	if (!seq || tag != ASN1_ID_SEQUENCE)
>   		return false;
>
> -	/* Take first INTEGER as the modulus */
> -	der = der_find_elem(der, n_length, 0, &tag, &n_length);
> +	/* First INTEGER may be a 1-byte version (for private key) or
> +	 * the modulus (public key)
> +	 */
> +	der = der_find_elem(seq, seq_length, 0, &tag, &n_length);
> +	if (der && tag == ASN1_ID_INTEGER && n_length == 1) {
> +		/* Found version number, implies this is a private key. */
> +		der = der_find_elem(seq, seq_length, 1, &tag, &n_length);
> +		pubkey = false;
> +	}
> +
>   	if (!der || tag != ASN1_ID_INTEGER || n_length < 4)
>   		return false;
>
> @@ -358,95 +381,11 @@ static bool parse_rsa_key(struct l_asymmetric_cipher *cipher, const void *key,
>   	}
>
>   	cipher->key_size = n_length;

This probably belongs as a setsockopt into the kernel...

> +	cipher->public_key = pubkey;
>
>   	return true;
>   }
>
> -static void write_asn1_definite_length(uint8_t **buf, size_t len)
> -{
> -	int n;
> -
> -	if (len < 0x80) {
> -		*(*buf)++ = len;
> -
> -		return;
> -	}
> -
> -	for (n = 1; len >> (n * 8); n++);
> -	*(*buf)++ = 0x80 | n;
> -
> -	while (n--)
> -		*(*buf)++ = len >> (n * 8);
> -}
> -
> -/*
> - * Extract a ASN1 RsaKey-formatted public+private key structure in the
> - * form used in the kernel.  It is simpler than the PKCS#1 form as it only
> - * contains the N, E and D integers and also correctly parses as a PKCS#1
> - * RSAPublicKey.
> - */
> -uint8_t *extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
> -			size_t *out_len)
> -{
> -	uint8_t *key, *ptr, *ver, *n, *e, *d;
> -	uint8_t tag;
> -	size_t ver_len, n_len, e_len, d_len;
> -	int pos;
> -
> -	/* Unpack the outer SEQUENCE */
> -	pkcs1_key = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag,
> -					&pkcs1_key_len);
> -	if (!pkcs1_key || tag != ASN1_ID_SEQUENCE)
> -		return NULL;
> -
> -	/* Check if the version element if present */
> -	ver = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag, &ver_len);
> -	if (!ver || tag != ASN1_ID_INTEGER)
> -		return NULL;
> -
> -	pos = (ver_len == 1 && ver[0] == 0x00) ? 1 : 0;
> -
> -	n = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 0, &tag, &n_len);
> -	if (!n || tag != ASN1_ID_INTEGER)
> -		return NULL;
> -
> -	e = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 1, &tag, &e_len);
> -	if (!e || tag != ASN1_ID_INTEGER)
> -		return NULL;
> -
> -	d = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 2, &tag, &d_len);
> -	if (!d || tag != ASN1_ID_INTEGER)
> -		return NULL;
> -
> -	/* New SEQUENCE length including tags and lengths */
> -	*out_len = 1 + (n_len >= 0x80 ? n_len >= 0x100 ? 3 : 2 : 1) + n_len +
> -		1 + (e_len >= 0x80 ? e_len >= 0x100 ? 3 : 2 : 1) + e_len +
> -		1 + (d_len >= 0x80 ? d_len >= 0x100 ? 3 : 2 : 1) + d_len;
> -	ptr = key = l_malloc(*out_len +
> -		1 + (*out_len >= 0x80 ? *out_len >= 0x100 ? 3 : 2 : 1));
> -
> -	*ptr++ = ASN1_ID_SEQUENCE;
> -	write_asn1_definite_length(&ptr, *out_len);
> -
> -	*ptr++ = ASN1_ID_INTEGER;
> -	write_asn1_definite_length(&ptr, n_len);
> -	memcpy(ptr, n, n_len);
> -	ptr += n_len;
> -
> -	*ptr++ = ASN1_ID_INTEGER;
> -	write_asn1_definite_length(&ptr, e_len);
> -	memcpy(ptr, e, e_len);
> -	ptr += e_len;
> -
> -	*ptr++ = ASN1_ID_INTEGER;
> -	write_asn1_definite_length(&ptr, d_len);
> -	memcpy(ptr, d, d_len);
> -	ptr += d_len;
> -
> -	*out_len = ptr - key;
> -	return key;
> -}
> -
>   LIB_EXPORT struct l_asymmetric_cipher *l_asymmetric_cipher_new(
>   					enum l_asymmetric_cipher_type type,
>   					const void *key, size_t key_length)
> @@ -473,14 +412,18 @@ LIB_EXPORT struct l_asymmetric_cipher *l_asymmetric_cipher_new(
>   	}
>
>   	cipher->cipher.encrypt_sk = create_alg("akcipher", alg_name,
> -						key, key_length);
> +						key, key_length,
> +						cipher->public_key);
>   	if (cipher->cipher.encrypt_sk < 0)
>   		goto error_free;
>
> -	cipher->cipher.decrypt_sk = create_alg("akcipher", alg_name,
> -						key, key_length);
> -	if (cipher->cipher.decrypt_sk < 0)
> -		goto error_close;
> +	if (!cipher->public_key) {
> +		cipher->cipher.decrypt_sk = create_alg("akcipher", alg_name,
> +							key, key_length,
> +							cipher->public_key);
> +		if (cipher->cipher.decrypt_sk < 0)
> +			goto error_close;
> +	}
>
>   	return cipher;
>
> @@ -508,151 +451,52 @@ LIB_EXPORT int l_asymmetric_cipher_get_key_size(
>   	return cipher->key_size;
>   }
>
> -static void getrandom_nonzero(uint8_t *buf, int len)
> -{
> -	while (len--) {
> -		l_getrandom(buf, 1);
> -		while (buf[0] == 0)
> -			l_getrandom(buf, 1);
> -
> -		buf++;
> -	}
> -}
> -
> -LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *cipher,
> +LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher *acipher,
>   					const void *in, void *out,
>   					size_t len_in, size_t len_out)
>   {
> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
> -		uint8_t buf[cipher->key_size];
> -		int ps_len = cipher->key_size - len_in - 3;
> -
> -		if (len_in > (size_t) cipher->key_size - 11)
> -			return false;
> -		if (len_out != (size_t) cipher->key_size)
> -			return false;
> -
> -		buf[0] = 0x00;
> -		buf[1] = 0x02;
> -		getrandom_nonzero(buf + 2, ps_len);
> -		buf[ps_len + 2] = 0x00;
> -		memcpy(buf + ps_len + 3, in, len_in);
> -
> -		if (!l_cipher_encrypt(&cipher->cipher, buf, out,
> -					cipher->key_size))
> -			return false;
> -	}
> +	if (unlikely(!acipher))
> +		return false;
>
> -	return true;
> +	if (unlikely(!in) || unlikely(!out))
> +		return false;
> +
> +	return operate_cipher(acipher->cipher.encrypt_sk, ALG_OP_ENCRYPT,
> +				in, out, len_in, len_out);
>   }
>
> -LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *cipher,
> +LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher *acipher,
>   					const void *in, void *out,
>   					size_t len_in, size_t len_out)
>   {
> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
> -		uint8_t buf[cipher->key_size];
> -		int pos;
> -
> -		if (len_in != (size_t) cipher->key_size)
> -			return false;
> -
> -		if (!l_cipher_decrypt(&cipher->cipher, in, buf,
> -					cipher->key_size))
> -			return false;
> -
> -		if (buf[0] != 0x00)
> -			return false;
> -		if (buf[1] != 0x02)
> -			return false;
> -
> -		for (pos = 2; pos < cipher->key_size; pos++)
> -			if (buf[pos] == 0)
> -				break;
> -		if (pos < 10 || pos == cipher->key_size)
> -			return false;
> -
> -		pos++;
> -		if (len_out != (size_t) cipher->key_size - pos)
> -			return false;
> -
> -		memcpy(out, buf + pos, cipher->key_size - pos);
> -	}

I'm all for getting rid of the padding stuff, but as mentioned 
previously, I'm not sure the pkcs1pad template is part of the rsa 
akcipher by default.  Is it?

> +	if (unlikely(!acipher))
> +		return false;
>
> -	return true;
> +	if (unlikely(!in) || unlikely(!out))
> +		return false;
> +
> +	return operate_cipher(acipher->cipher.decrypt_sk, ALG_OP_DECRYPT,
> +				in, out, len_in, len_out);
>   }
>
>   LIB_EXPORT bool l_asymmetric_cipher_sign(struct l_asymmetric_cipher *cipher,
>   					const void *in, void *out,
>   					size_t len_in, size_t len_out)
>   {
> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
> -		uint8_t buf[cipher->key_size];
> -		int ps_len = cipher->key_size - len_in - 3;
> -
> -		if (len_in > (size_t) cipher->key_size - 11)
> -			return false;
> -		if (len_out != (size_t) cipher->key_size)
> -			return false;
> -
> -		buf[0] = 0x00;
> -		buf[1] = 0x01;
> -		memset(buf + 2, 0xff, ps_len);
> -		buf[ps_len + 2] = 0x00;
> -		memcpy(buf + ps_len + 3, in, len_in);
> -
> -		/*
> -		 * The RSA signing operation uses the same primitive as
> -		 * decryption so just call decrypt for now.
> -		 */
> -		if (!l_cipher_decrypt(&cipher->cipher, buf, out,
> -					cipher->key_size))
> -			return false;
> -	}
> -
> -	return true;
> +	/*
> +	 * The RSA signing operation uses the same primitive as
> +	 * decryption so just call decrypt for now.
> +	 */
> +	return l_asymmetric_cipher_decrypt(cipher, in, out, len_in, len_out);
>   }
>
>   LIB_EXPORT bool l_asymmetric_cipher_verify(struct l_asymmetric_cipher *cipher,
>   					const void *in, void *out,
>   					size_t len_in, size_t len_out)
>   {
> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
> -		uint8_t buf[cipher->key_size];
> -		int pos;
> -
> -		if (len_in != (size_t) cipher->key_size)
> -			return false;
> -
> -		/*
> -		 * The RSA verify operation uses the same primitive as
> -		 * encryption so just call encrypt.
> -		 */
> -		if (!l_cipher_encrypt(&cipher->cipher, in, buf,
> -					cipher->key_size))
> -			return false;
> -
> -		if (buf[0] != 0x00)
> -			return false;
> -		if (buf[1] != 0x01)
> -			return false;
> -
> -		for (pos = 2; pos < cipher->key_size; pos++)
> -			if (buf[pos] != 0xff)
> -				break;
> -		if (pos < 10 || pos == cipher->key_size || buf[pos] != 0)
> -			return false;
> -
> -		pos++;
> -		if (len_out != (size_t) cipher->key_size - pos)
> -			return false;
> -
> -		memcpy(out, buf + pos, cipher->key_size - pos);
> -	}
> -
> -	return true;
> +	/*
> +	 * The RSA verify operation uses the same primitive as
> +	 * encryption so just call encrypt.
> +	 */
> +	return l_asymmetric_cipher_encrypt(cipher, in, out, len_in, len_out);
>   }
> diff --git a/ell/tls.c b/ell/tls.c
> index e47e8bf..6896a05 100644
> --- a/ell/tls.c
> +++ b/ell/tls.c
> @@ -918,8 +918,8 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
>   				tls_get_hash_t get_hash)
>   {
>   	struct l_asymmetric_cipher *rsa_privkey;
> -	uint8_t *privkey, *privkey_short;
> -	size_t key_size, short_size;
> +	uint8_t *privkey;
> +	size_t key_size;
>   	bool result;
>   	const struct tls_hash_algorithm *hash_type;
>   	uint8_t hash[HANDSHAKE_HASH_MAX_SIZE];
> @@ -943,19 +943,9 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t **out,
>   		return false;
>   	}
>
> -	privkey_short = extract_rsakey(privkey, key_size, &short_size);
> -	tls_free_key(privkey, key_size);
> -
> -	if (!privkey_short) {
> -		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
> -				TLS_ALERT_BAD_CERT);
> -
> -		return false;
> -	}
> -
>   	rsa_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
> -						privkey_short, short_size);
> -	tls_free_key(privkey_short, short_size);
> +						privkey, key_size);
> +	tls_free_key(privkey, key_size);
>
>   	if (!rsa_privkey) {
>   		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);

Should we be reporting BAD_CERT here?

> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls, const uint8_t *in, size_t len,
>   		 */
>   	}
>
> -	digest_info = alloca(expected_len);
> +	if (expected_len > key_size)
> +		goto err_free_rsa;
> +
> +	digest_info = alloca(key_size);

This looks like a separate fix and belongs in a separate patch.

>
>   	result = l_asymmetric_cipher_verify(rsa_client_pubkey, in + 4,
>   						digest_info,
> -						key_size, expected_len);
> +						key_size, key_size);

Same here?

>
>   	l_asymmetric_cipher_free(rsa_client_pubkey);
>
> @@ -1741,8 +1734,8 @@ static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
>   {
>   	uint8_t pre_master_secret[48], random_secret[46];
>   	struct l_asymmetric_cipher *rsa_server_privkey;
> -	uint8_t *privkey, *privkey_short;
> -	size_t key_size, short_size;
> +	uint8_t *privkey;
> +	size_t key_size;
>   	bool result;
>
>   	if (!tls->priv_key_path) {
> @@ -1762,19 +1755,9 @@ static void tls_handle_rsa_client_key_xchg(struct l_tls *tls,
>   		return;
>   	}
>
> -	privkey_short = extract_rsakey(privkey, key_size, &short_size);
> -	tls_free_key(privkey, key_size);
> -
> -	if (!privkey_short) {
> -		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
> -				TLS_ALERT_BAD_CERT);
> -
> -		return;
> -	}
> -
>   	rsa_server_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
> -						privkey_short, short_size);
> -	tls_free_key(privkey_short, short_size);
> +							privkey, key_size);
> +	tls_free_key(privkey, key_size);
>
>   	if (!rsa_server_privkey) {
>   		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>

Regards,
-Denis

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds
  2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
                   ` (9 preceding siblings ...)
  2016-06-06 20:54 ` [PATCH 11/11] tls: Free cert memory after sending cert Mat Martineau
@ 2016-06-07 17:54 ` Denis Kenzior
  10 siblings, 0 replies; 24+ messages in thread
From: Denis Kenzior @ 2016-06-07 17:54 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 194 bytes --]

Hi Mat,

On 06/06/2016 03:54 PM, Mat Martineau wrote:
> ---
>   .gitignore | 1 +
>   1 file changed, 1 insertion(+)
>

I went ahead and applied patches 1-7 and 11.

Thanks,
-Denis


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-07 17:51   ` Denis Kenzior
@ 2016-06-07 19:10     ` Mat Martineau
  2016-06-07 19:32       ` Denis Kenzior
  2016-06-07 21:47     ` Andrzej Zaborowski
  1 sibling, 1 reply; 24+ messages in thread
From: Mat Martineau @ 2016-06-07 19:10 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 20712 bytes --]


On Tue, 7 Jun 2016, Denis Kenzior wrote:

> Hi Mat,
>
> On 06/06/2016 03:54 PM, Mat Martineau wrote:
>> There are some significant differences in the current iteration of
>> kernel AF_ALG akcipher support:
>>   * Kernel handles padding
>>   * Kernel accepts DER-encoded certs as-is (no need to extract values)
>>   * Must explicitly set private or public key
>> ---
>>   ell/cipher-private.h |   3 -
>>   ell/cipher.c         | 300 
>> +++++++++++++--------------------------------------
>>   ell/tls.c            |  43 +++-----
>>   3 files changed, 85 insertions(+), 261 deletions(-)
>> 
>> diff --git a/ell/cipher-private.h b/ell/cipher-private.h
>> index 7d115f6..77ddd06 100644
>> --- a/ell/cipher-private.h
>> +++ b/ell/cipher-private.h
>> @@ -20,9 +20,6 @@
>>    *
>>    */
>> 
>> -uint8_t *extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
>> -			size_t *out_len);
>> -
>>   #define ASN1_ID(class, pc, tag)	(((class) << 6) | ((pc) << 5) | 
>> (tag))
>>
>>   #define ASN1_CLASS_UNIVERSAL	0
>> diff --git a/ell/cipher.c b/ell/cipher.c
>> index 671071b..04bbd82 100644
>> --- a/ell/cipher.c
>> +++ b/ell/cipher.c
>> @@ -78,6 +78,10 @@ struct af_alg_iv {
>>   #define SOL_ALG 279
>>   #endif
>> 
>> +#ifndef ALG_SET_PUBKEY
>> +#define ALG_SET_PUBKEY	6
>> +#endif
>> +
>
> So we don't put #ifdef guards around
> ALG_SET_KEY, SET_IV, SET_OP.  Why is this different? Should we have guards 
> around all of these?

ALG_SET_KEY (etc.) are conditional based on autoconf looking for if_alg.h
ALG_SET_PUBKEY is new, it may be undefined even if if_alg.h is present.

>
>>   #define is_valid_type(type)  ((type) <= L_CIPHER_DES3_EDE_CBC)
>>
>>   struct l_cipher {
>> @@ -87,10 +91,11 @@ struct l_cipher {
>>   };
>>
>>   static int create_alg(const char *alg_type, const char *alg_name,
>> -				const void *key, size_t key_length)
>> +			const void *key, size_t key_length, bool public)
>>   {
>>   	struct sockaddr_alg salg;
>>   	int sk;
>> +	int keyopt;
>>   	int ret;
>>
>>   	sk = socket(PF_ALG, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
>> @@ -107,7 +112,8 @@ static int create_alg(const char *alg_type, const char 
>> *alg_name,
>>   		return -1;
>>   	}
>> 
>> -	if (setsockopt(sk, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
>> +	keyopt = public ? ALG_SET_PUBKEY : ALG_SET_KEY;
>> +	if (setsockopt(sk, SOL_ALG, keyopt, key, key_length) < 0) {
>>   		close(sk);
>>   		return -1;
>>   	}
>> @@ -149,11 +155,13 @@ LIB_EXPORT struct l_cipher *l_cipher_new(enum 
>> l_cipher_type type,
>>   		break;
>>   	}
>> 
>> -	cipher->encrypt_sk = create_alg("skcipher", alg_name, key, 
>> key_length);
>> +	cipher->encrypt_sk = create_alg("skcipher", alg_name, key, 
>> key_length,
>> +					false);
>>   	if (cipher->encrypt_sk < 0)
>>   		goto error_free;
>> 
>> -	cipher->decrypt_sk = create_alg("skcipher", alg_name, key, 
>> key_length);
>> +	cipher->decrypt_sk = create_alg("skcipher", alg_name, key, 
>> key_length,
>> +					false);
>>   	if (cipher->decrypt_sk < 0)
>>   		goto error_close;
>> 
>> @@ -178,7 +186,8 @@ LIB_EXPORT void l_cipher_free(struct l_cipher *cipher)
>>   }
>>
>>   static bool operate_cipher(int sk, __u32 operation,
>> -				const void *in, void *out, size_t len)
>> +				const void *in, void *out, size_t len_in,
>> +				size_t len_out)
>>   {
>>   	char c_msg_buf[CMSG_SPACE(sizeof(operation))];
>>   	struct msghdr msg;
>> @@ -198,7 +207,7 @@ static bool operate_cipher(int sk, __u32 operation,
>>   	memcpy(CMSG_DATA(c_msg), &operation, sizeof(operation));
>>
>>   	iov.iov_base = (void *) in;
>> -	iov.iov_len = len;
>> +	iov.iov_len = len_in;
>>
>>   	msg.msg_iov = &iov;
>>   	msg.msg_iovlen = 1;
>> @@ -206,7 +215,7 @@ static bool operate_cipher(int sk, __u32 operation,
>>   	if (sendmsg(sk, &msg, 0) < 0)
>>   		return false;
>> 
>> -	if (read(sk, out, len) < 0)
>> +	if (read(sk, out, len_out) < 0)
>>   		return false;
>>
>>   	return true;
>> @@ -221,7 +230,8 @@ LIB_EXPORT bool l_cipher_encrypt(struct l_cipher 
>> *cipher,
>>   	if (unlikely(!in) || unlikely(!out))
>>   		return false;
>> 
>> -	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, out, 
>> len);
>> +	return operate_cipher(cipher->encrypt_sk, ALG_OP_ENCRYPT, in, out, 
>> len,
>> +				len);
>>   }
>>
>>   LIB_EXPORT bool l_cipher_decrypt(struct l_cipher *cipher,
>> @@ -233,7 +243,8 @@ LIB_EXPORT bool l_cipher_decrypt(struct l_cipher 
>> *cipher,
>>   	if (unlikely(!in) || unlikely(!out))
>>   		return false;
>> 
>> -	return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, 
>> len);
>> +	return operate_cipher(cipher->decrypt_sk, ALG_OP_DECRYPT, in, out, 
>> len,
>> +				len);
>>   }
>>
>>   LIB_EXPORT bool l_cipher_set_iv(struct l_cipher *cipher, const uint8_t 
>> *iv,
>> @@ -275,6 +286,7 @@ LIB_EXPORT bool l_cipher_set_iv(struct l_cipher 
>> *cipher, const uint8_t *iv,
>>   struct l_asymmetric_cipher {
>>   	struct l_cipher cipher;
>>   	int key_size;
>> +	bool public_key;
>>   };
>>
>>   static inline int parse_asn1_definite_length(const uint8_t **buf,
>> @@ -334,20 +346,31 @@ static bool parse_rsa_key(struct l_asymmetric_cipher 
>> *cipher, const void *key,
>>   	 * and cache the size of the modulus n for later use.
>>   	 * (RFC3279)
>>   	 */
>> +	size_t seq_length;
>>   	size_t n_length;
>> +	uint8_t *seq;
>>   	uint8_t *der;
>>   	uint8_t tag;
>> +	bool pubkey = true;
>
> I'm a bit unsure that we really want to know this information.  What is it's 
> use actually?  We should always implicitly know what type of certificate we 
> are giving to l_asymmetric_cipher_new, so it might just need to be a 
> parameter.

Two pieces of information are extracted: the key size (used by tls) and 
whether it's public or private. The public/private bit is a freebie when 
retrieving the key size. It used to be that the key size could be 
extracted the same way for both public and private keys.

After digging some more, there is a brand new way to query key information 
(including the length) from asymmetric keys stored in the kernel. If we 
switch to using that we wouldn't have to parse certs in userspace at all, 
which sounds like a win to me. Still wouldn't need to make the user 
designate public vs. private in l_asymmetric_new, since the kernel would 
know already.

>
>>
>>   	if (key_length < 8)
>>   		return false;
>>
>>   	/* Unpack the outer SEQUENCE */
>> -	der = der_find_elem((uint8_t *) key, key_length, 0, &tag, &n_length);
>> -	if (!der || tag != ASN1_ID_SEQUENCE)
>> +	seq = der_find_elem((uint8_t *) key, key_length, 0, &tag, 
>> &seq_length);
>> +	if (!seq || tag != ASN1_ID_SEQUENCE)
>>   		return false;
>> 
>> -	/* Take first INTEGER as the modulus */
>> -	der = der_find_elem(der, n_length, 0, &tag, &n_length);
>> +	/* First INTEGER may be a 1-byte version (for private key) or
>> +	 * the modulus (public key)
>> +	 */
>> +	der = der_find_elem(seq, seq_length, 0, &tag, &n_length);
>> +	if (der && tag == ASN1_ID_INTEGER && n_length == 1) {
>> +		/* Found version number, implies this is a private key. */
>> +		der = der_find_elem(seq, seq_length, 1, &tag, &n_length);
>> +		pubkey = false;
>> +	}
>> +
>>   	if (!der || tag != ASN1_ID_INTEGER || n_length < 4)
>>   		return false;
>> 
>> @@ -358,95 +381,11 @@ static bool parse_rsa_key(struct l_asymmetric_cipher 
>> *cipher, const void *key,
>>   	}
>>
>>   	cipher->key_size = n_length;
>
> This probably belongs as a setsockopt into the kernel...

See previous comment - found a way to query key length from the kernel.

>
>> +	cipher->public_key = pubkey;
>>
>>   	return true;
>>   }
>> 
>> -static void write_asn1_definite_length(uint8_t **buf, size_t len)
>> -{
>> -	int n;
>> -
>> -	if (len < 0x80) {
>> -		*(*buf)++ = len;
>> -
>> -		return;
>> -	}
>> -
>> -	for (n = 1; len >> (n * 8); n++);
>> -	*(*buf)++ = 0x80 | n;
>> -
>> -	while (n--)
>> -		*(*buf)++ = len >> (n * 8);
>> -}
>> -
>> -/*
>> - * Extract a ASN1 RsaKey-formatted public+private key structure in the
>> - * form used in the kernel.  It is simpler than the PKCS#1 form as it only
>> - * contains the N, E and D integers and also correctly parses as a PKCS#1
>> - * RSAPublicKey.
>> - */
>> -uint8_t *extract_rsakey(uint8_t *pkcs1_key, size_t pkcs1_key_len,
>> -			size_t *out_len)
>> -{
>> -	uint8_t *key, *ptr, *ver, *n, *e, *d;
>> -	uint8_t tag;
>> -	size_t ver_len, n_len, e_len, d_len;
>> -	int pos;
>> -
>> -	/* Unpack the outer SEQUENCE */
>> -	pkcs1_key = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag,
>> -					&pkcs1_key_len);
>> -	if (!pkcs1_key || tag != ASN1_ID_SEQUENCE)
>> -		return NULL;
>> -
>> -	/* Check if the version element if present */
>> -	ver = der_find_elem(pkcs1_key, pkcs1_key_len, 0, &tag, &ver_len);
>> -	if (!ver || tag != ASN1_ID_INTEGER)
>> -		return NULL;
>> -
>> -	pos = (ver_len == 1 && ver[0] == 0x00) ? 1 : 0;
>> -
>> -	n = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 0, &tag, &n_len);
>> -	if (!n || tag != ASN1_ID_INTEGER)
>> -		return NULL;
>> -
>> -	e = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 1, &tag, &e_len);
>> -	if (!e || tag != ASN1_ID_INTEGER)
>> -		return NULL;
>> -
>> -	d = der_find_elem(pkcs1_key, pkcs1_key_len, pos + 2, &tag, &d_len);
>> -	if (!d || tag != ASN1_ID_INTEGER)
>> -		return NULL;
>> -
>> -	/* New SEQUENCE length including tags and lengths */
>> -	*out_len = 1 + (n_len >= 0x80 ? n_len >= 0x100 ? 3 : 2 : 1) + n_len +
>> -		1 + (e_len >= 0x80 ? e_len >= 0x100 ? 3 : 2 : 1) + e_len +
>> -		1 + (d_len >= 0x80 ? d_len >= 0x100 ? 3 : 2 : 1) + d_len;
>> -	ptr = key = l_malloc(*out_len +
>> -		1 + (*out_len >= 0x80 ? *out_len >= 0x100 ? 3 : 2 : 1));
>> -
>> -	*ptr++ = ASN1_ID_SEQUENCE;
>> -	write_asn1_definite_length(&ptr, *out_len);
>> -
>> -	*ptr++ = ASN1_ID_INTEGER;
>> -	write_asn1_definite_length(&ptr, n_len);
>> -	memcpy(ptr, n, n_len);
>> -	ptr += n_len;
>> -
>> -	*ptr++ = ASN1_ID_INTEGER;
>> -	write_asn1_definite_length(&ptr, e_len);
>> -	memcpy(ptr, e, e_len);
>> -	ptr += e_len;
>> -
>> -	*ptr++ = ASN1_ID_INTEGER;
>> -	write_asn1_definite_length(&ptr, d_len);
>> -	memcpy(ptr, d, d_len);
>> -	ptr += d_len;
>> -
>> -	*out_len = ptr - key;
>> -	return key;
>> -}
>> -
>>   LIB_EXPORT struct l_asymmetric_cipher *l_asymmetric_cipher_new(
>>   					enum l_asymmetric_cipher_type type,
>>   					const void *key, size_t key_length)
>> @@ -473,14 +412,18 @@ LIB_EXPORT struct l_asymmetric_cipher 
>> *l_asymmetric_cipher_new(
>>   	}
>>
>>   	cipher->cipher.encrypt_sk = create_alg("akcipher", alg_name,
>> -						key, key_length);
>> +						key, key_length,
>> +						cipher->public_key);
>>   	if (cipher->cipher.encrypt_sk < 0)
>>   		goto error_free;
>> 
>> -	cipher->cipher.decrypt_sk = create_alg("akcipher", alg_name,
>> -						key, key_length);
>> -	if (cipher->cipher.decrypt_sk < 0)
>> -		goto error_close;
>> +	if (!cipher->public_key) {
>> +		cipher->cipher.decrypt_sk = create_alg("akcipher", alg_name,
>> +							key, key_length,
>> +							cipher->public_key);
>> +		if (cipher->cipher.decrypt_sk < 0)
>> +			goto error_close;
>> +	}
>>
>>   	return cipher;
>> 
>> @@ -508,151 +451,52 @@ LIB_EXPORT int l_asymmetric_cipher_get_key_size(
>>   	return cipher->key_size;
>>   }
>> 
>> -static void getrandom_nonzero(uint8_t *buf, int len)
>> -{
>> -	while (len--) {
>> -		l_getrandom(buf, 1);
>> -		while (buf[0] == 0)
>> -			l_getrandom(buf, 1);
>> -
>> -		buf++;
>> -	}
>> -}
>> -
>> -LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher 
>> *cipher,
>> +LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher 
>> *acipher,
>>   					const void *in, void *out,
>>   					size_t len_in, size_t len_out)
>>   {
>> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
>> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
>> -		uint8_t buf[cipher->key_size];
>> -		int ps_len = cipher->key_size - len_in - 3;
>> -
>> -		if (len_in > (size_t) cipher->key_size - 11)
>> -			return false;
>> -		if (len_out != (size_t) cipher->key_size)
>> -			return false;
>> -
>> -		buf[0] = 0x00;
>> -		buf[1] = 0x02;
>> -		getrandom_nonzero(buf + 2, ps_len);
>> -		buf[ps_len + 2] = 0x00;
>> -		memcpy(buf + ps_len + 3, in, len_in);
>> -
>> -		if (!l_cipher_encrypt(&cipher->cipher, buf, out,
>> -					cipher->key_size))
>> -			return false;
>> -	}
>> +	if (unlikely(!acipher))
>> +		return false;
>> 
>> -	return true;
>> +	if (unlikely(!in) || unlikely(!out))
>> +		return false;
>> +
>> +	return operate_cipher(acipher->cipher.encrypt_sk, ALG_OP_ENCRYPT,
>> +				in, out, len_in, len_out);
>>   }
>> 
>> -LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher 
>> *cipher,
>> +LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher 
>> *acipher,
>>   					const void *in, void *out,
>>   					size_t len_in, size_t len_out)
>>   {
>> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
>> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
>> -		uint8_t buf[cipher->key_size];
>> -		int pos;
>> -
>> -		if (len_in != (size_t) cipher->key_size)
>> -			return false;
>> -
>> -		if (!l_cipher_decrypt(&cipher->cipher, in, buf,
>> -					cipher->key_size))
>> -			return false;
>> -
>> -		if (buf[0] != 0x00)
>> -			return false;
>> -		if (buf[1] != 0x02)
>> -			return false;
>> -
>> -		for (pos = 2; pos < cipher->key_size; pos++)
>> -			if (buf[pos] == 0)
>> -				break;
>> -		if (pos < 10 || pos == cipher->key_size)
>> -			return false;
>> -
>> -		pos++;
>> -		if (len_out != (size_t) cipher->key_size - pos)
>> -			return false;
>> -
>> -		memcpy(out, buf + pos, cipher->key_size - pos);
>> -	}
>
> I'm all for getting rid of the padding stuff, but as mentioned previously, 
> I'm not sure the pkcs1pad template is part of the rsa akcipher by default. 
> Is it?

I thought it was, but now I'm not sure. The kernel seemed to object if the 
data was padded out to the full length. I'm digging more to confirm 
what's actually happening, but I probably have to pass in pkcs1pad(rsa) as 
the alg name.

>
>> +	if (unlikely(!acipher))
>> +		return false;
>> 
>> -	return true;
>> +	if (unlikely(!in) || unlikely(!out))
>> +		return false;
>> +
>> +	return operate_cipher(acipher->cipher.decrypt_sk, ALG_OP_DECRYPT,
>> +				in, out, len_in, len_out);
>>   }
>>
>>   LIB_EXPORT bool l_asymmetric_cipher_sign(struct l_asymmetric_cipher 
>> *cipher,
>>   					const void *in, void *out,
>>   					size_t len_in, size_t len_out)
>>   {
>> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
>> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
>> -		uint8_t buf[cipher->key_size];
>> -		int ps_len = cipher->key_size - len_in - 3;
>> -
>> -		if (len_in > (size_t) cipher->key_size - 11)
>> -			return false;
>> -		if (len_out != (size_t) cipher->key_size)
>> -			return false;
>> -
>> -		buf[0] = 0x00;
>> -		buf[1] = 0x01;
>> -		memset(buf + 2, 0xff, ps_len);
>> -		buf[ps_len + 2] = 0x00;
>> -		memcpy(buf + ps_len + 3, in, len_in);
>> -
>> -		/*
>> -		 * The RSA signing operation uses the same primitive as
>> -		 * decryption so just call decrypt for now.
>> -		 */
>> -		if (!l_cipher_decrypt(&cipher->cipher, buf, out,
>> -					cipher->key_size))
>> -			return false;
>> -	}
>> -
>> -	return true;
>> +	/*
>> +	 * The RSA signing operation uses the same primitive as
>> +	 * decryption so just call decrypt for now.
>> +	 */
>> +	return l_asymmetric_cipher_decrypt(cipher, in, out, len_in, len_out);
>>   }
>>
>>   LIB_EXPORT bool l_asymmetric_cipher_verify(struct l_asymmetric_cipher 
>> *cipher,
>>   					const void *in, void *out,
>>   					size_t len_in, size_t len_out)
>>   {
>> -	if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
>> -		/* PKCS#1 v1.5 RSA padding according to RFC3447 */
>> -		uint8_t buf[cipher->key_size];
>> -		int pos;
>> -
>> -		if (len_in != (size_t) cipher->key_size)
>> -			return false;
>> -
>> -		/*
>> -		 * The RSA verify operation uses the same primitive as
>> -		 * encryption so just call encrypt.
>> -		 */
>> -		if (!l_cipher_encrypt(&cipher->cipher, in, buf,
>> -					cipher->key_size))
>> -			return false;
>> -
>> -		if (buf[0] != 0x00)
>> -			return false;
>> -		if (buf[1] != 0x01)
>> -			return false;
>> -
>> -		for (pos = 2; pos < cipher->key_size; pos++)
>> -			if (buf[pos] != 0xff)
>> -				break;
>> -		if (pos < 10 || pos == cipher->key_size || buf[pos] != 0)
>> -			return false;
>> -
>> -		pos++;
>> -		if (len_out != (size_t) cipher->key_size - pos)
>> -			return false;
>> -
>> -		memcpy(out, buf + pos, cipher->key_size - pos);
>> -	}
>> -
>> -	return true;
>> +	/*
>> +	 * The RSA verify operation uses the same primitive as
>> +	 * encryption so just call encrypt.
>> +	 */
>> +	return l_asymmetric_cipher_encrypt(cipher, in, out, len_in, len_out);
>>   }
>> diff --git a/ell/tls.c b/ell/tls.c
>> index e47e8bf..6896a05 100644
>> --- a/ell/tls.c
>> +++ b/ell/tls.c
>> @@ -918,8 +918,8 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t 
>> **out,
>>   				tls_get_hash_t get_hash)
>>   {
>>   	struct l_asymmetric_cipher *rsa_privkey;
>> -	uint8_t *privkey, *privkey_short;
>> -	size_t key_size, short_size;
>> +	uint8_t *privkey;
>> +	size_t key_size;
>>   	bool result;
>>   	const struct tls_hash_algorithm *hash_type;
>>   	uint8_t hash[HANDSHAKE_HASH_MAX_SIZE];
>> @@ -943,19 +943,9 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t 
>> **out,
>>   		return false;
>>   	}
>> 
>> -	privkey_short = extract_rsakey(privkey, key_size, &short_size);
>> -	tls_free_key(privkey, key_size);
>> -
>> -	if (!privkey_short) {
>> -		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
>> -				TLS_ALERT_BAD_CERT);
>> -
>> -		return false;
>> -	}
>> -
>>   	rsa_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
>> -						privkey_short, short_size);
>> -	tls_free_key(privkey_short, short_size);
>> +						privkey, key_size);
>> +	tls_free_key(privkey, key_size);
>>
>>   	if (!rsa_privkey) {
>>   		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>
> Should we be reporting BAD_CERT here?

A bad cert is one of several reasons l_asymmetric_cipher_new can currently 
fail. It will be easier to identify a BAD_CERT condition when using the 
kernel to determine key size, so I will keep that in mind.

>
>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls, const 
>> uint8_t *in, size_t len,
>>   		 */
>>   	}
>> 
>> -	digest_info = alloca(expected_len);
>> +	if (expected_len > key_size)
>> +		goto err_free_rsa;
>> +
>> +	digest_info = alloca(key_size);
>
> This looks like a separate fix and belongs in a separate patch.
>

What happened here is that the kernel no longer lets you read only 
the amount of data you're expecting - you need to read the maximum size 
you might get. And if I'm telling the kernel to read a potentially larger 
number of bytes, there needs to be a big enough buffer for it.

>>
>>   	result = l_asymmetric_cipher_verify(rsa_client_pubkey, in + 4,
>>   						digest_info,
>> -						key_size, expected_len);
>> +						key_size, key_size);
>
> Same here?

Yes, this also belongs here.

>
>>
>>   	l_asymmetric_cipher_free(rsa_client_pubkey);
>> 
>> @@ -1741,8 +1734,8 @@ static void tls_handle_rsa_client_key_xchg(struct 
>> l_tls *tls,
>>   {
>>   	uint8_t pre_master_secret[48], random_secret[46];
>>   	struct l_asymmetric_cipher *rsa_server_privkey;
>> -	uint8_t *privkey, *privkey_short;
>> -	size_t key_size, short_size;
>> +	uint8_t *privkey;
>> +	size_t key_size;
>>   	bool result;
>>
>>   	if (!tls->priv_key_path) {
>> @@ -1762,19 +1755,9 @@ static void tls_handle_rsa_client_key_xchg(struct 
>> l_tls *tls,
>>   		return;
>>   	}
>> 
>> -	privkey_short = extract_rsakey(privkey, key_size, &short_size);
>> -	tls_free_key(privkey, key_size);
>> -
>> -	if (!privkey_short) {
>> -		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
>> -				TLS_ALERT_BAD_CERT);
>> -
>> -		return;
>> -	}
>> -
>>   	rsa_server_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
>> -						privkey_short, short_size);
>> -	tls_free_key(privkey_short, short_size);
>> +							privkey, key_size);
>> +	tls_free_key(privkey, key_size);
>>
>>   	if (!rsa_server_privkey) {
>>   		tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>>

--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-07 19:10     ` Mat Martineau
@ 2016-06-07 19:32       ` Denis Kenzior
  2016-06-08  0:18         ` Mat Martineau
  0 siblings, 1 reply; 24+ messages in thread
From: Denis Kenzior @ 2016-06-07 19:32 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2499 bytes --]

Hi Mat,

 >>
>> I'm a bit unsure that we really want to know this information.  What
>> is it's use actually?  We should always implicitly know what type of
>> certificate we are giving to l_asymmetric_cipher_new, so it might just
>> need to be a parameter.
>
> Two pieces of information are extracted: the key size (used by tls) and
> whether it's public or private. The public/private bit is a freebie when
> retrieving the key size. It used to be that the key size could be
> extracted the same way for both public and private keys.
>
> After digging some more, there is a brand new way to query key
> information (including the length) from asymmetric keys stored in the
> kernel. If we switch to using that we wouldn't have to parse certs in

I'd like to see akcipher (and maybe even skcipher) support obtaining of 
the key size via a getsockopt.  Just seems like a good idea.

> userspace at all, which sounds like a win to me. Still wouldn't need to
> make the user designate public vs. private in l_asymmetric_new, since
> the kernel would know already.

Don't we need to know whether the sign/verify operations are available, 
or just the verify?

>> I'm all for getting rid of the padding stuff, but as mentioned
>> previously, I'm not sure the pkcs1pad template is part of the rsa
>> akcipher by default. Is it?
>
> I thought it was, but now I'm not sure. The kernel seemed to object if
> the data was padded out to the full length. I'm digging more to confirm
> what's actually happening, but I probably have to pass in pkcs1pad(rsa)
> as the alg name.
>

That is what I thought.  I think Andrew mentioned that this wasn't yet 
exposed to user space.

>>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>>> const uint8_t *in, size_t len,
>>>            */
>>>       }
>>>
>>> -    digest_info = alloca(expected_len);
>>> +    if (expected_len > key_size)
>>> +        goto err_free_rsa;
>>> +
>>> +    digest_info = alloca(key_size);
>>
>> This looks like a separate fix and belongs in a separate patch.
>>
>
> What happened here is that the kernel no longer lets you read only the
> amount of data you're expecting - you need to read the maximum size you
> might get. And if I'm telling the kernel to read a potentially larger
> number of bytes, there needs to be a big enough buffer for it.
>

This still feels wrong to me.  Are you sure its not related to the 
PKCS1.5 padding ?

Regards,
-Denis

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-07 17:51   ` Denis Kenzior
  2016-06-07 19:10     ` Mat Martineau
@ 2016-06-07 21:47     ` Andrzej Zaborowski
  2016-06-07 22:23       ` Denis Kenzior
  1 sibling, 1 reply; 24+ messages in thread
From: Andrzej Zaborowski @ 2016-06-07 21:47 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 8082 bytes --]

Hi Denis and Mat,

On 7 June 2016 at 19:51, Denis Kenzior <denkenz@gmail.com> wrote:
> On 06/06/2016 03:54 PM, Mat Martineau wrote:
>> @@ -508,151 +451,52 @@ LIB_EXPORT int l_asymmetric_cipher_get_key_size(
>>         return cipher->key_size;
>>   }
>>
>> -static void getrandom_nonzero(uint8_t *buf, int len)
>> -{
>> -       while (len--) {
>> -               l_getrandom(buf, 1);
>> -               while (buf[0] == 0)
>> -                       l_getrandom(buf, 1);
>> -
>> -               buf++;
>> -       }
>> -}
>> -
>> -LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher
>> *cipher,
>> +LIB_EXPORT bool l_asymmetric_cipher_encrypt(struct l_asymmetric_cipher
>> *acipher,
>>                                         const void *in, void *out,
>>                                         size_t len_in, size_t len_out)
>>   {
>> -       if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
>> -               /* PKCS#1 v1.5 RSA padding according to RFC3447 */
>> -               uint8_t buf[cipher->key_size];
>> -               int ps_len = cipher->key_size - len_in - 3;
>> -
>> -               if (len_in > (size_t) cipher->key_size - 11)
>> -                       return false;
>> -               if (len_out != (size_t) cipher->key_size)
>> -                       return false;
>> -
>> -               buf[0] = 0x00;
>> -               buf[1] = 0x02;
>> -               getrandom_nonzero(buf + 2, ps_len);
>> -               buf[ps_len + 2] = 0x00;
>> -               memcpy(buf + ps_len + 3, in, len_in);
>> -
>> -               if (!l_cipher_encrypt(&cipher->cipher, buf, out,
>> -                                       cipher->key_size))
>> -                       return false;
>> -       }
>> +       if (unlikely(!acipher))
>> +               return false;
>>
>> -       return true;
>> +       if (unlikely(!in) || unlikely(!out))
>> +               return false;
>> +
>> +       return operate_cipher(acipher->cipher.encrypt_sk, ALG_OP_ENCRYPT,
>> +                               in, out, len_in, len_out);
>>   }
>>
>> -LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher
>> *cipher,
>> +LIB_EXPORT bool l_asymmetric_cipher_decrypt(struct l_asymmetric_cipher
>> *acipher,
>>                                         const void *in, void *out,
>>                                         size_t len_in, size_t len_out)
>>   {
>> -       if (cipher->cipher.type == L_CIPHER_RSA_PKCS1_V1_5) {
>> -               /* PKCS#1 v1.5 RSA padding according to RFC3447 */
>> -               uint8_t buf[cipher->key_size];
>> -               int pos;
>> -
>> -               if (len_in != (size_t) cipher->key_size)
>> -                       return false;
>> -
>> -               if (!l_cipher_decrypt(&cipher->cipher, in, buf,
>> -                                       cipher->key_size))
>> -                       return false;
>> -
>> -               if (buf[0] != 0x00)
>> -                       return false;
>> -               if (buf[1] != 0x02)
>> -                       return false;
>> -
>> -               for (pos = 2; pos < cipher->key_size; pos++)
>> -                       if (buf[pos] == 0)
>> -                               break;
>> -               if (pos < 10 || pos == cipher->key_size)
>> -                       return false;
>> -
>> -               pos++;
>> -               if (len_out != (size_t) cipher->key_size - pos)
>> -                       return false;
>> -
>> -               memcpy(out, buf + pos, cipher->key_size - pos);
>> -       }
>
>
> I'm all for getting rid of the padding stuff, but as mentioned previously,
> I'm not sure the pkcs1pad template is part of the rsa akcipher by default.
> Is it?

I believe the "rsa" cipher does not include padding and
"pkcs1pad(rsa)" does and now there's also a "pkcs1pad(rsa, <hash
type>)" that could save as a little more work in the TLS code if we
only supported TLS 1.2 but can't be used for < 1.2.

>

>> @@ -943,19 +943,9 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t
>> **out,
>>                 return false;
>>         }
>>
>> -       privkey_short = extract_rsakey(privkey, key_size, &short_size);
>> -       tls_free_key(privkey, key_size);
>> -
>> -       if (!privkey_short) {
>> -               tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
>> -                               TLS_ALERT_BAD_CERT);
>> -
>> -               return false;
>> -       }
>> -
>>         rsa_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
>> -                                               privkey_short,
>> short_size);
>> -       tls_free_key(privkey_short, short_size);
>> +                                               privkey, key_size);
>> +       tls_free_key(privkey, key_size);
>>
>>         if (!rsa_privkey) {
>>                 tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>
>
> Should we be reporting BAD_CERT here?

I'm not sure if you mean BAD_CERT as the second or third parameter but
I don't think we should do either.  Passing BAD_CERT to the remote end
implies it that it has supplied a bad certificate and the disconnect
is their fault.  Passing BAD_CERT to our higher layer will imply that
our certificate is wrong.  In reality the problem here is most likely
kernel configuration.

>
>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>> const uint8_t *in, size_t len,
>>                  */
>>         }
>>
>> -       digest_info = alloca(expected_len);
>> +       if (expected_len > key_size)
>> +               goto err_free_rsa;
>> +
>> +       digest_info = alloca(key_size);
>
>
> This looks like a separate fix and belongs in a separate patch.
>
>>
>>         result = l_asymmetric_cipher_verify(rsa_client_pubkey, in + 4,
>>                                                 digest_info,
>> -                                               key_size, expected_len);
>> +                                               key_size, key_size);
>
>
> Same here?

expected_len and key_size are almost certainly not equal.  Why are we
expecing a digest_info of the same size as the key?  if the kernel now
always returns data padded to key_size perhaps our cipher layer should
remove that padding.  Also if the kernel is not checking the output
length anymore then perhaps we need to check it's correct.

>
>
>>
>>         l_asymmetric_cipher_free(rsa_client_pubkey);
>>
>> @@ -1741,8 +1734,8 @@ static void tls_handle_rsa_client_key_xchg(struct
>> l_tls *tls,
>>   {
>>         uint8_t pre_master_secret[48], random_secret[46];
>>         struct l_asymmetric_cipher *rsa_server_privkey;
>> -       uint8_t *privkey, *privkey_short;
>> -       size_t key_size, short_size;
>> +       uint8_t *privkey;
>> +       size_t key_size;
>>         bool result;
>>
>>         if (!tls->priv_key_path) {
>> @@ -1762,19 +1755,9 @@ static void tls_handle_rsa_client_key_xchg(struct
>> l_tls *tls,
>>                 return;
>>         }
>>
>> -       privkey_short = extract_rsakey(privkey, key_size, &short_size);
>> -       tls_free_key(privkey, key_size);
>> -
>> -       if (!privkey_short) {
>> -               tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
>> -                               TLS_ALERT_BAD_CERT);
>> -
>> -               return;
>> -       }
>> -
>>         rsa_server_privkey =
>> l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
>> -                                               privkey_short,
>> short_size);
>> -       tls_free_key(privkey_short, short_size);
>> +                                                       privkey,
>> key_size);
>> +       tls_free_key(privkey, key_size);
>>
>>         if (!rsa_server_privkey) {
>>                 tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>>
>
> Regards,
> -Denis
>
> _______________________________________________
> ell mailing list
> ell(a)lists.01.org
> https://lists.01.org/mailman/listinfo/ell

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-07 21:47     ` Andrzej Zaborowski
@ 2016-06-07 22:23       ` Denis Kenzior
  2016-06-07 22:43         ` Andrzej Zaborowski
  0 siblings, 1 reply; 24+ messages in thread
From: Denis Kenzior @ 2016-06-07 22:23 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2089 bytes --]

Hi Andrew,
 >
> I believe the "rsa" cipher does not include padding and
> "pkcs1pad(rsa)" does and now there's also a "pkcs1pad(rsa, <hash
> type>)" that could save as a little more work in the TLS code if we
> only supported TLS 1.2 but can't be used for < 1.2.

I wonder if keyctl can expose the hash for us as well.  Either way, we 
should take advantage of this if possible.

>
>>
>
>>> @@ -943,19 +943,9 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t
>>> **out,
>>>                  return false;
>>>          }
>>>
>>> -       privkey_short = extract_rsakey(privkey, key_size, &short_size);
>>> -       tls_free_key(privkey, key_size);
>>> -
>>> -       if (!privkey_short) {
>>> -               tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
>>> -                               TLS_ALERT_BAD_CERT);
>>> -
>>> -               return false;
>>> -       }
>>> -
>>>          rsa_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
>>> -                                               privkey_short,
>>> short_size);
>>> -       tls_free_key(privkey_short, short_size);
>>> +                                               privkey, key_size);
>>> +       tls_free_key(privkey, key_size);
>>>
>>>          if (!rsa_privkey) {
>>>                  tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>>
>>
>> Should we be reporting BAD_CERT here?
>
> I'm not sure if you mean BAD_CERT as the second or third parameter but

Third parameter.  Mat took out the code that returned BAD_CERT if 
extract_rsakey failed.  So now if the asymmetric cipher creation fails, 
we have to assume that the certificate is bad (or a configuration issue).

> I don't think we should do either.  Passing BAD_CERT to the remote end
> implies it that it has supplied a bad certificate and the disconnect
> is their fault.  Passing BAD_CERT to our higher layer will imply that
> our certificate is wrong.  In reality the problem here is most likely
> kernel configuration.

Or that the remote has given us a bad certificate :)

Regards,
-Denis

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-07 22:23       ` Denis Kenzior
@ 2016-06-07 22:43         ` Andrzej Zaborowski
  0 siblings, 0 replies; 24+ messages in thread
From: Andrzej Zaborowski @ 2016-06-07 22:43 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2594 bytes --]

Hi Denis,

On 8 June 2016 at 00:23, Denis Kenzior <denkenz@gmail.com> wrote:
> Hi Andrew,
>>
>>
>> I believe the "rsa" cipher does not include padding and
>> "pkcs1pad(rsa)" does and now there's also a "pkcs1pad(rsa, <hash
>> type>)" that could save as a little more work in the TLS code if we
>> only supported TLS 1.2 but can't be used for < 1.2.
>
>
> I wonder if keyctl can expose the hash for us as well.  Either way, we
> should take advantage of this if possible.

Since it would only work for TLS 1.2 I think it's easier to not use it
so we can share more code between 1.2 and pre 1.2.

>
>>
>>>
>>
>>>> @@ -943,19 +943,9 @@ static bool tls_rsa_sign(struct l_tls *tls, uint8_t
>>>> **out,
>>>>                  return false;
>>>>          }
>>>>
>>>> -       privkey_short = extract_rsakey(privkey, key_size, &short_size);
>>>> -       tls_free_key(privkey, key_size);
>>>> -
>>>> -       if (!privkey_short) {
>>>> -               tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR,
>>>> -                               TLS_ALERT_BAD_CERT);
>>>> -
>>>> -               return false;
>>>> -       }
>>>> -
>>>>          rsa_privkey = l_asymmetric_cipher_new(L_CIPHER_RSA_PKCS1_V1_5,
>>>> -                                               privkey_short,
>>>> short_size);
>>>> -       tls_free_key(privkey_short, short_size);
>>>> +                                               privkey, key_size);
>>>> +       tls_free_key(privkey, key_size);
>>>>
>>>>          if (!rsa_privkey) {
>>>>                  tls_disconnect(tls, TLS_ALERT_INTERNAL_ERROR, 0);
>>>
>>>
>>>
>>> Should we be reporting BAD_CERT here?
>>
>>
>> I'm not sure if you mean BAD_CERT as the second or third parameter but
>
>
> Third parameter.  Mat took out the code that returned BAD_CERT if
> extract_rsakey failed.  So now if the asymmetric cipher creation fails, we
> have to assume that the certificate is bad (or a configuration issue).

Oh, right.  So l_asymmetric_cipher_new will fail if either the kernel
doesn't support the API we want or the if the key format is bad.

>
>> I don't think we should do either.  Passing BAD_CERT to the remote end
>> implies it that it has supplied a bad certificate and the disconnect
>> is their fault.  Passing BAD_CERT to our higher layer will imply that
>> our certificate is wrong.  In reality the problem here is most likely
>> kernel configuration.
>
>
> Or that the remote has given us a bad certificate :)

The disconnect callback receives a flag that will tell it it's a local error.

Best regards

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-07 19:32       ` Denis Kenzior
@ 2016-06-08  0:18         ` Mat Martineau
  2016-06-09 20:20           ` Mat Martineau
  0 siblings, 1 reply; 24+ messages in thread
From: Mat Martineau @ 2016-06-08  0:18 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 3602 bytes --]

On Tue, 7 Jun 2016, Denis Kenzior wrote:

> Hi Mat,
>
>>>
>>> I'm a bit unsure that we really want to know this information.  What
>>> is it's use actually?  We should always implicitly know what type of
>>> certificate we are giving to l_asymmetric_cipher_new, so it might just
>>> need to be a parameter.
>> 
>> Two pieces of information are extracted: the key size (used by tls) and
>> whether it's public or private. The public/private bit is a freebie when
>> retrieving the key size. It used to be that the key size could be
>> extracted the same way for both public and private keys.
>> 
>> After digging some more, there is a brand new way to query key
>> information (including the length) from asymmetric keys stored in the
>> kernel. If we switch to using that we wouldn't have to parse certs in
>
> I'd like to see akcipher (and maybe even skcipher) support obtaining of the 
> key size via a getsockopt.  Just seems like a good idea.

It helps that there's an internal API for this: crypto_akcipher_maxsize(). 
AF_ALG doesn't currently have any getsockopt handler, unfortunately. I'll 
see if the AF_ALG akcipher contributors will help push for it too.

>
>> userspace at all, which sounds like a win to me. Still wouldn't need to
>> make the user designate public vs. private in l_asymmetric_new, since
>> the kernel would know already.
>
> Don't we need to know whether the sign/verify operations are available, or 
> just the verify?

Sure, but that doesn't mean the caller of l_asymmetric_new needs to tell 
us whether it's a private key or not. We send the key to the kernel and 
ask the kernel which of encrypt/decrypt/sign/verify are available when 
using that key.

>
>>> I'm all for getting rid of the padding stuff, but as mentioned
>>> previously, I'm not sure the pkcs1pad template is part of the rsa
>>> akcipher by default. Is it?
>> 
>> I thought it was, but now I'm not sure. The kernel seemed to object if
>> the data was padded out to the full length. I'm digging more to confirm
>> what's actually happening, but I probably have to pass in pkcs1pad(rsa)
>> as the alg name.
>> 
>
> That is what I thought.  I think Andrew mentioned that this wasn't yet 
> exposed to user space.
>
>>>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>>>> const uint8_t *in, size_t len,
>>>>            */
>>>>       }
>>>> 
>>>> -    digest_info = alloca(expected_len);
>>>> +    if (expected_len > key_size)
>>>> +        goto err_free_rsa;
>>>> +
>>>> +    digest_info = alloca(key_size);
>>> 
>>> This looks like a separate fix and belongs in a separate patch.
>>> 
>> 
>> What happened here is that the kernel no longer lets you read only the
>> amount of data you're expecting - you need to read the maximum size you
>> might get. And if I'm telling the kernel to read a potentially larger
>> number of bytes, there needs to be a big enough buffer for it.
>> 
>
> This still feels wrong to me.  Are you sure its not related to the PKCS1.5 
> padding ?

Yes. akcipher_recvmsg() does this check before invoking any crypto ops:

         /* ensure output buffer is sufficiently large */
         if (usedpages < akcipher_calcsize(ctx)) {
                 err = -EMSGSIZE;
                 goto unlock;
         }

(where akcipher_calcsize() returns the key size in bytes when using RSA)

I'm not sure why, since the length of the destination buffer gets 
propagated to the crypto algorithm and it could decide what to do. I'll 
ask Stephan.

--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-08  0:18         ` Mat Martineau
@ 2016-06-09 20:20           ` Mat Martineau
  2016-06-09 21:06             ` Denis Kenzior
  2016-06-09 21:20             ` Andrzej Zaborowski
  0 siblings, 2 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-09 20:20 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 1798 bytes --]

On Tue, 7 Jun 2016, Mat Martineau wrote:

> On Tue, 7 Jun 2016, Denis Kenzior wrote:
>>>>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>>>>> const uint8_t *in, size_t len,
>>>>>            */
>>>>>       }
>>>>> 
>>>>> -    digest_info = alloca(expected_len);
>>>>> +    if (expected_len > key_size)
>>>>> +        goto err_free_rsa;
>>>>> +
>>>>> +    digest_info = alloca(key_size);
>>>> 
>>>> This looks like a separate fix and belongs in a separate patch.
>>>> 
>>> 
>>> What happened here is that the kernel no longer lets you read only the
>>> amount of data you're expecting - you need to read the maximum size you
>>> might get. And if I'm telling the kernel to read a potentially larger
>>> number of bytes, there needs to be a big enough buffer for it.
>>> 
>> 
>> This still feels wrong to me.  Are you sure its not related to the PKCS1.5 
>> padding ?
>
> Yes. akcipher_recvmsg() does this check before invoking any crypto ops:
>
>        /* ensure output buffer is sufficiently large */
>        if (usedpages < akcipher_calcsize(ctx)) {
>                err = -EMSGSIZE;
>                goto unlock;
>        }
>
> (where akcipher_calcsize() returns the key size in bytes when using RSA)
>
> I'm not sure why, since the length of the destination buffer gets propagated 
> to the crypto algorithm and it could decide what to do. I'll ask Stephan.

I convinced the author to drop this extra length check. This means we can 
do short reads when using RSA software crypto. However, I see that 
hardware drivers can require the full length output buffer anyway 
(probably because of how the hardware handles DMA access) - so we 
sacrifice compatibility if we use a smaller read buffer.

--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-09 20:20           ` Mat Martineau
@ 2016-06-09 21:06             ` Denis Kenzior
  2016-06-09 21:18               ` Mat Martineau
  2016-06-09 21:20             ` Andrzej Zaborowski
  1 sibling, 1 reply; 24+ messages in thread
From: Denis Kenzior @ 2016-06-09 21:06 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2073 bytes --]

Hi Mat, Andrew,

On 06/09/2016 03:20 PM, Mat Martineau wrote:
> On Tue, 7 Jun 2016, Mat Martineau wrote:
>
>> On Tue, 7 Jun 2016, Denis Kenzior wrote:
>>>>>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>>>>>> const uint8_t *in, size_t len,
>>>>>>            */
>>>>>>       }
>>>>>>
>>>>>> -    digest_info = alloca(expected_len);
>>>>>> +    if (expected_len > key_size)
>>>>>> +        goto err_free_rsa;
>>>>>> +
>>>>>> +    digest_info = alloca(key_size);
>>>>>
>>>>> This looks like a separate fix and belongs in a separate patch.
>>>>>
>>>>
>>>> What happened here is that the kernel no longer lets you read only the
>>>> amount of data you're expecting - you need to read the maximum size you
>>>> might get. And if I'm telling the kernel to read a potentially larger
>>>> number of bytes, there needs to be a big enough buffer for it.
>>>>
>>>
>>> This still feels wrong to me.  Are you sure its not related to the
>>> PKCS1.5 padding ?
>>
>> Yes. akcipher_recvmsg() does this check before invoking any crypto ops:
>>
>>        /* ensure output buffer is sufficiently large */
>>        if (usedpages < akcipher_calcsize(ctx)) {
>>                err = -EMSGSIZE;
>>                goto unlock;
>>        }
>>
>> (where akcipher_calcsize() returns the key size in bytes when using RSA)
>>
>> I'm not sure why, since the length of the destination buffer gets
>> propagated to the crypto algorithm and it could decide what to do.
>> I'll ask Stephan.
>
> I convinced the author to drop this extra length check. This means we
> can do short reads when using RSA software crypto. However, I see that
> hardware drivers can require the full length output buffer anyway
> (probably because of how the hardware handles DMA access) - so we
> sacrifice compatibility if we use a smaller read buffer.

We still have the issue of pkcs1 pad template...

But my opinion is: 'If this is needed, then this is needed.'  So I have 
no problem doing it this way.

Andrew, thoughts?

Regards,
-Denis

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-09 21:06             ` Denis Kenzior
@ 2016-06-09 21:18               ` Mat Martineau
  0 siblings, 0 replies; 24+ messages in thread
From: Mat Martineau @ 2016-06-09 21:18 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2355 bytes --]

On Thu, 9 Jun 2016, Denis Kenzior wrote:

> Hi Mat, Andrew,
>
> On 06/09/2016 03:20 PM, Mat Martineau wrote:
>> On Tue, 7 Jun 2016, Mat Martineau wrote:
>> 
>>> On Tue, 7 Jun 2016, Denis Kenzior wrote:
>>>>>>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>>>>>>> const uint8_t *in, size_t len,
>>>>>>>            */
>>>>>>>       }
>>>>>>> 
>>>>>>> -    digest_info = alloca(expected_len);
>>>>>>> +    if (expected_len > key_size)
>>>>>>> +        goto err_free_rsa;
>>>>>>> +
>>>>>>> +    digest_info = alloca(key_size);
>>>>>> 
>>>>>> This looks like a separate fix and belongs in a separate patch.
>>>>>> 
>>>>> 
>>>>> What happened here is that the kernel no longer lets you read only the
>>>>> amount of data you're expecting - you need to read the maximum size you
>>>>> might get. And if I'm telling the kernel to read a potentially larger
>>>>> number of bytes, there needs to be a big enough buffer for it.
>>>>> 
>>>> 
>>>> This still feels wrong to me.  Are you sure its not related to the
>>>> PKCS1.5 padding ?
>>> 
>>> Yes. akcipher_recvmsg() does this check before invoking any crypto ops:
>>>
>>>        /* ensure output buffer is sufficiently large */
>>>        if (usedpages < akcipher_calcsize(ctx)) {
>>>                err = -EMSGSIZE;
>>>                goto unlock;
>>>        }
>>> 
>>> (where akcipher_calcsize() returns the key size in bytes when using RSA)
>>> 
>>> I'm not sure why, since the length of the destination buffer gets
>>> propagated to the crypto algorithm and it could decide what to do.
>>> I'll ask Stephan.
>> 
>> I convinced the author to drop this extra length check. This means we
>> can do short reads when using RSA software crypto. However, I see that
>> hardware drivers can require the full length output buffer anyway
>> (probably because of how the hardware handles DMA access) - so we
>> sacrifice compatibility if we use a smaller read buffer.
>
> We still have the issue of pkcs1 pad template...

I think I have that fixed, but I'm also updating the unit test to compare 
ELL asymmetric encryption results against known-correct encrypted data.

> But my opinion is: 'If this is needed, then this is needed.'  So I have no 
> problem doing it this way.
>
> Andrew, thoughts?



--
Mat Martineau
Intel OTC

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 08/11] cipher: Update for current kernel akcipher interface
  2016-06-09 20:20           ` Mat Martineau
  2016-06-09 21:06             ` Denis Kenzior
@ 2016-06-09 21:20             ` Andrzej Zaborowski
  1 sibling, 0 replies; 24+ messages in thread
From: Andrzej Zaborowski @ 2016-06-09 21:20 UTC (permalink / raw)
  To: ell

[-- Attachment #1: Type: text/plain, Size: 2703 bytes --]

Hi Mat,

On 9 June 2016 at 22:20, Mat Martineau
<mathew.j.martineau@linux.intel.com> wrote:
> On Tue, 7 Jun 2016, Mat Martineau wrote:
>> On Tue, 7 Jun 2016, Denis Kenzior wrote:
>>>>>>
>>>>>> @@ -1078,11 +1068,14 @@ static bool tls_rsa_verify(struct l_tls *tls,
>>>>>> const uint8_t *in, size_t len,
>>>>>>            */
>>>>>>       }
>>>>>>
>>>>>> -    digest_info = alloca(expected_len);
>>>>>> +    if (expected_len > key_size)
>>>>>> +        goto err_free_rsa;
>>>>>> +
>>>>>> +    digest_info = alloca(key_size);
>>>>>
>>>>>
>>>>> This looks like a separate fix and belongs in a separate patch.
>>>>>
>>>>
>>>> What happened here is that the kernel no longer lets you read only the
>>>> amount of data you're expecting - you need to read the maximum size you
>>>> might get. And if I'm telling the kernel to read a potentially larger
>>>> number of bytes, there needs to be a big enough buffer for it.
>>>>
>>>
>>> This still feels wrong to me.  Are you sure its not related to the
>>> PKCS1.5 padding ?
>>
>>
>> Yes. akcipher_recvmsg() does this check before invoking any crypto ops:
>>
>>        /* ensure output buffer is sufficiently large */
>>        if (usedpages < akcipher_calcsize(ctx)) {
>>                err = -EMSGSIZE;
>>                goto unlock;
>>        }
>>
>> (where akcipher_calcsize() returns the key size in bytes when using RSA)
>>
>> I'm not sure why, since the length of the destination buffer gets
>> propagated to the crypto algorithm and it could decide what to do. I'll ask
>> Stephan.
>
>
> I convinced the author to drop this extra length check. This means we can do
> short reads when using RSA software crypto. However, I see that hardware
> drivers can require the full length output buffer anyway (probably because
> of how the hardware handles DMA access) - so we sacrifice compatibility if
> we use a smaller read buffer.

I understand we need to be using the padding transform anyway so this
doesn't affect us. The buffer received by AF_ALG is not the one used
by the rsa transform.  The pkcs1pad code allocates a key-sized buffer
to which rsa will write the result and there will be various checks
and a memcpy from that buffer to the one provided by AF_ALG /
userspace.

That said if the driver doesn't conform to the API, even though it was
created at about the same time as the API then it needs to be fixed.

Also I can't understand why Tadeusz decided to skpi leading zeros from
the RSA input and output numbers, no other API does that and it
doesn't help anybody on the kernel or the userspace sides, I think the
mpi library was modified to do that just for RSA.

Best regards

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2016-06-09 21:20 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-06 20:54 [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Mat Martineau
2016-06-06 20:54 ` [PATCH 02/11] main: Fix comment typo Mat Martineau
2016-06-06 20:54 ` [PATCH 03/11] unit: Free all memory allocated during the DH test Mat Martineau
2016-06-06 20:54 ` [PATCH 04/11] unit: Script and config file for creating test certificates Mat Martineau
2016-06-06 20:54 ` [PATCH 05/11] unit: New set of " Mat Martineau
2016-06-06 20:54 ` [PATCH 06/11] key: Add keyring APIs Mat Martineau
2016-06-06 20:54 ` [PATCH 07/11] unit: Keyring tests Mat Martineau
2016-06-06 20:54 ` [PATCH 08/11] cipher: Update for current kernel akcipher interface Mat Martineau
2016-06-06 23:55   ` Denis Kenzior
2016-06-07 17:51   ` Denis Kenzior
2016-06-07 19:10     ` Mat Martineau
2016-06-07 19:32       ` Denis Kenzior
2016-06-08  0:18         ` Mat Martineau
2016-06-09 20:20           ` Mat Martineau
2016-06-09 21:06             ` Denis Kenzior
2016-06-09 21:18               ` Mat Martineau
2016-06-09 21:20             ` Andrzej Zaborowski
2016-06-07 21:47     ` Andrzej Zaborowski
2016-06-07 22:23       ` Denis Kenzior
2016-06-07 22:43         ` Andrzej Zaborowski
2016-06-06 20:54 ` [PATCH 09/11] unit: Update for akcipher changes Mat Martineau
2016-06-06 20:54 ` [PATCH 10/11] cipher: Return result length from asymmetric cipher operations Mat Martineau
2016-06-06 20:54 ` [PATCH 11/11] tls: Free cert memory after sending cert Mat Martineau
2016-06-07 17:54 ` [PATCH 01/11] gitignore: Add unit/test-dbus-message-fds Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.