iPXE
Defines | Functions | Variables
cms.c File Reference

Cryptographic Message Syntax (PKCS #7) More...

#include <stdint.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <ipxe/asn1.h>
#include <ipxe/x509.h>
#include <ipxe/malloc.h>
#include <ipxe/uaccess.h>
#include <ipxe/cms.h>

Go to the source code of this file.

Defines

#define EACCES_NON_SIGNING   __einfo_error ( EINFO_EACCES_NON_SIGNING )
#define EINFO_EACCES_NON_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" )
#define EACCES_NON_CODE_SIGNING   __einfo_error ( EINFO_EACCES_NON_CODE_SIGNING )
#define EINFO_EACCES_NON_CODE_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )
#define EACCES_WRONG_NAME   __einfo_error ( EINFO_EACCES_WRONG_NAME )
#define EINFO_EACCES_WRONG_NAME   __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )
#define EACCES_NO_SIGNATURES   __einfo_error ( EINFO_EACCES_NO_SIGNATURES )
#define EINFO_EACCES_NO_SIGNATURES   __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )
#define EINVAL_DIGEST   __einfo_error ( EINFO_EINVAL_DIGEST )
#define EINFO_EINVAL_DIGEST   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a digest algorithm" )
#define EINVAL_PUBKEY   __einfo_error ( EINFO_EINVAL_PUBKEY )
#define EINFO_EINVAL_PUBKEY   __einfo_uniqify ( EINFO_EINVAL, 0x02, "Not a public-key algorithm" )
#define ENOTSUP_SIGNEDDATA   __einfo_error ( EINFO_ENOTSUP_SIGNEDDATA )
#define EINFO_ENOTSUP_SIGNEDDATA   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int cms_parse_content_type (struct cms_signature *sig, const struct asn1_cursor *raw)
 Parse CMS signature content type.
static int cms_parse_certificates (struct cms_signature *sig, const struct asn1_cursor *raw)
 Parse CMS signature certificate list.
static struct x509_certificatecms_find_issuer_serial (struct cms_signature *sig, const struct asn1_cursor *issuer, const struct asn1_cursor *serial)
 Identify CMS signature certificate by issuer and serial number.
static int cms_parse_signer_identifier (struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw)
 Parse CMS signature signer identifier.
static int cms_parse_digest_algorithm (struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw)
 Parse CMS signature digest algorithm.
static int cms_parse_signature_algorithm (struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw)
 Parse CMS signature algorithm.
static int cms_parse_signature_value (struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw)
 Parse CMS signature value.
static int cms_parse_signer_info (struct cms_signature *sig, struct cms_signer_info *info, const struct asn1_cursor *raw)
 Parse CMS signature signer information.
static int cms_parse (struct cms_signature *sig, const struct asn1_cursor *raw)
 Parse CMS signature from ASN.1 data.
static void cms_free (struct refcnt *refcnt)
 Free CMS signature.
int cms_signature (const void *data, size_t len, struct cms_signature **sig)
 Create CMS signature.
static void cms_digest (struct cms_signature *sig, struct cms_signer_info *info, userptr_t data, size_t len, void *out)
 Calculate digest of CMS-signed data.
static int cms_verify_digest (struct cms_signature *sig, struct cms_signer_info *info, struct x509_certificate *cert, userptr_t data, size_t len)
 Verify digest of CMS-signed data.
static int cms_verify_signer_info (struct cms_signature *sig, struct cms_signer_info *info, userptr_t data, size_t len, time_t time, struct x509_chain *store, struct x509_root *root)
 Verify CMS signature signer information.
int cms_verify (struct cms_signature *sig, userptr_t data, size_t len, const char *name, time_t time, struct x509_chain *store, struct x509_root *root)
 Verify CMS signature.

Variables

static uint8_t oid_signeddata [] = { ASN1_OID_SIGNEDDATA }
 "pkcs7-signedData" object identifier
static struct asn1_cursor oid_signeddata_cursor
 "pkcs7-signedData" object identifier cursor

Detailed Description

Cryptographic Message Syntax (PKCS #7)

The format of CMS messages is defined in RFC 5652.

Definition in file cms.c.


Define Documentation

Definition at line 45 of file cms.c.

Referenced by cms_verify_signer_info().

#define EINFO_EACCES_NON_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x01, "Not a signing certificate" )

Definition at line 47 of file cms.c.

Definition at line 49 of file cms.c.

Referenced by cms_verify_signer_info().

#define EINFO_EACCES_NON_CODE_SIGNING   __einfo_uniqify ( EINFO_EACCES, 0x02, "Not a code-signing certificate" )

Definition at line 51 of file cms.c.

Definition at line 53 of file cms.c.

Referenced by cms_verify().

#define EINFO_EACCES_WRONG_NAME   __einfo_uniqify ( EINFO_EACCES, 0x04, "Incorrect certificate name" )

Definition at line 55 of file cms.c.

Definition at line 57 of file cms.c.

Referenced by cms_verify().

#define EINFO_EACCES_NO_SIGNATURES   __einfo_uniqify ( EINFO_EACCES, 0x05, "No signatures present" )

Definition at line 59 of file cms.c.

Definition at line 61 of file cms.c.

#define EINFO_EINVAL_DIGEST   __einfo_uniqify ( EINFO_EINVAL, 0x01, "Not a digest algorithm" )

Definition at line 63 of file cms.c.

Definition at line 65 of file cms.c.

#define EINFO_EINVAL_PUBKEY   __einfo_uniqify ( EINFO_EINVAL, 0x02, "Not a public-key algorithm" )

Definition at line 67 of file cms.c.

Definition at line 69 of file cms.c.

Referenced by cms_parse_content_type().

#define EINFO_ENOTSUP_SIGNEDDATA   __einfo_uniqify ( EINFO_ENOTSUP, 0x01, "Not a digital signature" )

Definition at line 71 of file cms.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int cms_parse_content_type ( struct cms_signature sig,
const struct asn1_cursor raw 
) [static]

Parse CMS signature content type.

Parameters:
sigCMS signature
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 88 of file cms.c.

References asn1_compare(), asn1_enter(), ASN1_OID, asn1_cursor::data, DBGC, DBGC_HDA, ENOTSUP_SIGNEDDATA, asn1_cursor::len, and memcpy().

Referenced by cms_parse().

                                                                    {
        struct asn1_cursor cursor;

        /* Enter contentType */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_OID );

        /* Check OID is pkcs7-signedData */
        if ( asn1_compare ( &cursor, &oid_signeddata_cursor ) != 0 ) {
                DBGC ( sig, "CMS %p does not contain signedData:\n", sig );
                DBGC_HDA ( sig, 0, raw->data, raw->len );
                return -ENOTSUP_SIGNEDDATA;
        }

        DBGC ( sig, "CMS %p contains signedData\n", sig );
        return 0;
}
static int cms_parse_certificates ( struct cms_signature sig,
const struct asn1_cursor raw 
) [static]

Parse CMS signature certificate list.

Parameters:
sigCMS signature
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 114 of file cms.c.

References asn1_enter(), ASN1_EXPLICIT_TAG, asn1_skip_any(), cms_signature::certificates, asn1_cursor::data, DBGC, DBGC_HDA, asn1_cursor::len, memcpy(), rc, strerror(), x509_append_raw(), x509_last(), and x509_name().

Referenced by cms_parse().

                                                                    {
        struct asn1_cursor cursor;
        struct x509_certificate *cert;
        int rc;

        /* Enter certificates */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );

        /* Add each certificate */
        while ( cursor.len ) {

                /* Add certificate to chain */
                if ( ( rc = x509_append_raw ( sig->certificates, cursor.data,
                                              cursor.len ) ) != 0 ) {
                        DBGC ( sig, "CMS %p could not append certificate: %s\n",
                               sig, strerror ( rc) );
                        DBGC_HDA ( sig, 0, cursor.data, cursor.len );
                        return rc;
                }
                cert = x509_last ( sig->certificates );
                DBGC ( sig, "CMS %p found certificate %s\n",
                       sig, x509_name ( cert ) );

                /* Move to next certificate */
                asn1_skip_any ( &cursor );
        }

        return 0;
}
static struct x509_certificate* cms_find_issuer_serial ( struct cms_signature sig,
const struct asn1_cursor issuer,
const struct asn1_cursor serial 
) [static, read]

