Commit e85d19c6 authored by Antonio Iacono's avatar Antonio Iacono Committed by Dr. Matthias St. Pierre
Browse files

crypto/cms: Add support for CAdES Basic Electronic Signatures (CAdES-BES)



A CAdES Basic Electronic Signature (CAdES-BES) contains, among other
specifications, a collection of  Signing Certificate reference attributes,
stored in the signedData ether as ESS signing-certificate or as
ESS signing-certificate-v2. These are described in detail in Section 5.7.2
of RFC 5126 - CMS Advanced Electronic Signatures (CAdES).

This patch adds support for adding  ESS signing-certificate[-v2] attributes
to CMS signedData. Although it implements only a small part of the RFC, it
is sufficient many cases to enable the `openssl cms` app to create signatures
which comply with legal requirements of some European States (e.g Italy).

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
Reviewed-by: default avatarMatthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
(Merged from https://github.com/openssl/openssl/pull/7893)
parent 9f5a87fd
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
/*
 * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
@@ -65,7 +65,7 @@ struct cms_key_param_st {
typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
    OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
    OPT_DECRYPT, OPT_SIGN, OPT_CADES, OPT_SIGN_RECEIPT, OPT_RESIGN,
    OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
    OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
    OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
@@ -102,6 +102,7 @@ const OPTIONS cms_options[] = {
    {"sign", OPT_SIGN, '-', "Sign message"},
    {"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
    {"resign", OPT_RESIGN, '-', "Resign a signed message"},
    {"cades", OPT_CADES, '-', "Include signer certificate digest"},
    {"verify", OPT_VERIFY, '-', "Verify signed message"},
    {"verify_retcode", OPT_VERIFY_RETCODE, '-'},
    {"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
@@ -326,6 +327,9 @@ int cms_main(int argc, char **argv)
        case OPT_BINARY:
            flags |= CMS_BINARY;
            break;
        case OPT_CADES:
            flags |= CMS_CADES;
            break;
        case OPT_KEYID:
            flags |= CMS_USE_KEYID;
            break;
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ SUBDIRS=objects buffer bio stack lhash rand evp asn1 pem x509 x509v3 conf \
        md2 md4 md5 sha mdc2 gmac hmac ripemd whrlpool poly1305 blake2 \
        siphash sm3 des aes rc2 rc4 rc5 idea aria bf cast camellia \
        seed sm4 chacha modes bn ec rsa dsa dh sm2 dso engine \
        err comp ocsp cms ts srp cmac ct async kmac
        err comp ocsp cms ts srp cmac ct async kmac ess

LIBS=../libcrypto
SOURCE[../libcrypto]=\
+4 −0
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ static const ERR_STRING_DATA CMS_str_functs[] = {
    {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNER, 0), "CMS_add1_signer"},
    {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNINGTIME, 0),
     "cms_add1_signingTime"},
    {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNING_CERT, 0),
     "CMS_add1_signing_cert"},
    {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_ADD1_SIGNING_CERT_V2, 0),
     "CMS_add1_signing_cert_v2"},
    {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESS, 0), "CMS_compress"},
    {ERR_PACK(ERR_LIB_CMS, CMS_F_CMS_COMPRESSEDDATA_CREATE, 0),
     "cms_CompressedData_create"},
+71 −2
Original line number Diff line number Diff line
/*
 * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
 * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
@@ -14,11 +14,13 @@
#include <openssl/x509v3.h>
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/ess.h>
#include "cms_lcl.h"
#include "internal/ess_int.h"

IMPLEMENT_ASN1_FUNCTIONS(CMS_ReceiptRequest)

/* ESS services: for now just Signed Receipt related */
/* ESS services */

int CMS_get1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest **prr)
{
@@ -335,3 +337,70 @@ ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si)
    CMS_ReceiptRequest_free(rr);
    return os;
}

/*
 * Add signer certificate's V2 digest to a SignerInfo
 * structure
 */

int CMS_add1_signing_cert_v2(CMS_SignerInfo *si,
                             ESS_SIGNING_CERT_V2 *sc)
{
    ASN1_STRING *seq = NULL;
    unsigned char *p, *pp;
    int len;

    /* Add SigningCertificateV2 signed attribute to the signer info. */
    len = i2d_ESS_SIGNING_CERT_V2(sc, NULL);
    if ((pp = OPENSSL_malloc(len)) == NULL)
        goto err;
    p = pp;
    i2d_ESS_SIGNING_CERT_V2(sc, &p);
    if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len))
        goto err;
    OPENSSL_free(pp);
    pp = NULL;
    if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificateV2,
                                     V_ASN1_SEQUENCE, seq, -1))
        goto err;
    ASN1_STRING_free(seq);
    return 1;
 err:
    CMSerr(CMS_F_CMS_ADD1_SIGNING_CERT_V2, ERR_R_MALLOC_FAILURE);
    ASN1_STRING_free(seq);
    OPENSSL_free(pp);
    return 0;
}

/*
 * Add signer certificate's digest to a SignerInfo
 * structure
 */

int CMS_add1_signing_cert(CMS_SignerInfo *si, ESS_SIGNING_CERT *sc)
{
    ASN1_STRING *seq = NULL;
    unsigned char *p, *pp;
    int len;

    /* Add SigningCertificate signed attribute to the signer info. */
    len = i2d_ESS_SIGNING_CERT(sc, NULL);
    if ((pp = OPENSSL_malloc(len)) == NULL)
        goto err;
    p = pp;
    i2d_ESS_SIGNING_CERT(sc, &p);
    if (!(seq = ASN1_STRING_new()) || !ASN1_STRING_set(seq, pp, len))
        goto err;
    OPENSSL_free(pp);
    pp = NULL;
    if (!CMS_signed_add1_attr_by_NID(si, NID_id_smime_aa_signingCertificate,
                                     V_ASN1_SEQUENCE, seq, -1))
        goto err;
    ASN1_STRING_free(seq);
    return 1;
 err:
    CMSerr(CMS_F_CMS_ADD1_SIGNING_CERT, ERR_R_MALLOC_FAILURE);
    ASN1_STRING_free(seq);
    OPENSSL_free(pp);
    return 0;
}
+21 −0
Original line number Diff line number Diff line
@@ -332,6 +332,27 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
                !CMS_SignerInfo_sign(si))
                goto err;
        }
        if (flags & CMS_CADES) {
            ESS_SIGNING_CERT *sc = NULL;
            ESS_SIGNING_CERT_V2 *sc2 = NULL;
            int add_sc;

            if (md == EVP_sha1() || md == NULL) {
                if ((sc = ESS_SIGNING_CERT_new_init(signer,
                                                    NULL, 1)) == NULL)
                    goto err;
                add_sc = CMS_add1_signing_cert(si, sc);
                ESS_SIGNING_CERT_free(sc);
            } else {
                if ((sc2 = ESS_SIGNING_CERT_V2_new_init(md, signer,
                                                        NULL, 1)) == NULL)
                    goto err;
                add_sc = CMS_add1_signing_cert_v2(si, sc2);
                ESS_SIGNING_CERT_V2_free(sc2);
            }
            if (!add_sc)
                goto err;
        }
    }

    if (!(flags & CMS_NOCERTS)) {
Loading