]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
pki: Allow specifying signature scheme for PKCS#7 signatures
authorTobias Brunner <tobias@strongswan.org>
Thu, 30 Mar 2023 09:19:28 +0000 (11:19 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 31 Mar 2023 07:11:20 +0000 (09:11 +0200)
Also changed the error handling a bit so it is more like in the other
pki commands.

src/pki/commands/pkcs7.c
src/pki/man/pki---pkcs7.1.in

index fd474a1a4c15ce36676d26193cd132552a6345bf..8d3528fdc11c3a7d37711fbbbc13f03b049044d0 100644 (file)
@@ -151,7 +151,8 @@ static int verify(chunk_t chunk)
 /**
  * Sign data into PKCS#7 signed-data
  */
-static int sign(chunk_t chunk, certificate_t *cert, private_key_t *key)
+static int sign(chunk_t chunk, certificate_t *cert, private_key_t *key,
+                               hash_algorithm_t digest, signature_params_t *scheme)
 {
        container_t *container;
        chunk_t encoding;
@@ -162,6 +163,8 @@ static int sign(chunk_t chunk, certificate_t *cert, private_key_t *key)
                                                                   BUILD_BLOB, chunk,
                                                                   BUILD_SIGNING_CERT, cert,
                                                                   BUILD_SIGNING_KEY, key,
+                                                                  BUILD_SIGNATURE_SCHEME, scheme,
+                                                                  BUILD_DIGEST_ALG, digest,
                                                                   BUILD_END);
        if (container)
        {
@@ -171,6 +174,7 @@ static int sign(chunk_t chunk, certificate_t *cert, private_key_t *key)
                        free(encoding.ptr);
                }
                container->destroy(container);
+               res = 0;
        }
        return res;
 }
@@ -196,6 +200,7 @@ static int encrypt(chunk_t chunk, certificate_t *cert)
                        free(encoding.ptr);
                }
                container->destroy(container);
+               res = 0;
        }
        return res;
 }
@@ -277,12 +282,14 @@ static int show(chunk_t chunk)
  */
 static int pkcs7()
 {
-       char *arg, *file = NULL;
+       char *arg, *file = NULL, *error = NULL;
        private_key_t *key = NULL;
        certificate_t *cert = NULL;
        chunk_t data = chunk_empty;
+       hash_algorithm_t digest = HASH_UNKNOWN;
+       signature_params_t *scheme = NULL;
        mem_cred_t *creds;
-       int res = 1;
+       int res = 0;
        FILE *in;
        enum {
                OP_NONE,
@@ -292,6 +299,8 @@ static int pkcs7()
                OP_DECRYPT,
                OP_SHOW,
        } op = OP_NONE;
+       bool pss = lib->settings->get_bool(lib->settings, "%s.rsa_pss", FALSE,
+                                                                          lib->ns);
 
        creds = mem_cred_create();
 
@@ -300,8 +309,7 @@ static int pkcs7()
                switch (command_getopt(&arg))
                {
                        case 'h':
-                               creds->destroy(creds);
-                               return command_usage(NULL);
+                               goto usage;
                        case 'i':
                                file = arg;
                                continue;
@@ -342,12 +350,12 @@ static int pkcs7()
                                continue;
                        case 'k':
                                key = lib->creds->create(lib->creds,
-                                                                                CRED_PRIVATE_KEY, KEY_RSA,
+                                                                                CRED_PRIVATE_KEY, KEY_ANY,
                                                                                 BUILD_FROM_FILE, arg, BUILD_END);
                                if (!key)
                                {
-                                       fprintf(stderr, "parsing private key failed\n");
-                                       goto end;
+                                       error = "parsing private key failed";
+                                       goto usage;
                                }
                                creds->add_key(creds, key);
                                continue;
@@ -357,17 +365,31 @@ static int pkcs7()
                                                                                  BUILD_FROM_FILE, arg, BUILD_END);
                                if (!cert)
                                {
-                                       fprintf(stderr, "parsing certificate failed\n");
-                                       goto end;
+                                       error = "parsing certificate failed";
+                                       goto usage;
                                }
                                creds->add_cert(creds, TRUE, cert);
                                continue;
+                       case 'g':
+                               if (!enum_from_name(hash_algorithm_short_names, arg, &digest))
+                               {
+                                       error = "invalid --digest type";
+                                       goto usage;
+                               }
+                               continue;
+                       case 'R':
+                               if (!parse_rsa_padding(arg, &pss))
+                               {
+                                       error = "invalid RSA padding";
+                                       goto usage;
+                               }
+                               continue;
                        case EOF:
                                break;
                        default:
                        invalid:
-                               creds->destroy(creds);
-                               return command_usage("invalid --pkcs7 option");
+                               error = "invalid --pkcs7 option";
+                               goto usage;
                }
                break;
        }
@@ -388,12 +410,12 @@ static int pkcs7()
 
        if (!data.len)
        {
-               fprintf(stderr, "reading input failed!\n");
+               error = "reading input failed";
                goto end;
        }
        if (op != OP_SHOW && !cert)
        {
-               fprintf(stderr, "requiring a certificate!\n");
+               error = "requiring a certificate";
                goto end;
        }
 
