tsaTemplates.c   [plain text]


/*
 * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved.
 * 
 * @APPLE_LICENSE_HEADER_START@
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Apple Public Source License
 * Version 2.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://www.opensource.apple.com/apsl/ and read it before using this
 * file.
 * 
 * The Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 * Please see the License for the specific language governing rights and
 * limitations under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 *
 * tsaTemplates.c -  ASN1 templates Time Stamping Authority requests and responses
 */

#include <security_asn1/keyTemplates.h>     /* for kSecAsn1AlgorithmIDTemplate */
#include <security_asn1/SecAsn1Templates.h>
#include <stddef.h>
#include <assert.h>

#include "tsaTemplates.h"
#include "cmslocal.h"

// *** from CMSEncoder.cpp

typedef struct {
    CSSM_OID	contentType;
    CSSM_DATA	content;    
} SimpleContentInfo;

// SecCmsContentInfoTemplate
static const SecAsn1Template cmsSimpleContentInfoTemplate[] = {
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SimpleContentInfo) },
    { SEC_ASN1_OBJECT_ID, offsetof(SimpleContentInfo, contentType) },
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
	  offsetof(SimpleContentInfo, content),
	  kSecAsn1AnyTemplate },
    { 0, }
};

#pragma mark ----- tsa -----

/*
Accuracy ::= SEQUENCE {
                seconds        INTEGER           OPTIONAL,
                millis     [0] INTEGER  (1..999) OPTIONAL,
                micros     [1] INTEGER  (1..999) OPTIONAL  }
*/

const SecAsn1Template kSecAsn1SignedIntegerTemplate[] = {
    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT, 0, NULL, sizeof(SecAsn1Item) }
};

const SecAsn1Template kSecAsn1UnsignedIntegerTemplate[] = {
    { SEC_ASN1_INTEGER, 0, NULL, sizeof(SecAsn1Item) }
};

const SecAsn1Template kSecAsn1TSAAccuracyTemplate[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TSAAccuracy) },
    { SEC_ASN1_INTEGER,
        offsetof(SecAsn1TSAAccuracy, seconds) },
    { SEC_ASN1_CONTEXT_SPECIFIC | 0 | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSAAccuracy, millis), kSecAsn1UnsignedIntegerTemplate },
    { SEC_ASN1_CONTEXT_SPECIFIC | 1 | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSAAccuracy, micros), kSecAsn1UnsignedIntegerTemplate },
    { 0 }
};

/*
MessageImprint ::= SEQUENCE  {
     hashAlgorithm                AlgorithmIdentifier,
     hashedMessage                OCTET STRING  }
*/

const SecAsn1Template kSecAsn1TSAMessageImprintTemplate[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TSAMessageImprint) },
    { SEC_ASN1_INLINE, offsetof(SecAsn1TSAMessageImprint,hashAlgorithm),
        kSecAsn1AlgorithmIDTemplate },
    { SEC_ASN1_OCTET_STRING,
        offsetof(SecAsn1TSAMessageImprint,hashedMessage) },
    { 0 }
};

/*
    TimeStampReq ::= SEQUENCE  {
       version                  INTEGER  { v1(1) },
       messageImprint           MessageImprint,
         --a hash algorithm OID and the hash value of the data to be
         --time-stamped
       reqPolicy                TSAPolicyId                OPTIONAL,
       nonce                    INTEGER                    OPTIONAL,
       certReq                  BOOLEAN                    DEFAULT FALSE,
       extensions               [0] IMPLICIT Extensions    OPTIONAL  }

    MessageImprint ::= SEQUENCE  {
         hashAlgorithm                AlgorithmIdentifier,
         hashedMessage                OCTET STRING  }

    TSAPolicyId ::= OBJECT IDENTIFIER
*/

const SecAsn1Template kSecAsn1TSATimeStampReqTemplate[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TSATimeStampReq) },
    { SEC_ASN1_INTEGER,
        offsetof(SecAsn1TSATimeStampReq, version) },
    { SEC_ASN1_INLINE, offsetof(SecAsn1TSATimeStampReq,messageImprint),
        kSecAsn1TSAMessageImprintTemplate },
    { SEC_ASN1_OBJECT_ID | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSATimeStampReq,reqPolicy) },
    { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSATimeStampReq, nonce) },
    { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, 
        offsetof(SecAsn1TSATimeStampReq, certReq) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
        offsetof(SecAsn1TSATimeStampReq, extensions),
        kSecAsn1SequenceOfCertExtensionTemplate },
    { 0 }
};

/*
    PKIFreeText ::= SEQUENCE {
        SIZE (1..MAX) OF UTF8String
        -- text encoded as UTF-8 String (note: each UTF8String SHOULD
        -- include an RFC 1766 language tag to indicate the language -- of the contained text)
    }
    
    See e.g. kSecAsn1SequenceOfUTF8StringTemplate
*/