Identify CMS signature certificate by issuer and serial number.

Parameters:
sigCMS signature
issuerIssuer
serialSerial number
Return values:
certX.509 certificate, or NULL if not found

Definition at line 155 of file cms.c.

References asn1_compare(), x509_link::cert, cms_signature::certificates, x509_certificate::issuer, link, x509_chain::links, list_for_each_entry, NULL, x509_serial::raw, x509_issuer::raw, and x509_certificate::serial.

Referenced by cms_parse_signer_identifier().

                                                            {
        struct x509_link *link;
        struct x509_certificate *cert;

        /* Scan through certificate list */
        list_for_each_entry ( link, &sig->certificates->links, list ) {

                /* Check issuer and serial number */
                cert = link->cert;
                if ( ( asn1_compare ( issuer, &cert->issuer.raw ) == 0 ) &&
                     ( asn1_compare ( serial, &cert->serial.raw ) == 0 ) )
                        return cert;
        }

        return NULL;
}
static int cms_parse_signer_identifier ( struct cms_signature sig,
struct cms_signer_info info,
const struct asn1_cursor raw 
) [static]

Parse CMS signature signer identifier.

Parameters:
sigCMS signature
infoSigner information to fill in
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 182 of file cms.c.

References asn1_enter(), ASN1_INTEGER, ASN1_SEQUENCE, asn1_shrink(), asn1_skip_any(), cms_signature::certificates, cms_signer_info::chain, cms_find_issuer_serial(), asn1_cursor::data, DBGC, DBGC_HDA, ENOENT, asn1_cursor::len, memcpy(), rc, strerror(), x509_append(), and x509_auto_append().

