signature-params: Add functions to parse/build ASN.1 RSASSA-PSS params
authorTobias Brunner <tobias@strongswan.org>
Wed, 20 Sep 2017 13:21:51 +0000 (15:21 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 8 Nov 2017 15:48:10 +0000 (16:48 +0100)
src/libstrongswan/Android.mk
src/libstrongswan/Makefile.am
src/libstrongswan/credentials/keys/signature_params.c [new file with mode: 0644]
src/libstrongswan/credentials/keys/signature_params.h
src/libstrongswan/tests/Makefile.am
src/libstrongswan/tests/suites/test_signature_params.c [new file with mode: 0644]
src/libstrongswan/tests/tests.h

index afca134..0247add 100644 (file)
@@ -20,6 +20,7 @@ crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
 credentials/credential_factory.c credentials/builder.c \
 credentials/cred_encoding.c credentials/keys/private_key.c \
 credentials/keys/public_key.c credentials/keys/shared_key.c \
+credentials/keys/signature_params.c \
 credentials/certificates/certificate.c credentials/certificates/crl.c \
 credentials/certificates/ocsp_response.c credentials/certificates/x509.c \
 credentials/certificates/certificate_printer.c \
index c0cc094..a9759ae 100644 (file)
@@ -18,6 +18,7 @@ crypto/xofs/xof.c crypto/xofs/xof_bitspender.c \
 credentials/credential_factory.c credentials/builder.c \
 credentials/cred_encoding.c credentials/keys/private_key.c \
 credentials/keys/public_key.c credentials/keys/shared_key.c \
+credentials/keys/signature_params.c \
 credentials/certificates/certificate.c credentials/certificates/crl.c \
 credentials/certificates/ocsp_response.c credentials/certificates/x509.c \
 credentials/certificates/certificate_printer.c \
diff --git a/src/libstrongswan/credentials/keys/signature_params.c b/src/libstrongswan/credentials/keys/signature_params.c
new file mode 100644 (file)
index 0000000..72a61e1
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "signature_params.h"
+
+#include <asn1/oid.h>
+#include <asn1/asn1_parser.h>
+
+/**
+ * ASN.1 definition of RSASSA-PSS-params
+ */
+static const asn1Object_t RSASSAPSSParamsObjects[] = {
+       { 0, "RSASSA-PSS-params",       ASN1_SEQUENCE,          ASN1_NONE                       }, /* 0 */
+       { 1,   "DEFAULT SHA-1",         ASN1_CONTEXT_C_0,       ASN1_DEF                        }, /* 1 */
+       { 2,     "hashAlgorithm",       ASN1_EOC,                       ASN1_RAW                        }, /* 2 */
+       { 1,   "DEFAULT MGF1SHA1",      ASN1_CONTEXT_C_1,       ASN1_DEF                        }, /* 3 */
+       { 2,     "maskGenAlgorithm",ASN1_EOC,                   ASN1_RAW                        }, /* 4 */
+       { 1,   "DEFAULT 20",            ASN1_CONTEXT_C_2,       ASN1_DEF                        }, /* 5 */
+       { 2,     "saltLength",          ASN1_INTEGER,           ASN1_BODY                       }, /* 6 */
+       { 1,   "DEFAULT 1",                     ASN1_CONTEXT_C_3,       ASN1_DEF                        }, /* 7 */
+       { 2,     "trailerField",        ASN1_INTEGER,           ASN1_BODY                       }, /* 8 */
+       { 0, "exit",                            ASN1_EOC,                       ASN1_EXIT                       }
+};
+#define RSASSA_PSS_PARAMS_HASH_ALG             2
+#define RSASSA_PSS_PARAMS_MGF_ALG              4
+#define RSASSA_PSS_PARAMS_SALT_LEN             6
+#define RSASSA_PSS_PARAMS_TRAILER              8
+
+/*
+ * Described in header
+ */
+bool rsa_pss_params_parse(chunk_t asn1, int level0, rsa_pss_params_t *params)
+{
+       asn1_parser_t *parser;
+       chunk_t object;
+       int objectID, alg;
+       bool success = FALSE;
+
+       params->hash = HASH_SHA1;
+       params->mgf1_hash = HASH_SHA1;
+       params->salt_len = HASH_SIZE_SHA1;
+
+       parser = asn1_parser_create(RSASSAPSSParamsObjects, asn1);
+       parser->set_top_level(parser, level0);
+
+       while (parser->iterate(parser, &objectID, &object))
+       {
+               u_int level = parser->get_level(parser)+1;
+
+               switch (objectID)
+               {
+                       case RSASSA_PSS_PARAMS_HASH_ALG:
+                               if (object.len)
+                               {
+                                       alg = asn1_parse_algorithmIdentifier(object, level, NULL);
+                                       params->hash = hasher_algorithm_from_oid(alg);
+                                       if (params->hash == HASH_UNKNOWN)
+                                       {
+                                               goto end;
+                                       }
+                               }
+                               break;
+                       case RSASSA_PSS_PARAMS_MGF_ALG:
+                               if (object.len)
+                               {
+                                       chunk_t hash;
+
+                                       alg = asn1_parse_algorithmIdentifier(object, level, &hash);
+                                       if (alg != OID_MGF1)
+                                       {
+                                               goto end;
+                                       }
+                                       alg = asn1_parse_algorithmIdentifier(hash, level+1, NULL);
+                                       params->mgf1_hash = hasher_algorithm_from_oid(alg);
+                                       if (params->mgf1_hash == HASH_UNKNOWN)
+                                       {
+                                               goto end;
+                                       }
+                               }
+                               break;
+                       case RSASSA_PSS_PARAMS_SALT_LEN:
+                               if (object.len)
+                               {
+                                       params->salt_len = (size_t)asn1_parse_integer_uint64(object);
+                               }
+                               break;
+                       case RSASSA_PSS_PARAMS_TRAILER:
+                               if (object.len && (object.len != 1 || *object.ptr != 1))
+                               {
+                                       goto end;
+                               }
+                               break;
+                       default:
+                               break;
+               }
+       }
+       success = parser->success(parser);
+
+end:
+       parser->destroy(parser);
+       return success;
+}
+
+/*
+ * Described in header
+ */
+bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
+{
+       chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty;
+       int alg;
+
+       if (params->hash != HASH_SHA1)
+       {       /* with SHA-1 we MUST omit the field */
+               alg = hasher_algorithm_to_oid(params->hash);
+               if (alg == OID_UNKNOWN)
+               {
+                       return FALSE;
+               }
+               hash = asn1_algorithmIdentifier(alg);
+       }
+       if (params->mgf1_hash != HASH_SHA1)
+       {       /* with MGF1-SHA1 we MUST omit the field */
+               alg = hasher_algorithm_to_oid(params->mgf1_hash);
+               if (alg == OID_UNKNOWN)
+               {
+                       chunk_free(&hash);
+                       return FALSE;
+               }
+               mgf = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_MGF1),
+                                               asn1_algorithmIdentifier(alg));
+       }
+       if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
+       {
+               if (params->salt_len != HASH_SIZE_SHA1)
+               {
+                       slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len));
+               }
+       }
+       else if (params->hash != HASH_SHA1)
+       {
+               size_t hlen = hasher_hash_size(params->hash);
+               if (!hlen)
+               {
+                       chunk_free(&hash);
+                       chunk_free(&mgf);
+                       return FALSE;
+               }
+               slen = asn1_integer("m", asn1_integer_from_uint64(hlen));
+       }
+       *asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm",
+                               hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty,
+                               mgf.len ? asn1_wrap(ASN1_CONTEXT_C_1, "m", mgf) : chunk_empty,
+                               slen.len ? asn1_wrap(ASN1_CONTEXT_C_2, "m", slen) : chunk_empty);
+       return TRUE;
+}
index 24f0f40..f243954 100644 (file)
@@ -38,4 +38,23 @@ struct rsa_pss_params_t {
 #define RSA_PSS_SALT_LEN_DEFAULT -1
 };
 