const SecAsn1Template kSecAsn1TSAPKIStatusInfoTemplate[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TSAPKIStatusInfo) },
    { SEC_ASN1_INTEGER,
        offsetof(SecAsn1TSAPKIStatusInfo, status) },
    {  SEC_ASN1_CONSTRUCTED | SEC_ASN1_SEQUENCE | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSAPKIStatusInfo, statusString) },
    { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSAPKIStatusInfo,failInfo) },
    { 0 }
};

const SecAsn1Template kSecAsn1TSAPKIStatusInfoTemplateRFC3161[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TSAPKIStatusInfo) },
    { SEC_ASN1_INTEGER,
        offsetof(SecAsn1TSAPKIStatusInfo, status) },
    { SEC_ASN1_UTF8_STRING | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSAPKIStatusInfo, statusString) },
    { SEC_ASN1_BIT_STRING | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSAPKIStatusInfo,failInfo) },
    { 0 }
};

const SecAsn1Template kSecAsn1TSATimeStampRespTemplate[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TimeStampResp) },
    { SEC_ASN1_INLINE, offsetof(SecAsn1TimeStampResp,status),
        kSecAsn1TSAPKIStatusInfoTemplate },
    { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL, offsetof(SecAsn1TimeStampResp,timeStampToken),
        SecCmsContentInfoTemplate },
    { 0 }
};

// Decode the status but not the TimeStampToken
const SecAsn1Template kSecAsn1TSATimeStampRespTemplateDER[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TimeStampRespDER) },
    { SEC_ASN1_INLINE, offsetof(SecAsn1TimeStampRespDER,status),
        kSecAsn1TSAPKIStatusInfoTemplate },
    { SEC_ASN1_ANY | SEC_ASN1_OPTIONAL ,//| SEC_ASN1_SAVE,
	  offsetof(SecAsn1TimeStampRespDER, timeStampTokenDER), kSecAsn1AnyTemplate  },
    { 0 }
};

/*
    RFC 3161               Time-Stamp Protocol (TSP)             August 2001

    TimeStampToken ::= ContentInfo

     -- contentType is id-signedData as defined in [CMS]
     -- content is SignedData as defined in([CMS])
     -- eContentType within SignedData is id-ct-TSTInfo
     -- eContent within SignedData is TSTInfo

    TSTInfo ::= SEQUENCE  {
        version                      INTEGER  { v1(1) },
        policy                       TSAPolicyId,
        messageImprint               MessageImprint,
          -- MUST have the same value as the similar field in
          -- TimeStampReq
        serialNumber                 INTEGER,
         -- Time-Stamping users MUST be ready to accommodate integers
         -- up to 160 bits.
        genTime                      GeneralizedTime,
        accuracy                     Accuracy                 OPTIONAL,
        ordering                     BOOLEAN             DEFAULT FALSE,
        nonce                        INTEGER                  OPTIONAL,
          -- MUST be present if the similar field was present
          -- in TimeStampReq.  In that case it MUST have the same value.
        tsa                          [0] GeneralName          OPTIONAL,
        extensions                   [1] IMPLICIT Extensions  OPTIONAL   }

    Accuracy ::= SEQUENCE {
                    seconds        INTEGER           OPTIONAL,
                    millis     [0] INTEGER  (1..999) OPTIONAL,
                    micros     [1] INTEGER  (1..999) OPTIONAL  }
*/
    
const SecAsn1Template kSecAsn1TSATSTInfoTemplate[] = {
    { SEC_ASN1_SEQUENCE,
	  0, NULL, sizeof(SecAsn1TSATSTInfo) },
    { SEC_ASN1_INTEGER,
        offsetof(SecAsn1TSATSTInfo, version) },
    { SEC_ASN1_OBJECT_ID,
        offsetof(SecAsn1TSATSTInfo,reqPolicy) },
   { SEC_ASN1_INLINE, offsetof(SecAsn1TSATSTInfo,messageImprint),
        kSecAsn1TSAMessageImprintTemplate },
    { SEC_ASN1_INTEGER,
        offsetof(SecAsn1TSATSTInfo, serialNumber) },
    { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM,
        offsetof(SecAsn1TSATSTInfo,genTime) },
    { SEC_ASN1_INLINE | SEC_ASN1_OPTIONAL,
	  offsetof(SecAsn1TSATSTInfo,accuracy),
	  kSecAsn1TSAAccuracyTemplate },
    { SEC_ASN1_BOOLEAN | SEC_ASN1_OPTIONAL, 
        offsetof(SecAsn1TSATSTInfo, ordering) },
    { SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSATSTInfo, nonce) },
    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0 | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSATSTInfo, tsa),
        kSecAsn1GenNameOtherNameTemplate},

    { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1 | SEC_ASN1_OPTIONAL,
        offsetof(SecAsn1TSATSTInfo, extensions),
        kSecAsn1CertExtensionTemplate },
    { 0 }
};