Referenced by cms_parse_signer_info().

                                                                         {
        struct asn1_cursor cursor;
        struct asn1_cursor serial;
        struct asn1_cursor issuer;
        struct x509_certificate *cert;
        int rc;

        /* Enter issuerAndSerialNumber */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Identify issuer */
        memcpy ( &issuer, &cursor, sizeof ( issuer ) );
        if ( ( rc = asn1_shrink ( &issuer, ASN1_SEQUENCE ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not locate issuer: %s\n",
                       sig, info, strerror ( rc ) );
                DBGC_HDA ( sig, 0, raw->data, raw->len );
                return rc;
        }
        DBGC ( sig, "CMS %p/%p issuer is:\n", sig, info );
        DBGC_HDA ( sig, 0, issuer.data, issuer.len );
        asn1_skip_any ( &cursor );

        /* Identify serialNumber */
        memcpy ( &serial, &cursor, sizeof ( serial ) );
        if ( ( rc = asn1_shrink ( &serial, ASN1_INTEGER ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not locate serialNumber: %s\n",
                       sig, info, strerror ( rc ) );
                DBGC_HDA ( sig, 0, raw->data, raw->len );
                return rc;
        }
        DBGC ( sig, "CMS %p/%p serial number is:\n", sig, info );
        DBGC_HDA ( sig, 0, serial.data, serial.len );

        /* Identify certificate */
        cert = cms_find_issuer_serial ( sig, &issuer, &serial );
        if ( ! cert ) {
                DBGC ( sig, "CMS %p/%p could not identify signer's "
                       "certificate\n", sig, info );
                return -ENOENT;
        }

        /* Append certificate to chain */
        if ( ( rc = x509_append ( info->chain, cert ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not append certificate: %s\n",
                       sig, info, strerror ( rc ) );
                return rc;
        }

        /* Append remaining certificates to chain */
        if ( ( rc = x509_auto_append ( info->chain,
                                       sig->certificates ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not append certificates: %s\n",
                       sig, info, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int cms_parse_digest_algorithm ( struct cms_signature sig,
struct cms_signer_info info,
const struct asn1_cursor raw 
) [static]

Parse CMS signature digest algorithm.

Parameters:
sigCMS signature
infoSigner information to fill in
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 252 of file cms.c.

References algorithm, asn1_digest_algorithm(), asn1_cursor::data, DBGC, DBGC_HDA, cms_signer_info::digest, asn1_algorithm::digest, asn1_cursor::len, asn1_algorithm::name, rc, and strerror().

Referenced by cms_parse_signer_info().

                                                                        {
        struct asn1_algorithm *algorithm;
        int rc;

        /* Identify algorithm */
        if ( ( rc = asn1_digest_algorithm ( raw, &algorithm ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not identify digest algorithm: "
                       "%s\n", sig, info, strerror ( rc ) );
                DBGC_HDA ( sig, 0, raw->data, raw->len );
                return rc;
        }

        /* Record digest algorithm */
        info->digest = algorithm->digest;
        DBGC ( sig, "CMS %p/%p digest algorithm is %s\n",
               sig, info, algorithm->name );

        return 0;
}
static int cms_parse_signature_algorithm ( struct cms_signature sig,
struct cms_signer_info info,
const struct asn1_cursor raw 
) [static]

Parse CMS signature algorithm.

Parameters:
sigCMS signature
infoSigner information to fill in
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 282 of file cms.c.

References algorithm, asn1_pubkey_algorithm(), asn1_cursor::data, DBGC, DBGC_HDA, asn1_cursor::len, asn1_algorithm::name, cms_signer_info::pubkey, asn1_algorithm::pubkey, rc, and strerror().

Referenced by cms_parse_signer_info().

                                                                           {
        struct asn1_algorithm *algorithm;
        int rc;

        /* Identify algorithm */
        if ( ( rc = asn1_pubkey_algorithm ( raw, &algorithm ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not identify public-key "
                       "algorithm: %s\n", sig, info, strerror ( rc ) );
                DBGC_HDA ( sig, 0, raw->data, raw->len );
                return rc;
        }

        /* Record signature algorithm */
        info->pubkey = algorithm->pubkey;
        DBGC ( sig, "CMS %p/%p public-key algorithm is %s\n",
               sig, info, algorithm->name );

        return 0;
}
static int cms_parse_signature_value ( struct cms_signature sig,
struct cms_signer_info info,
const struct asn1_cursor raw 
) [static]

Parse CMS signature value.

Parameters:
sigCMS signature
infoSigner information to fill in
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 312 of file cms.c.

References asn1_enter(), ASN1_OCTET_STRING, asn1_cursor::data, DBGC, DBGC_HDA, ENOMEM, asn1_cursor::len, malloc(), memcpy(), rc, cms_signer_info::signature, and cms_signer_info::signature_len.

Referenced by cms_parse_signer_info().

                                                                       {
        struct asn1_cursor cursor;
        int rc;

        /* Enter signature */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        if ( ( rc = asn1_enter ( &cursor, ASN1_OCTET_STRING ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not locate signature:\n",
                       sig, info );
                DBGC_HDA ( sig, 0, raw->data, raw->len );
                return rc;
        }

        /* Record signature */
        info->signature_len = cursor.len;
        info->signature = malloc ( info->signature_len );
        if ( ! info->signature )
                return -ENOMEM;
        memcpy ( info->signature, cursor.data, info->signature_len );
        DBGC ( sig, "CMS %p/%p signature value is:\n", sig, info );
        DBGC_HDA ( sig, 0, info->signature, info->signature_len );

        return 0;
}
static int cms_parse_signer_info ( struct cms_signature sig,
struct cms_signer_info info,
const struct asn1_cursor raw 
) [static]

Parse CMS signature signer information.

Parameters:
sigCMS signature
infoSigner information to fill in
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 347 of file cms.c.

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_INTEGER, ASN1_SEQUENCE, asn1_skip(), asn1_skip_any(), asn1_skip_if_exists(), cms_parse_digest_algorithm(), cms_parse_signature_algorithm(), cms_parse_signature_value(), cms_parse_signer_identifier(), memcpy(), and rc.

Referenced by cms_parse().

                                                                   {
        struct asn1_cursor cursor;
        int rc;

        /* Enter signerInfo */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Skip version */
        asn1_skip ( &cursor, ASN1_INTEGER );

        /* Parse sid */
        if ( ( rc = cms_parse_signer_identifier ( sig, info, &cursor ) ) != 0 )
                return rc;
        asn1_skip_any ( &cursor );

        /* Parse digestAlgorithm */
        if ( ( rc = cms_parse_digest_algorithm ( sig, info, &cursor ) ) != 0 )
                return rc;
        asn1_skip_any ( &cursor );

        /* Skip signedAttrs, if present */
        asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );

        /* Parse signatureAlgorithm */
        if ( ( rc = cms_parse_signature_algorithm ( sig, info, &cursor ) ) != 0)
                return rc;
        asn1_skip_any ( &cursor );

        /* Parse signature */
        if ( ( rc = cms_parse_signature_value ( sig, info, &cursor ) ) != 0 )
                return rc;

        return 0;
}
static int cms_parse ( struct cms_signature sig,
const struct asn1_cursor raw 
) [static]

Parse CMS signature from ASN.1 data.

Parameters:
sigCMS signature
rawASN.1 cursor
Return values:
rcReturn status code

Definition at line 392 of file cms.c.

References asn1_enter(), ASN1_EXPLICIT_TAG, ASN1_INTEGER, ASN1_SEQUENCE, ASN1_SET, asn1_skip(), asn1_skip_any(), asn1_skip_if_exists(), cms_signer_info::chain, cms_parse_certificates(), cms_parse_content_type(), cms_parse_signer_info(), ENOMEM, cms_signature::info, info, asn1_cursor::len, cms_signer_info::list, list_add, memcpy(), rc, x509_alloc_chain(), and zalloc().

Referenced by cms_signature().

                                                       {
        struct asn1_cursor cursor;
        struct cms_signer_info *info;
        int rc;

        /* Enter contentInfo */
        memcpy ( &cursor, raw, sizeof ( cursor ) );
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Parse contentType */

        if ( ( rc = cms_parse_content_type ( sig, &cursor ) ) != 0 )
                return rc;
        asn1_skip_any ( &cursor );

        /* Enter content */
        asn1_enter ( &cursor, ASN1_EXPLICIT_TAG ( 0 ) );

        /* Enter signedData */
        asn1_enter ( &cursor, ASN1_SEQUENCE );

        /* Skip version */
        asn1_skip ( &cursor, ASN1_INTEGER );

        /* Skip digestAlgorithms */
        asn1_skip ( &cursor, ASN1_SET );

        /* Skip encapContentInfo */
        asn1_skip ( &cursor, ASN1_SEQUENCE );

        /* Parse certificates */
        if ( ( rc = cms_parse_certificates ( sig, &cursor ) ) != 0 )
                return rc;
        asn1_skip_any ( &cursor );

        /* Skip crls, if present */
        asn1_skip_if_exists ( &cursor, ASN1_EXPLICIT_TAG ( 1 ) );

        /* Enter signerInfos */
        asn1_enter ( &cursor, ASN1_SET );

        /* Add each signerInfo.  Errors are handled by ensuring that
         * cms_put() will always be able to free any allocated memory.
         */
        while ( cursor.len ) {

                /* Allocate signer information block */
                info = zalloc ( sizeof ( *info ) );
                if ( ! info )
                        return -ENOMEM;
                list_add ( &info->list, &sig->info );

                /* Allocate certificate chain */
                info->chain = x509_alloc_chain();
                if ( ! info->chain )
                        return -ENOMEM;

                /* Parse signerInfo */
                if ( ( rc = cms_parse_signer_info ( sig, info,
                                                    &cursor ) ) != 0 )
                        return rc;
                asn1_skip_any ( &cursor );
        }

        return 0;
}
static void cms_free ( struct refcnt refcnt) [static]

Free CMS signature.

Parameters:
refcntReference count

Definition at line 465 of file cms.c.

References cms_signature::certificates, cms_signer_info::chain, container_of, free, cms_signature::info, info, cms_signer_info::list, list_del, list_for_each_entry_safe, sig, cms_signer_info::signature, and x509_chain_put().

Referenced by cms_signature().

                                               {
        struct cms_signature *sig =
                container_of ( refcnt, struct cms_signature, refcnt );
        struct cms_signer_info *info;
        struct cms_signer_info *tmp;

        list_for_each_entry_safe ( info, tmp, &sig->info, list ) {
                list_del ( &info->list );
                x509_chain_put ( info->chain );
                free ( info->signature );
                free ( info );
        }
        x509_chain_put ( sig->certificates );
        free ( sig );
}
int cms_signature ( const void *  data,
size_t  len,
struct cms_signature **  sig 
)

Create CMS signature.

Parameters:
dataRaw signature data
lenLength of raw data
Return values:
sigCMS signature
rcReturn status code

On success, the caller holds a reference to the CMS signature, and is responsible for ultimately calling cms_put().

Definition at line 492 of file cms.c.

References asn1_shrink_any(), cms_free(), cms_parse(), cms_put(), asn1_cursor::data, data, ENOMEM, INIT_LIST_HEAD, asn1_cursor::len, len, rc, ref_init, x509_alloc_chain(), and zalloc().

                                                                               {
        struct asn1_cursor cursor;
        int rc;

        /* Allocate and initialise signature */
        *sig = zalloc ( sizeof ( **sig ) );
        if ( ! *sig ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        ref_init ( &(*sig)->refcnt, cms_free );
        INIT_LIST_HEAD ( &(*sig)->info );

        /* Allocate certificate list */
        (*sig)->certificates = x509_alloc_chain();
        if ( ! (*sig)->certificates ) {
                rc = -ENOMEM;
                goto err_alloc_chain;
        }

        /* Initialise cursor */
        cursor.data = data;
        cursor.len = len;
        asn1_shrink_any ( &cursor );

        /* Parse signature */
        if ( ( rc = cms_parse ( *sig, &cursor ) ) != 0 )
                goto err_parse;

        return 0;

 err_parse:
 err_alloc_chain:
        cms_put ( *sig );
 err_alloc:
        return rc;
}
static void cms_digest ( struct cms_signature sig,
struct cms_signer_info info,
userptr_t  data,
size_t  len,
void *  out 
) [static]

Calculate digest of CMS-signed data.

Parameters:
sigCMS signature
infoSigner information
dataSigned data
lenLength of signed data
outDigest output

Definition at line 539 of file cms.c.

References block, digest_algorithm::blocksize, copy_from_user(), ctx, digest_algorithm::ctxsize, DBGC, DBGC_HDA, cms_signer_info::digest, digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, len, and offset.

Referenced by cms_verify_digest().

                                                                 {
        struct digest_algorithm *digest = info->digest;
        uint8_t ctx[ digest->ctxsize ];
        uint8_t block[ digest->blocksize ];
        size_t offset = 0;
        size_t frag_len;

        /* Initialise digest */
        digest_init ( digest, ctx );

        /* Process data one block at a time */
        while ( len ) {
                frag_len = len;
                if ( frag_len > sizeof ( block ) )
                        frag_len = sizeof ( block );
                copy_from_user ( block, data, offset, frag_len );
                digest_update ( digest, ctx, block, frag_len );
                offset += frag_len;
                len -= frag_len;
        }

        /* Finalise digest */
        digest_final ( digest, ctx, out );

        DBGC ( sig, "CMS %p/%p digest value:\n", sig, info );
        DBGC_HDA ( sig, 0, out, digest->digestsize );
}
static int cms_verify_digest ( struct cms_signature sig,
struct cms_signer_info info,
struct x509_certificate cert,
userptr_t  data,
size_t  len 
) [static]

Verify digest of CMS-signed data.

Parameters:
sigCMS signature
infoSigner information
certCorresponding certificate
dataSigned data
lenLength of signed data
Return values:
rcReturn status code

Definition at line 579 of file cms.c.

References cms_digest(), ctx, pubkey_algorithm::ctxsize, asn1_cursor::data, DBGC, cms_signer_info::digest, digest, digest_algorithm::digestsize, asn1_cursor::len, cms_signer_info::pubkey, pubkey_final(), pubkey_init(), pubkey_verify(), x509_subject::public_key, x509_public_key::raw, rc, cms_signer_info::signature, cms_signer_info::signature_len, strerror(), and x509_certificate::subject.

Referenced by cms_verify_signer_info().

                                                            {
        struct digest_algorithm *digest = info->digest;
        struct pubkey_algorithm *pubkey = info->pubkey;
        struct x509_public_key *public_key = &cert->subject.public_key;
        uint8_t digest_out[ digest->digestsize ];
        uint8_t ctx[ pubkey->ctxsize ];
        int rc;

        /* Generate digest */
        cms_digest ( sig, info, data, len, digest_out );

        /* Initialise public-key algorithm */
        if ( ( rc = pubkey_init ( pubkey, ctx, public_key->raw.data,
                                  public_key->raw.len ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not initialise public key: %s\n",
                       sig, info, strerror ( rc ) );
                goto err_init;
        }

        /* Verify digest */
        if ( ( rc = pubkey_verify ( pubkey, ctx, digest, digest_out,
                                    info->signature,
                                    info->signature_len ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p signature verification failed: %s\n",
                       sig, info, strerror ( rc ) );
                goto err_verify;
        }

 err_verify:
        pubkey_final ( pubkey, ctx );
 err_init:
        return rc;
}
static int cms_verify_signer_info ( struct cms_signature sig,
struct cms_signer_info info,
userptr_t  data,
size_t  len,
time_t  time,
struct x509_chain store,
struct x509_root root 
) [static]

Verify CMS signature signer information.

Parameters:
sigCMS signature
infoSigner information
dataSigned data
lenLength of signed data
timeTime at which to validate certificates
storeCertificate store, or NULL to use default
rootRoot certificate list, or NULL to use default
Return values:
rcReturn status code

Definition at line 628 of file cms.c.

References assert, x509_key_usage::bits, x509_extended_key_usage::bits, cms_signer_info::chain, cms_verify_digest(), DBGC, EACCES_NON_CODE_SIGNING, EACCES_NON_SIGNING, x509_extensions::ext_usage, x509_certificate::extensions, NULL, rc, strerror(), x509_extensions::usage, X509_CODE_SIGNING, X509_DIGITAL_SIGNATURE, x509_first(), and x509_validate_chain().

Referenced by cms_verify().

                                                             {
        struct x509_certificate *cert;
        int rc;

        /* Validate certificate chain */
        if ( ( rc = x509_validate_chain ( info->chain, time, store,
                                          root ) ) != 0 ) {
                DBGC ( sig, "CMS %p/%p could not validate chain: %s\n",
                       sig, info, strerror ( rc ) );
                return rc;
        }

        /* Extract code-signing certificate */
        cert = x509_first ( info->chain );
        assert ( cert != NULL );

        /* Check that certificate can create digital signatures */
        if ( ! ( cert->extensions.usage.bits & X509_DIGITAL_SIGNATURE ) ) {
                DBGC ( sig, "CMS %p/%p certificate cannot create signatures\n",
                       sig, info );
                return -EACCES_NON_SIGNING;
        }

        /* Check that certificate can sign code */
        if ( ! ( cert->extensions.ext_usage.bits & X509_CODE_SIGNING ) ) {
                DBGC ( sig, "CMS %p/%p certificate is not code-signing\n",
                       sig, info );
                return -EACCES_NON_CODE_SIGNING;
        }

        /* Verify digest */
        if ( ( rc = cms_verify_digest ( sig, info, cert, data, len ) ) != 0 )
                return rc;

        return 0;
}
int cms_verify ( struct cms_signature sig,
userptr_t  data,
size_t  len,
const char *  name,
time_t  time,
struct x509_chain store,
struct x509_root root 
)

Verify CMS signature.

Parameters:
sigCMS signature
dataSigned data
lenLength of signed data
nameRequired common name, or NULL to check all signatures
timeTime at which to validate certificates
storeCertificate store, or NULL to use default
rootRoot certificate list, or NULL to use default
Return values:
rcReturn status code

Definition at line 681 of file cms.c.

References cms_signer_info::chain, cms_verify_signer_info(), count, DBGC, EACCES_NO_SIGNATURES, EACCES_WRONG_NAME, cms_signature::info, info, list_for_each_entry, rc, x509_check_name(), and x509_first().

Referenced by cms_verify_fail_okx(), cms_verify_okx(), and imgverify().

                                          {
        struct cms_signer_info *info;
        struct x509_certificate *cert;
        int count = 0;
        int rc;

        /* Verify using all signerInfos */
        list_for_each_entry ( info, &sig->info, list ) {
                cert = x509_first ( info->chain );
                if ( name && ( x509_check_name ( cert, name ) != 0 ) )
                        continue;
                if ( ( rc = cms_verify_signer_info ( sig, info, data, len, time,
                                                     store, root ) ) != 0 )
                        return rc;
                count++;
        }

        /* Check that we have verified at least one signature */
        if ( count == 0 ) {
                if ( name ) {
                        DBGC ( sig, "CMS %p had no signatures matching name "
                               "%s\n", sig, name );
                        return -EACCES_WRONG_NAME;
                } else {
                        DBGC ( sig, "CMS %p had no signatures\n", sig );
                        return -EACCES_NO_SIGNATURES;
                }
        }

        return 0;
}

Variable Documentation

"pkcs7-signedData" object identifier

Definition at line 75 of file cms.c.

Initial value:

"pkcs7-signedData" object identifier cursor

Definition at line 78 of file cms.c.