]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
pkcs7: Support rsa-pss signatures
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sun, 2 Oct 2022 11:01:34 +0000 (13:01 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 3 Oct 2022 07:52:07 +0000 (09:52 +0200)
src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
src/pki/commands/scep.c
src/pki/scep/scep.c
src/pki/scep/scep.h

index c74af9d828ba198f4213797792ce5f624cfa6827..be020e761dadb2feed06b99ded45347827eb1471 100644 (file)
@@ -44,6 +44,11 @@ struct private_pkcs7_signed_data_t {
         */
        container_t *content;
 
+       /**
+        * Signature scheme
+        */
+       signature_params_t *scheme;
+
        /**
         * Encoded PKCS#7 signed-data
         */
@@ -365,6 +370,7 @@ METHOD(container_t, destroy, void,
        this->creds->destroy(this->creds);
        this->signerinfos->destroy_function(this->signerinfos,
                                                                                (void*)signerinfo_destroy);
+       signature_params_destroy(this->scheme);
        DESTROY_IF(this->content);
        free(this->encoding.ptr);
        free(this);
@@ -527,31 +533,45 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
 {
        chunk_t authenticatedAttributes = chunk_empty;
        chunk_t encryptedDigest = chunk_empty;
-       chunk_t data, signerInfo, encoding = chunk_empty;
-       chunk_t messageDigest, signingTime, attributes;
-       signature_scheme_t scheme;
+       chunk_t data = chunk_empty, encoding = chunk_empty;
+       chunk_t digest_alg = chunk_empty, sig_scheme = chunk_empty;
+       chunk_t signerInfo = chunk_empty, messageDigest, signingTime, attributes;
        hasher_t *hasher;
        time_t now;
-       int digest_oid;
 
-       digest_oid = hasher_algorithm_to_oid(alg);
-       scheme = signature_scheme_from_oid(digest_oid);
-
-       if (!this->content->get_data(this->content, &data))
+       /* select signature scheme, if not already specified */
+       if (!this->scheme)
+       {
+               INIT(this->scheme,
+                       .scheme = signature_scheme_from_oid(
+                                                       hasher_signature_algorithm_to_oid(alg,
+                                                               key->get_type(key))),
+               );
+       }
+       if (this->scheme->scheme == SIGN_UNKNOWN)
+       {
+               return FALSE;
+       }
+       if (!signature_params_build(this->scheme, &sig_scheme))
        {
                return FALSE;
        }
+       if (!this->content->get_data(this->content, &data))
+       {
+               goto err;
+       }
 
        hasher = lib->crypto->create_hasher(lib->crypto, alg);
        if (!hasher || !hasher->allocate_hash(hasher, data, &messageDigest))
        {
                DESTROY_IF(hasher);
-               DBG1(DBG_LIB, "  hash algorithm %N not support",
+               DBG1(DBG_LIB, "  hash algorithm %N not supported",
                         hash_algorithm_names, alg);
-               free(data.ptr);
-               return FALSE;
+               goto err;
        }
+       chunk_free(&data);
        hasher->destroy(hasher);
+
        pkcs9->add_attribute(pkcs9,
                                        OID_PKCS9_MESSAGE_DIGEST,
                                        asn1_wrap(ASN1_OCTET_STRING, "m", messageDigest));
@@ -562,40 +582,38 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
        pkcs9->add_attribute(pkcs9, OID_PKCS9_SIGNING_TIME, signingTime);
        pkcs9->add_attribute(pkcs9, OID_PKCS9_CONTENT_TYPE,
                                                 asn1_build_known_oid(OID_PKCS7_DATA));
-
        attributes = pkcs9->get_encoding(pkcs9);
 
-       if (!key->sign(key, scheme, NULL, attributes, &encryptedDigest))
+       if (!key->sign(key, this->scheme->scheme, this->scheme->params, attributes,
+                                  &encryptedDigest))
        {
-               free(data.ptr);
-               return FALSE;
+               goto err;
        }
        authenticatedAttributes = chunk_clone(attributes);
        *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
 
-       free(data.ptr);
        if (encryptedDigest.ptr)
        {
                encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
        }
-       signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm",
+
+       digest_alg = asn1_algorithmIdentifier(hasher_algorithm_to_oid(alg));
+       signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmcmmm",
                                        ASN1_INTEGER_1,
                                        build_issuerAndSerialNumber(cert),
-                                       asn1_algorithmIdentifier(digest_oid),
+                                       digest_alg,
                                        authenticatedAttributes,
-                                       asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
+                                       sig_scheme,
                                        encryptedDigest);
+       sig_scheme = chunk_empty;
 
        if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
        {
-               free(signerInfo.ptr);
-               return FALSE;
+               goto err;
        }
        if (!this->content->get_encoding(this->content, &data))
        {
-               free(encoding.ptr);
-               free(signerInfo.ptr);
-               return FALSE;
+               goto err;
        }
 
        this->encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
@@ -603,15 +621,22 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
                asn1_wrap(ASN1_CONTEXT_C_0, "m",
                        asn1_wrap(ASN1_SEQUENCE, "cmmmm",
                                ASN1_INTEGER_1,
-                               asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_oid)),
+                               asn1_wrap(ASN1_SET, "m", digest_alg),
                                data,
                                asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding),
                                asn1_wrap(ASN1_SET, "m", signerInfo))));
 