@@ -404,11 +426,21 @@ static int pkcs7()
                case OP_SIGN:
                        if (!key)
                        {
-                               fprintf(stderr, "signing requires a private key\n");
-                               res = 1;
+                               error = "signing requires a private key";
                                break;
                        }
-                       res = sign(data, cert, key);
+                       scheme = get_signature_scheme(key, digest, pss);
+                       if (!scheme)
+                       {
+                               error = "no signature scheme found";
+                               break;
+                       }
+                       if (digest == HASH_UNKNOWN)
+                       {
+                               digest = hasher_from_signature_scheme(scheme->scheme,
+                                                                                                         scheme->params);
+                       }
+                       res = sign(data, cert, key, digest, scheme);
                        break;
                case OP_VERIFY:
                        res = verify(data);
@@ -420,7 +452,6 @@ static int pkcs7()
                        if (!key)
                        {
                                fprintf(stderr, "decryption requires a private key\n");
-                               res = 1;
                                break;
                        }
                        res = decrypt(data);
@@ -435,9 +466,19 @@ static int pkcs7()
        lib->credmgr->remove_local_set(lib->credmgr, &creds->set);
 
 end:
+       signature_params_destroy(scheme);
        creds->destroy(creds);
        free(data.ptr);
+       if (error)
+       {
+               fprintf(stderr, "%s\n", error);
+               return 1;
+       }
        return res;
+
+usage:
+       creds->destroy(creds);
+       return command_usage(error);
 }
 
 /**
@@ -448,17 +489,21 @@ static void __attribute__ ((constructor))reg()
        command_register((command_t) {
                pkcs7, '7', "pkcs7", "PKCS#7 wrap/unwrap functions",
                {"--sign|--verify|--encrypt|--decrypt|--show",
-                "[--in file] [--cert file]+ [--key file]"},
+                "[--in file] [--cert file]+ [--key file]",
+                "[--digest md5|sha1|sha224|sha256|sha384|sha512|sha3_224|sha3_256|sha3_384|sha3_512]",
+                "[--rsa-padding pkcs1|pss]"},
                {
-                       {"help",        'h', 0, "show usage information"},
-                       {"sign",        's', 0, "create PKCS#7 signed-data"},
-                       {"verify",      'u', 0, "verify PKCS#7 signed-data"},
-                       {"encrypt",     'e', 0, "create PKCS#7 enveloped-data"},
-                       {"decrypt",     'd', 0, "decrypt PKCS#7 enveloped-data"},
-                       {"show",        'p', 0, "show info about PKCS#7, print certificates"},
-                       {"in",          'i', 1, "input file, default: stdin"},
-                       {"key",         'k', 1, "path to private key for sign/decrypt"},
-                       {"cert",        'c', 1, "path to certificate for sign/verify/encrypt"},
+                       {"help",                'h', 0, "show usage information"},
+                       {"sign",                's', 0, "create PKCS#7 signed-data"},
+                       {"verify",              'u', 0, "verify PKCS#7 signed-data"},
+                       {"encrypt",             'e', 0, "create PKCS#7 enveloped-data"},
+                       {"decrypt",             'd', 0, "decrypt PKCS#7 enveloped-data"},
+                       {"show",                'p', 0, "show info about PKCS#7, print certificates"},
+                       {"in",                  'i', 1, "input file, default: stdin"},
+                       {"key",                 'k', 1, "path to private key for sign/decrypt"},
+                       {"cert",                'c', 1, "path to certificate for sign/verify/encrypt"},
+                       {"digest",              'g', 1, "digest for signature creation, default: key-specific"},
+                       {"rsa-padding", 'R', 1, "padding for RSA signatures, default: pkcs1"},
                }
        });
 }
index 38186cf709ac117a977b4dd6b7d953ef747a0152..b4abdf33c7172cb242fd3daab758c8f6c11046d2 100644 (file)
@@ -1,4 +1,4 @@
-.TH "PKI \-\-PKCS7" 1 "2013-07-31" "@PACKAGE_VERSION@" "strongSwan"
+.TH "PKI \-\-PKCS7" 1 "2023-03-30" "@PACKAGE_VERSION@" "strongSwan"
 .
 .SH "NAME"
 .
@@ -11,6 +11,8 @@ pki \-\-pkcs7 \- Provides PKCS#7 wrap/unwrap functions
 .OP \-\-in file
 .OP \-\-cert file
 .OP \-\-key file
+.OP \-\-digest digest
+.OP \-\-rsa\-padding padding
 .OP \-\-debug level
 .YS
 .
@@ -73,6 +75,15 @@ Certificate for
 and
 .BR \-\-encrypt.
 Can be used multiple times.
+.TP
+.BI "\-g, \-\-digest " digest
+Digest to use for signature creation. One of \fImd5\fR, \fIsha1\fR,
+\fIsha224\fR, \fIsha256\fR, \fIsha384\fR, or \fIsha512\fR.  The default is
+determined based on the type and size of the signature key.
+.TP
+.BI "\-R, \-\-rsa\-padding " padding
+Padding to use for RSA signatures. Either \fIpkcs1\fR or \fIpss\fR, defaults
+to \fIpkcs1\fR.
 .
 .SH "SEE ALSO"
 .