+/**
+ * Parse the given ASN.1 algorithm identifier params
+ *
+ * @param asn1         ASN.1 encoded RSASSA-PSS-params
+ * @param level0       current level of the ASN.1 parser
+ * @param params       parsed parameters
+ * @return                     TRUE if successfully parsed
+ */
+bool rsa_pss_params_parse(chunk_t asn1, int level0, rsa_pss_params_t *params);
+
+/**
+ * Build ASN.1 algorithm identifier params
+ *
+ * @param params       parameters to encode
+ * @param asn1         ASN.1 encoded RSASSA-PSS-params (allocated)
+ * @return                     TRUE if successfully built
+ */
+bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1);
+
 #endif /** SIGNATURE_PARAMS_H_ @}*/
index 0231c1c..d764a6a 100644 (file)
@@ -56,7 +56,8 @@ tests_SOURCES = tests.h tests.c \
   suites/test_test_rng.c \
   suites/test_mgf1.c \
   suites/test_ntru.c \
-  suites/test_ed25519.c
+  suites/test_ed25519.c \
+  suites/test_signature_params.c
 
 tests_CFLAGS = \
   -I$(top_srcdir)/src/libstrongswan \
diff --git a/src/libstrongswan/tests/suites/test_signature_params.c b/src/libstrongswan/tests/suites/test_signature_params.c
new file mode 100644 (file)
index 0000000..0b69880
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2017 Tobias Brunner
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <asn1/oid.h>
+#include <asn1/asn1.h>
+#include <credentials/keys/signature_params.h>
+
+struct {
+       chunk_t aid;
+       rsa_pss_params_t params;
+} rsa_pss_parse_tests[] = {
+       /* from RFC 7427, no parameters (empty sequence) */
+       { chunk_from_chars(0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x00),
+         { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }},
+       /* from RFC 7427, default parameters (SHA-1), would actually not be sent
+        * like this, as corrected in errata */
+       { chunk_from_chars(0x30,0x3e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x31,0xa0,
+                                          0x0b,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0xa1,0x18,0x30,0x16,
+                                          0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,0x09,0x06,0x05,0x2b,
+                                          0x0e,0x03,0x02,0x1a,0x05,0x00,0xa2,0x03,0x02,0x01,0x14,0xa3,0x03,0x02,0x01,0x01),
+         { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }},
+       /* from RFC 7427, SHA-256 */
+       { chunk_from_chars(0x30,0x46,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x39,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x20,0xa3,0x03,0x02,0x01,0x01),
+         { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, }},
+       /* from RFC 7427, SHA-256 (errata, without trailer, with len corrections) */
+       { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x20),
+         { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, }},
+       /* SHA-512 */
+       { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x40),
+         { .hash = HASH_SHA512, .mgf1_hash = HASH_SHA512, .salt_len = HASH_SIZE_SHA512, }},
+       /* SHA-256, no salt */
+       { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x00),
+               { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 0, }},
+       /* only hash specified */
+       { chunk_from_chars(0x30,0x1e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x11,
+                                          0xa0,0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,
+                                          0x05,0x00),
+               { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }},
+       /* only mgf specified */
+       { chunk_from_chars(0x30,0x2b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x1e,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,
+                                          0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00),
+               { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA1, }},
+       /* only salt specified */
+       { chunk_from_chars(0x30,0x12,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x05,0xa2,
+                                          0x03,0x02,0x01,0x20),
+         { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA256, }},
+};
+
+START_TEST(test_rsa_pss_params_parse)
+{
+       rsa_pss_params_t parsed;
+       chunk_t params;
+       int oid;
+
+       oid = asn1_parse_algorithmIdentifier(rsa_pss_parse_tests[_i].aid, 0, &params);
+       ck_assert_int_eq(OID_RSASSA_PSS, oid);
+       ck_assert(rsa_pss_params_parse(params, 1, &parsed));
+       ck_assert_int_eq(rsa_pss_parse_tests[_i].params.hash, parsed.hash);
+       ck_assert_int_eq(rsa_pss_parse_tests[_i].params.mgf1_hash, parsed.mgf1_hash);
+       ck_assert_int_eq(rsa_pss_parse_tests[_i].params.salt_len, parsed.salt_len);
+}
+END_TEST
+
+chunk_t rsa_pss_parse_invalid_tests[] = {
+       /* unknown hash */
+       chunk_from_chars(0x30,0x1e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x11,
+                                        0xa0,0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x00,
+                                        0x05,0x00),
+       /* unknown mgf */
+       chunk_from_chars(0x30,0x2b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x1e,
+                                        0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x00,
+                                        0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00),
+       /* unknown mgf-1 hash */
+       chunk_from_chars(0x30,0x2b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x1e,
+                                        0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,
+                                        0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x00,0x05,0x00),
+       /* incorrect trailer */
+       chunk_from_chars(0x30,0x12,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x05,
+                                        0xa3,0x03,0x02,0x01,0x02),
+       /* too long trailer */
+       chunk_from_chars(0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x06,
+                                        0xa3,0x04,0x02,0x02,0x01,0x01),
+};
+
+START_TEST(test_rsa_pss_params_parse_invalid)
+{
+       rsa_pss_params_t parsed;
+       chunk_t params;
+       int oid;
+
+       oid = asn1_parse_algorithmIdentifier(rsa_pss_parse_invalid_tests[_i], 0, &params);
+       ck_assert_int_eq(OID_RSASSA_PSS, oid);
+       ck_assert(!rsa_pss_params_parse(params, 1, &parsed));
+}
+END_TEST
+
+struct {
+       chunk_t aid;
+       rsa_pss_params_t params;
+} rsa_pss_build_tests[] = {
+       /* default parameters -> empty sequence */
+       { chunk_from_chars(0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x00),
+               { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }},
+       /* SHA-256 */
+       { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x20),
+               { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
+       /* default salt length: SHA-1 */
+       { chunk_from_chars(0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x00),
+               { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
+       /* default salt length: SHA-224 */
+       { chunk_from_chars(0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x16,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,0x05,0x00,
+                                          0xa2,0x03,0x02,0x01,0x1c),
+               { .hash = HASH_SHA224, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
+       /* default salt length: SHA-384 */
+       { chunk_from_chars(0x30,0x23,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x16,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,0x05,0x00,
+                                          0xa2,0x03,0x02,0x01,0x30),
+               { .hash = HASH_SHA384, .mgf1_hash = HASH_SHA1, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
+       /* SHA-512 */
+       { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x40),
+         { .hash = HASH_SHA512, .mgf1_hash = HASH_SHA512, .salt_len = RSA_PSS_SALT_LEN_DEFAULT, }},
+       /* SHA-256, no salt */
+       { chunk_from_chars(0x30,0x41,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x34,0xa0,
+                                          0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,0x30,
+                                          0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00,0xa2,0x03,
+                                          0x02,0x01,0x00),
+               { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 0, }},
+       /* SHA-256, rest default */
+       { chunk_from_chars(0x30,0x1e,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x11,
+                                          0xa0,0x0f,0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,
+                                          0x05,0x00),
+               { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }},
+       /* MGF1-SHA-256, rest default */
+       { chunk_from_chars(0x30,0x2b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x1e,
+                                          0xa1,0x1c,0x30,0x1a,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x08,
+                                          0x30,0x0d,0x06,0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,0x05,0x00),
+               { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA1, }},
+       /* only salt specified */
+       { chunk_from_chars(0x30,0x12,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0a,0x30,0x05,0xa2,
+                                          0x03,0x02,0x01,0x20),
+         { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA256, }},
+};
+
+START_TEST(test_rsa_pss_params_build)
+{
+       chunk_t params, aid;
+
+       ck_assert(rsa_pss_params_build(&rsa_pss_build_tests[_i].params, &params));
+       aid = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_RSASSA_PSS),
+                                       params);
+       ck_assert_chunk_eq(rsa_pss_build_tests[_i].aid, aid);
+       chunk_free(&aid);
+}
+END_TEST
+
+rsa_pss_params_t rsa_pss_build_invalid_tests[] = {
+       /* unknown hash */
+       { .hash = HASH_UNKNOWN, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, },
+       /* invalid mgf */
+       { .hash = HASH_SHA256, .mgf1_hash = HASH_UNKNOWN, .salt_len = HASH_SIZE_SHA256, },
+};
+
+START_TEST(test_rsa_pss_params_build_invalid)
+{
+       chunk_t params;
+
+       ck_assert(!rsa_pss_params_build(&rsa_pss_build_invalid_tests[_i], &params));
+}
+END_TEST
+
+Suite *signature_params_suite_create()
+{
+       Suite *s;
+       TCase *tc;
+
+       s = suite_create("signature params");
+
+       tc = tcase_create("parse");
+       tcase_add_loop_test(tc, test_rsa_pss_params_parse, 0, countof(rsa_pss_parse_tests));
+       tcase_add_loop_test(tc, test_rsa_pss_params_parse_invalid, 0, countof(rsa_pss_parse_invalid_tests));
+       suite_add_tcase(s, tc);
+
+       tc = tcase_create("build");
+       tcase_add_loop_test(tc, test_rsa_pss_params_build, 0, countof(rsa_pss_build_tests));
+       tcase_add_loop_test(tc, test_rsa_pss_params_build_invalid, 0, countof(rsa_pss_build_invalid_tests));
+       suite_add_tcase(s, tc);
+
+       return s;
+}
index c19cac2..525bdeb 100644 (file)
@@ -51,4 +51,5 @@ TEST_SUITE_DEPEND(mgf1_sha256_suite_create, XOF, XOF_MGF1_SHA256)
 TEST_SUITE_DEPEND(ntru_suite_create, DH, NTRU_112_BIT)
 TEST_SUITE_DEPEND(fetch_http_suite_create, FETCHER, "http://")
 TEST_SUITE_DEPEND(ed25519_suite_create, PRIVKEY_GEN, KEY_ED25519)
+TEST_SUITE(signature_params_suite_create)