-
        pkcs9->destroy(pkcs9);
        /* TODO: create signerInfos entry */
        return TRUE;
+
+err:
+       chunk_free(&data);
+       chunk_free(&digest_alg);
+       chunk_free(&sig_scheme);
+       chunk_free(&signerInfo);
+       chunk_free(&encoding);
+       return FALSE;
 }
 
 /**
@@ -621,7 +646,8 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
 {
        private_pkcs7_signed_data_t *this;
        chunk_t blob = chunk_empty;
-       hash_algorithm_t alg = HASH_SHA1;
+       hash_algorithm_t alg = HASH_SHA256;
+       signature_params_t *scheme = NULL;
        private_key_t *key = NULL;
        certificate_t *cert = NULL;
        pkcs7_attributes_t *pkcs9;
@@ -646,6 +672,9 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
                        case BUILD_BLOB:
                                blob = va_arg(args, chunk_t);
                                continue;
+                       case BUILD_SIGNATURE_SCHEME:
+                               scheme = va_arg(args, signature_params_t*);
+                               continue;
                        case BUILD_PKCS7_ATTRIBUTE:
                                oid = va_arg(args, int);
                                value = va_arg(args, chunk_t);
@@ -663,11 +692,11 @@ pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
        {
                this = create_empty();
 
+               this->scheme = signature_params_clone(scheme);
                this->creds->add_cert(this->creds, FALSE, cert->get_ref(cert));
                this->content = lib->creds->create(lib->creds,
                                                                                   CRED_CONTAINER, CONTAINER_PKCS7_DATA,
                                                                                   BUILD_BLOB, blob, BUILD_END);
-
                if (this->content && generate(this, key, cert, alg, pkcs9))
                {
                        return &this->public;
index 78102e460c270043fd877224f1107e0874506c76..de36d0abd288bd31c4247a25e731d17fc7a17f98 100644 (file)
@@ -465,7 +465,7 @@ static int scep()
        /* build pkcs7 request */
        pkcs7_req = scep_build_request(pkcs10_encoding, transID, scep_msg_type,
                                                                   x509_ca_enc, cipher, key_size, x509_signer,
-                                                                  digest_alg, priv_signer);
+                                                                  digest_alg, scheme, priv_signer);
        if (!pkcs7_req.ptr)
        {
                DBG1(DBG_APP, "failed to build SCEP request");
@@ -525,7 +525,7 @@ static int scep()
 
                certPoll = scep_build_request(issuerAndSubject, transID, SCEP_CertPoll_MSG,
                                                                          x509_ca_enc, cipher, key_size, x509_signer,
-                                                                         digest_alg, priv_signer);
+                                                                         digest_alg, scheme, priv_signer);
                if (!certPoll.ptr)
                {
                        DBG1(DBG_APP, "failed to build SCEP certPoll request");
index 0b3772dca7dcc393b0fde94e2f9f711f2aafb18b..abe246f8196c1e8dbb8d88a6e274ad93b368bf96 100644 (file)
@@ -163,7 +163,8 @@ bool scep_generate_transaction_id(public_key_t *public,
 chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
                                        certificate_t *enc_cert, encryption_algorithm_t enc_alg,
                                        size_t key_size, certificate_t *signer_cert,
-                                       hash_algorithm_t digest_alg, private_key_t *private_key)
+                                       hash_algorithm_t digest_alg, signature_params_t *scheme,
+                                       private_key_t *private_key)
 {
        chunk_t request;
        container_t *container;
@@ -212,6 +213,7 @@ chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
                                        BUILD_SIGNING_CERT, signer_cert,
                                        BUILD_SIGNING_KEY, private_key,
                                        BUILD_DIGEST_ALG, digest_alg,
+                                       BUILD_SIGNATURE_SCHEME, scheme,
                                        BUILD_PKCS7_ATTRIBUTE, OID_PKI_SENDER_NONCE, senderNonce,
                                        BUILD_PKCS7_ATTRIBUTE, OID_PKI_TRANS_ID, transID,
                                        BUILD_PKCS7_ATTRIBUTE, OID_PKI_MESSAGE_TYPE, msgType,
index 015945d0812ef7deea34305d88aa4989e5d4dee0..4e9711013647056b748b5d5bc84c842e907085e9 100644 (file)
@@ -108,7 +108,8 @@ bool scep_generate_transaction_id(public_key_t *key,
 chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg,
                                                certificate_t *enc_cert, encryption_algorithm_t enc_alg,
                                                size_t key_size, certificate_t *signer_cert,
-                                               hash_algorithm_t digest_alg, private_key_t *private_key);
+                                               hash_algorithm_t digest_alg, signature_params_t *scheme,
+                                               private_key_t *private_key);
 
 /**
  * Send a SCEP request via HTTP and wait for a response