06 Apr, 2016

2 commits

  • Generalise system_verify_data() to provide access to internal content
    through a callback. This allows all the PKCS#7 stuff to be hidden inside
    this function and removed from the PE file parser and the PKCS#7 test key.

    If external content is not required, NULL should be passed as data to the
    function. If the callback is not required, that can be set to NULL.

    The function is now called verify_pkcs7_signature() to contrast with
    verify_pefile_signature() and the definitions of both have been moved into
    linux/verification.h along with the key_being_used_for enum.

    Signed-off-by: David Howells

    David Howells
     
  • Point to the public_key_signature struct from the pkcs7_signed_info struct
    rather than embedding it. This makes the code consistent with the X.509
    signature handling and makes it possible to have a common cleanup function.

    We also save a copy of the digest in the signature without sharing the
    memory with the crypto layer metadata.

    Signed-off-by: David Howells

    David Howells
     

04 Mar, 2016

1 commit


29 Feb, 2016

1 commit

  • The boolean want is not initialized and hence garbage. The default should
    be false (later it is only set to true on tne sinfo->authattrs check).

    Found with static analysis using CoverityScan

    Signed-off-by: Colin Ian King
    Signed-off-by: David Howells

    Colin Ian King
     

10 Feb, 2016

1 commit


25 Jan, 2016

