From: Tobias Brunner Date: Fri, 24 Mar 2023 16:04:42 +0000 (+0100) Subject: pkcs7: Add support for CMS-style signatures (RSA-PSS, ECDSA) X-Git-Tag: 5.9.11dr2~3^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e76bc163419b981b1c9ce9e8c380bb94f9e8702;p=thirdparty%2Fstrongswan.git pkcs7: Add support for CMS-style signatures (RSA-PSS, ECDSA) For the legacy schemes with rsaEncryption nothing changes, but if an actual signature scheme is encoded we use that to find the key and verify the signature. The descriptions for the PKCS#7 structure are adapted for CMS. --- diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c index 1b9d13569b..30d536911c 100644 --- a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c +++ b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2023 Tobias Brunner * Copyright (C) 2012 Martin Willi * * Copyright (C) secunet Security Networks AG @@ -86,9 +87,9 @@ typedef struct { identification_t *issuer; /** - * EncryptedDigest + * Signature */ - chunk_t encrypted_digest; + chunk_t signature; /** * Digesting algorithm OID @@ -96,9 +97,9 @@ typedef struct { int digest_alg; /** - * Public key encryption algorithm OID + * Signature algorithm */ - int enc_alg; + signature_params_t sig_alg; } signerinfo_t; @@ -110,7 +111,8 @@ static void signerinfo_destroy(signerinfo_t *this) DESTROY_IF(this->attributes); DESTROY_IF(this->serial); DESTROY_IF(this->issuer); - free(this->encrypted_digest.ptr); + signature_params_clear(&this->sig_alg); + free(this->signature.ptr); free(this); } @@ -142,8 +144,8 @@ static const asn1Object_t signedDataObjects[] = { { 3, "authenticatedAttributes", ASN1_CONTEXT_C_0, ASN1_OPT | ASN1_OBJ }, /* 19 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ - { 3, "digestEncryptionAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ - { 3, "encryptedDigest", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ + { 3, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 21 */ + { 3, "signature", ASN1_OCTET_STRING, ASN1_BODY }, /* 22 */ { 3, "unauthenticatedAttributes", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 23 */ { 3, "end opt", ASN1_EOC, ASN1_END }, /* 24 */ { 1, "end loop", ASN1_EOC, ASN1_END }, /* 25 */ @@ -159,8 +161,8 @@ static const asn1Object_t signedDataObjects[] = { #define PKCS7_SERIAL_NUMBER 17 #define PKCS7_DIGEST_ALGORITHM 18 #define PKCS7_AUTH_ATTRIBUTES 19 -#define PKCS7_DIGEST_ENC_ALGORITHM 21 -#define PKCS7_ENCRYPTED_DIGEST 22 +#define PKCS7_SIGNATURE_ALGORITHM 21 +#define PKCS7_SIGNATURE 22 METHOD(container_t, get_type, container_type_t, private_pkcs7_signed_data_t *this) @@ -188,7 +190,6 @@ METHOD(enumerator_t, enumerate, bool, signature_enumerator_t *this, va_list args) { signerinfo_t *info; - signature_scheme_t scheme; hash_algorithm_t algorithm; enumerator_t *enumerator; certificate_t *cert; @@ -206,25 +207,20 @@ METHOD(enumerator_t, enumerate, bool, DESTROY_IF(this->auth); this->auth = NULL; - scheme = signature_scheme_from_oid(info->digest_alg); - if (scheme == SIGN_UNKNOWN) - { - DBG1(DBG_LIB, "unsupported signature scheme"); - continue; - } if (!info->attributes) { DBG1(DBG_LIB, "no authenticatedAttributes object found"); continue; } - if (info->enc_alg != OID_RSA_ENCRYPTION) + if (info->sig_alg.scheme == SIGN_UNKNOWN) { - DBG1(DBG_LIB, "only RSA digest encryption supported"); + DBG1(DBG_LIB, "unsupported signature scheme"); continue; } enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, - KEY_RSA, info->serial, FALSE); + key_type_from_signature_scheme(info->sig_alg.scheme), + info->serial, FALSE); while (enumerator->enumerate(enumerator, &cert, &auth)) { if (info->issuer->equals(info->issuer, cert->get_issuer(cert))) @@ -233,8 +229,8 @@ METHOD(enumerator_t, enumerate, bool, if (key) { chunk = info->attributes->get_encoding(info->attributes); - if (key->verify(key, scheme, NULL, chunk, - info->encrypted_digest)) + if (key->verify(key, info->sig_alg.scheme, + info->sig_alg.params, chunk, info->signature)) { this->auth = auth->clone(auth); key->destroy(key); @@ -448,7 +444,6 @@ static bool parse(private_pkcs7_signed_data_t *this, chunk_t content) case PKCS7_SIGNER_INFO: INIT(info, .digest_alg = OID_UNKNOWN, - .enc_alg = OID_UNKNOWN, ); this->signerinfos->insert_last(this->signerinfos, info); break; @@ -474,12 +469,22 @@ static bool parse(private_pkcs7_signed_data_t *this, chunk_t content) info->digest_alg = asn1_parse_algorithmIdentifier(object, level, NULL); break; - case PKCS7_DIGEST_ENC_ALGORITHM: - info->enc_alg = asn1_parse_algorithmIdentifier(object, - level, NULL); + case PKCS7_SIGNATURE_ALGORITHM: + if (!signature_params_parse(object, level, &info->sig_alg)) + { + if (asn1_parse_algorithmIdentifier(object, -1, + NULL) == OID_RSA_ENCRYPTION && + info->digest_alg != OID_UNKNOWN) + { + /* derive the signature scheme from the digest algorithm + * for the classic PKCS#7 RSA mechansim */ + info->sig_alg.scheme = signature_scheme_from_oid( + info->digest_alg); + } + } break; - case PKCS7_ENCRYPTED_DIGEST: - info->encrypted_digest = chunk_clone(object); + case PKCS7_SIGNATURE: + info->signature = chunk_clone(object); break; } }