1 commit

  • Dave Young reported:
    > Hi,
    >
    > I saw the warning "Missing required AuthAttr" when testing kexec,
    > known issue? Idea about how to fix it?
    >
    > The kernel is latest linus tree plus sevral patches from Toshi to
    > cleanup io resource structure.
    >
    > in function pkcs7_sig_note_set_of_authattrs():
    > if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
    > !test_bit(sinfo_has_message_digest, &sinfo->aa_set) ||
    > (ctx->msg->data_type == OID_msIndirectData &&
    > !test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))) {
    > pr_warn("Missing required AuthAttr\n");
    > return -EBADMSG;
    > }
    >
    > The third condition below is true:
    > (ctx->msg->data_type == OID_msIndirectData &&
    > !test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
    >
    > I signed the kernel with redhat test key like below:
    > pesign -c 'Red Hat Test Certificate' -i arch/x86/boot/bzImage -o /boot/vmlinuz-4.4.0-rc8+ -s --force

    And right he is! The Authenticode specification is a paragon amongst
    technical documents, and has this pearl of wisdom to offer:

    ---------------------------------
    Authenticode-Specific SignerInfo UnauthenticatedAttributes Structures

    The following Authenticode-specific data structures are present in
    SignerInfo authenticated attributes.

    SpcSpOpusInfo
    SpcSpOpusInfo is identified by SPC_SP_OPUS_INFO_OBJID
    (1.3.6.1.4.1.311.2.1.12) and is defined as follows:
    SpcSpOpusInfo ::= SEQUENCE {
    programName [0] EXPLICIT SpcString OPTIONAL,
    moreInfo [1] EXPLICIT SpcLink OPTIONAL,
    } --#public--

    SpcSpOpusInfo has two fields:
    programName
    This field contains the program description:
    If publisher chooses not to specify a description, the SpcString
    structure contains a zero-length program name.
    If the publisher chooses to specify a
    description, the SpcString structure contains a Unicode string.
    moreInfo
    This field is set to an SPCLink structure that contains a URL for
    a Web site with more information about the signer. The URL is an
    ASCII string.
    ---------------------------------

    Which is to say that this is an optional *unauthenticated* field which
    may be present in the Authenticated Attribute list. This is not how
    pkcs7 is supposed to work, so when David implemented this, he didn't
    appreciate the subtlety the original spec author was working with, and
    missed the part of the sublime prose that says this Authenticated
    Attribute is an Unauthenticated Attribute. As a result, the code in
    question simply takes as given that the Authenticated Attributes should
    be authenticated.

    But this one should not, individually. Because it says it's not
    authenticated.

    It still has to hash right so the TBS digest is correct. So it is both
    authenticated and unauthenticated, all at once. Truly, a wonder of
    technical accomplishment.

    Additionally, pesign's implementation has always attempted to be
    compatible with the signatures emitted from contemporary versions of
    Microsoft's signtool.exe. During the initial implementation, Microsoft
    signatures always produced the same values for SpcSpOpusInfo -
    {U"Microsoft Windows", "http://www.microsoft.com"} - without regard to
    who the signer was.

    Sometime between Windows 8 and Windows 8.1 they stopped including the
    field in their signatures altogether, and as such pesign stopped
    producing them in commits c0c4da6 and d79cb0c, sometime around June of
    2012. The theory here is that anything that breaks with
    pesign signatures would also be breaking with signtool.exe sigs as well,
    and that'll be a more noticed problem for firmwares parsing it, so it'll
    get fixed. The fact that we've done exactly this bug in Linux code is
    first class, grade A irony.

    So anyway, we should not be checking this field for presence or any
    particular value: if the field exists, it should be at the right place,
    but aside from that, as long as the hash matches the field is good.

    Signed-off-by: Peter Jones
    Tested-by: Dave Young
    Signed-off-by: Herbert Xu

    Peter Jones
     

01 Sep, 2015

1 commit

  • Add OIDs for sha224, sha284 and sha512 hash algos and use them to select
    the hashing algorithm. Without this, something like the following error
    might get written to dmesg:

    [ 31.829322] PKCS7: Unknown OID: [32] 2.16.840.1.101.3.4.2.3
    [ 31.829328] PKCS7: Unknown OID: [180] 2.16.840.1.101.3.4.2.3
    [ 31.829330] Unsupported digest algo: 55

    Where the 55 on the third line is OID__NR indicating an unknown OID.

    Reported-by: Valdis Kletnieks
    Signed-off-by: David Howells
    Tested-By: Valdis Kletnieks
    Signed-off-by: James Morris

    David Howells
     

13 Aug, 2015

3 commits

  • A PKCS#7 or CMS message can have per-signature authenticated attributes
    that are digested as a lump and signed by the authorising key for that
    signature. If such attributes exist, the content digest isn't itself
    signed, but rather it is included in a special authattr which then
    contributes to the signature.

    Further, we already require the master message content type to be
    pkcs7_signedData - but there's also a separate content type for the data
    itself within the SignedData object and this must be repeated inside the
    authattrs for each signer [RFC2315 9.2, RFC5652 11.1].

    We should really validate the authattrs if they exist or forbid them
    entirely as appropriate. To this end:

    (1) Alter the PKCS#7 parser to reject any message that has more than one
    signature where at least one signature has authattrs and at least one
    that does not.

    (2) Validate authattrs if they are present and strongly restrict them.
    Only the following authattrs are permitted and all others are
    rejected:

    (a) contentType. This is checked to be an OID that matches the
    content type in the SignedData object.

    (b) messageDigest. This must match the crypto digest of the data.

    (c) signingTime. If present, we check that this is a valid, parseable
    UTCTime or GeneralTime and that the date it encodes fits within
    the validity window of the matching X.509 cert.

    (d) S/MIME capabilities. We don't check the contents.

    (e) Authenticode SP Opus Info. We don't check the contents.

    (f) Authenticode Statement Type. We don't check the contents.

    The message is rejected if (a) or (b) are missing. If the message is
    an Authenticode type, the message is rejected if (e) is missing; if
    not Authenticode, the message is rejected if (d) - (f) are present.

    The S/MIME capabilities authattr (d) unfortunately has to be allowed
    to support kernels already signed by the pesign program. This only
    affects kexec. sign-file suppresses them (CMS_NOSMIMECAP).

    The message is also rejected if an authattr is given more than once or
    if it contains more than one element in its set of values.

    (3) Add a parameter to pkcs7_verify() to select one of the following
    restrictions and pass in the appropriate option from the callers:

    (*) VERIFYING_MODULE_SIGNATURE

    This requires that the SignedData content type be pkcs7-data and
    forbids authattrs. sign-file sets CMS_NOATTR. We could be more
    flexible and permit authattrs optionally, but only permit minimal
    content.

    (*) VERIFYING_FIRMWARE_SIGNATURE

    This requires that the SignedData content type be pkcs7-data and
    requires authattrs. In future, this will require an attribute
    holding the target firmware name in addition to the minimal set.

    (*) VERIFYING_UNSPECIFIED_SIGNATURE

    This requires that the SignedData content type be pkcs7-data but
    allows either no authattrs or only permits the minimal set.

    (*) VERIFYING_KEXEC_PE_SIGNATURE

    This only supports the Authenticode SPC_INDIRECT_DATA content type
    and requires at least an SpcSpOpusInfo authattr in addition to the
    minimal set. It also permits an SPC_STATEMENT_TYPE authattr (and
    an S/MIME capabilities authattr because the pesign program doesn't
    remove these).

    (*) VERIFYING_KEY_SIGNATURE
    (*) VERIFYING_KEY_SELF_SIGNATURE

    These are invalid in this context but are included for later use
    when limiting the use of X.509 certs.

    (4) The pkcs7_test key type is given a module parameter to select between
    the above options for testing purposes. For example:

    echo 1 >/sys/module/pkcs7_test_key/parameters/usage
    keyctl padd pkcs7_test foo @s
    Signed-off-by: David Howells
    Reviewed-by: Marcel Holtmann
    Reviewed-by: David Woodhouse

    David Howells
     
  • Since CMS is an evolution of PKCS#7, with much of the ASN.1 being
    compatible, add support for CMS signed-data messages also [RFC5652 sec 5].

    Signed-off-by: David Howells
    Reviewed-By: David Woodhouse

    David Howells
     
  • We only support PKCS#7 signed-data [RFC2315 sec 9] content at the top level,
    so reject anything else. Further, check that the version numbers in
    SignedData and SignerInfo are 1 in both cases.

    Note that we don't restrict the inner content type. In the PKCS#7 code we
    don't parse the data attached there, but merely verify the signature over
    it.

    Signed-off-by: David Howells
    Reviewed-By: David Woodhouse

    David Howells
     

17 Sep, 2014

3 commits

  • Make use of the new match string preparsing to overhaul key identification
    when searching for asymmetric keys. The following changes are made:

    (1) Use the previously created asymmetric_key_id struct to hold the following
    key IDs derived from the X.509 certificate or PKCS#7 message:

    id: serial number + issuer
    skid: subjKeyId + subject
    authority: authKeyId + issuer

    (2) Replace the hex fingerprint attached to key->type_data[1] with an
    asymmetric_key_ids struct containing the id and the skid (if present).

    (3) Make the asymmetric_type match data preparse select one of two searches:

    (a) An iterative search for the key ID given if prefixed with "id:". The
    prefix is expected to be followed by a hex string giving the ID to
    search for. The criterion key ID is checked against all key IDs
    recorded on the key.

    (b) A direct search if the key ID is not prefixed with "id:". This will
    look for an exact match on the key description.

    (4) Make x509_request_asymmetric_key() take a key ID. This is then converted
    into "id:" and passed into keyring_search() where match preparsing
    will turn it back into a binary ID.

    (5) X.509 certificate verification then takes the authority key ID and looks
    up a key that matches it to find the public key for the certificate
    signature.

    (6) PKCS#7 certificate verification then takes the id key ID and looks up a
    key that matches it to find the public key for the signed information
    block signature.

    Additional changes:

    (1) Multiple subjKeyId and authKeyId values on an X.509 certificate cause the
    cert to be rejected with -EBADMSG.

    (2) The 'fingerprint' ID is gone. This was primarily intended to convey PGP
    public key fingerprints. If PGP is supported in future, this should
    generate a key ID that carries the fingerprint.

    (3) Th ca_keyid= kernel command line option is now converted to a key ID and
    used to match the authority key ID. Possibly this should only match the
    actual authKeyId part and not the issuer as well.

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     
  • Fix the parser cleanup code to drain parsed out X.509 certs in the case that
    the decode fails and we jump to error_decode.

    The function is rearranged so that the same cleanup code is used in the success
    case as the error case - just that the message descriptor under construction is
    only released if it is still pointed to by the context struct at that point.

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     
  • The code to free a signed info block is repeated several times, so move the
    code to do it into a function of its own. This gives us a place to add clean
    ups for stuff that gets added to pkcs7_signed_info.

    Signed-off-by: David Howells
    Acked-by: Vivek Goyal

    David Howells
     

08 Jul, 2014

1 commit