andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: andre@0: /* andre@0: * Header for CMS types. andre@0: */ andre@0: andre@0: #ifndef _CMST_H_ andre@0: #define _CMST_H_ andre@0: andre@0: #include "seccomon.h" andre@0: #include "secoidt.h" andre@0: #include "certt.h" andre@0: #include "secmodt.h" andre@0: #include "secmodt.h" andre@0: andre@0: #include "plarena.h" andre@0: andre@0: /* Non-opaque objects. NOTE, though: I want them to be treated as andre@0: * opaque as much as possible. If I could hide them completely, andre@0: * I would. (I tried, but ran into trouble that was taking me too andre@0: * much time to get out of.) I still intend to try to do so. andre@0: * In fact, the only type that "outsiders" should even *name* is andre@0: * NSSCMSMessage, and they should not reference its fields. andre@0: */ andre@0: /* rjr: PKCS #11 cert handling (pk11cert.c) does use NSSCMSRecipientInfo's. andre@0: * This is because when we search the recipient list for the cert and key we andre@0: * want, we need to invert the order of the loops we used to have. The old andre@0: * loops were: andre@0: * andre@0: * For each recipient { andre@0: * find_cert = PK11_Find_AllCert(recipient->issuerSN); andre@0: * [which unrolls to... ] andre@0: * For each slot { andre@0: * Log into slot; andre@0: * search slot for cert; andre@0: * } andre@0: * } andre@0: * andre@0: * the new loop searchs all the recipients at once on a slot. this allows andre@0: * PKCS #11 to order slots in such a way that logout slots don't get checked andre@0: * if we can find the cert on a logged in slot. This eliminates lots of andre@0: * spurious password prompts when smart cards are installed... so why this andre@0: * comment? If you make NSSCMSRecipientInfo completely opaque, you need andre@0: * to provide a non-opaque list of issuerSN's (the only field PKCS#11 needs andre@0: * and fix up pk11cert.c first. NOTE: Only S/MIME calls this special PKCS #11 andre@0: * function. andre@0: */ andre@0: andre@0: typedef struct NSSCMSMessageStr NSSCMSMessage; andre@0: andre@0: typedef union NSSCMSContentUnion NSSCMSContent; andre@0: typedef struct NSSCMSContentInfoStr NSSCMSContentInfo; andre@0: andre@0: typedef struct NSSCMSSignedDataStr NSSCMSSignedData; andre@0: typedef struct NSSCMSSignerInfoStr NSSCMSSignerInfo; andre@0: typedef struct NSSCMSSignerIdentifierStr NSSCMSSignerIdentifier; andre@0: andre@0: typedef struct NSSCMSEnvelopedDataStr NSSCMSEnvelopedData; andre@0: typedef struct NSSCMSOriginatorInfoStr NSSCMSOriginatorInfo; andre@0: typedef struct NSSCMSRecipientInfoStr NSSCMSRecipientInfo; andre@0: andre@0: typedef struct NSSCMSDigestedDataStr NSSCMSDigestedData; andre@0: typedef struct NSSCMSEncryptedDataStr NSSCMSEncryptedData; andre@0: andre@0: typedef struct NSSCMSGenericWrapperDataStr NSSCMSGenericWrapperData; andre@0: andre@0: typedef struct NSSCMSAttributeStr NSSCMSAttribute; andre@0: andre@0: typedef struct NSSCMSDecoderContextStr NSSCMSDecoderContext; andre@0: typedef struct NSSCMSEncoderContextStr NSSCMSEncoderContext; andre@0: andre@0: typedef struct NSSCMSCipherContextStr NSSCMSCipherContext; andre@0: typedef struct NSSCMSDigestContextStr NSSCMSDigestContext; andre@0: andre@0: typedef struct NSSCMSContentInfoPrivateStr NSSCMSContentInfoPrivate; andre@0: andre@0: typedef SECStatus (*NSSCMSGenericWrapperDataCallback) andre@0: (NSSCMSGenericWrapperData *); andre@0: typedef void (*NSSCMSGenericWrapperDataDestroy) andre@0: (NSSCMSGenericWrapperData *); andre@0: andre@0: extern const SEC_ASN1Template NSSCMSGenericWrapperDataTemplate[]; andre@0: extern const SEC_ASN1Template NSS_PointerToCMSGenericWrapperDataTemplate[]; andre@0: andre@0: SEC_ASN1_CHOOSER_DECLARE(NSS_PointerToCMSGenericWrapperDataTemplate) andre@0: SEC_ASN1_CHOOSER_DECLARE(NSSCMSGenericWrapperDataTemplate) andre@0: andre@0: andre@0: andre@0: /* andre@0: * Type of function passed to NSSCMSDecode or NSSCMSDecoderStart. andre@0: * If specified, this is where the content bytes (only) will be "sent" andre@0: * as they are recovered during the decoding. andre@0: * And: andre@0: * Type of function passed to NSSCMSEncode or NSSCMSEncoderStart. andre@0: * This is where the DER-encoded bytes will be "sent". andre@0: * andre@0: * XXX Should just combine this with NSSCMSEncoderContentCallback type andre@0: * and use a simpler, common name. andre@0: */ andre@0: typedef void (*NSSCMSContentCallback)(void *arg, const char *buf, unsigned long len); andre@0: andre@0: /* andre@0: * Type of function passed to NSSCMSDecode or NSSCMSDecoderStart andre@0: * to retrieve the decryption key. This function is intended to be andre@0: * used for EncryptedData content info's which do not have a key available andre@0: * in a certificate, etc. andre@0: */ andre@0: typedef PK11SymKey *(*NSSCMSGetDecryptKeyCallback)(void *arg, SECAlgorithmID *algid); andre@0: andre@0: andre@0: /* ============================================================================= andre@0: * ENCAPSULATED CONTENTINFO & CONTENTINFO andre@0: */ andre@0: andre@0: union NSSCMSContentUnion { andre@0: /* either unstructured */ andre@0: SECItem * data; andre@0: /* or structured data */ andre@0: NSSCMSDigestedData * digestedData; andre@0: NSSCMSEncryptedData * encryptedData; andre@0: NSSCMSEnvelopedData * envelopedData; andre@0: NSSCMSSignedData * signedData; andre@0: NSSCMSGenericWrapperData * genericData; andre@0: /* or anonymous pointer to something */ andre@0: void * pointer; andre@0: }; andre@0: andre@0: struct NSSCMSContentInfoStr { andre@0: SECItem contentType; andre@0: NSSCMSContent content; andre@0: /* --------- local; not part of encoding --------- */ andre@0: SECOidData * contentTypeTag; andre@0: andre@0: /* additional info for encryptedData and envelopedData */ andre@0: /* we waste this space for signedData and digestedData. sue me. */ andre@0: andre@0: SECAlgorithmID contentEncAlg; andre@0: SECItem * rawContent; /* encrypted DER, optional */ andre@0: /* XXXX bytes not encrypted, but encoded? */ andre@0: /* --------- local; not part of encoding --------- */ andre@0: PK11SymKey * bulkkey; /* bulk encryption key */ andre@0: int keysize; /* size of bulk encryption key andre@0: * (only used by creation code) */ andre@0: SECOidTag contentEncAlgTag; /* oid tag of encryption algorithm andre@0: * (only used by creation code) */ andre@0: NSSCMSContentInfoPrivate *privateInfo; /* place for NSS private info */ andre@0: void *reserved; /* keep binary compatibility */ andre@0: }; andre@0: andre@0: /* ============================================================================= andre@0: * MESSAGE andre@0: */ andre@0: andre@0: struct NSSCMSMessageStr { andre@0: NSSCMSContentInfo contentInfo; /* "outer" cinfo */ andre@0: /* --------- local; not part of encoding --------- */ andre@0: PLArenaPool * poolp; andre@0: PRBool poolp_is_ours; andre@0: int refCount; andre@0: /* properties of the "inner" data */ andre@0: SECAlgorithmID ** detached_digestalgs; andre@0: SECItem ** detached_digests; andre@0: void * pwfn_arg; andre@0: NSSCMSGetDecryptKeyCallback decrypt_key_cb; andre@0: void * decrypt_key_cb_arg; andre@0: }; andre@0: andre@0: /* ============================================================================ andre@0: * GENERIC WRAPPER andre@0: * andre@0: * used for user defined types. andre@0: */ andre@0: struct NSSCMSGenericWrapperDataStr { andre@0: NSSCMSContentInfo contentInfo; andre@0: /* ---- local; not part of encoding ------ */ andre@0: NSSCMSMessage * cmsg; andre@0: /* wrapperspecific data starts here */ andre@0: }; andre@0: andre@0: /* ============================================================================= andre@0: * SIGNEDDATA andre@0: */ andre@0: andre@0: struct NSSCMSSignedDataStr { andre@0: SECItem version; andre@0: SECAlgorithmID ** digestAlgorithms; andre@0: NSSCMSContentInfo contentInfo; andre@0: SECItem ** rawCerts; andre@0: CERTSignedCrl ** crls; andre@0: NSSCMSSignerInfo ** signerInfos; andre@0: /* --------- local; not part of encoding --------- */ andre@0: NSSCMSMessage * cmsg; /* back pointer to message */ andre@0: SECItem ** digests; andre@0: CERTCertificate ** certs; andre@0: CERTCertificateList ** certLists; andre@0: CERTCertificate ** tempCerts; /* temporary certs, needed andre@0: * for example for signature andre@0: * verification */ andre@0: }; andre@0: #define NSS_CMS_SIGNED_DATA_VERSION_BASIC 1 /* what we *create* */ andre@0: #define NSS_CMS_SIGNED_DATA_VERSION_EXT 3 /* what we *create* */ andre@0: andre@0: typedef enum { andre@0: NSSCMSVS_Unverified = 0, andre@0: NSSCMSVS_GoodSignature = 1, andre@0: NSSCMSVS_BadSignature = 2, andre@0: NSSCMSVS_DigestMismatch = 3, andre@0: NSSCMSVS_SigningCertNotFound = 4, andre@0: NSSCMSVS_SigningCertNotTrusted = 5, andre@0: NSSCMSVS_SignatureAlgorithmUnknown = 6, andre@0: NSSCMSVS_SignatureAlgorithmUnsupported = 7, andre@0: NSSCMSVS_MalformedSignature = 8, andre@0: NSSCMSVS_ProcessingError = 9 andre@0: } NSSCMSVerificationStatus; andre@0: andre@0: typedef enum { andre@0: NSSCMSSignerID_IssuerSN = 0, andre@0: NSSCMSSignerID_SubjectKeyID = 1 andre@0: } NSSCMSSignerIDSelector; andre@0: andre@0: struct NSSCMSSignerIdentifierStr { andre@0: NSSCMSSignerIDSelector identifierType; andre@0: union { andre@0: CERTIssuerAndSN *issuerAndSN; andre@0: SECItem *subjectKeyID; andre@0: } id; andre@0: }; andre@0: andre@0: struct NSSCMSSignerInfoStr { andre@0: SECItem version; andre@0: NSSCMSSignerIdentifier signerIdentifier; andre@0: SECAlgorithmID digestAlg; andre@0: NSSCMSAttribute ** authAttr; andre@0: SECAlgorithmID digestEncAlg; andre@0: SECItem encDigest; andre@0: NSSCMSAttribute ** unAuthAttr; andre@0: /* --------- local; not part of encoding --------- */ andre@0: NSSCMSMessage * cmsg; /* back pointer to message */ andre@0: CERTCertificate * cert; andre@0: CERTCertificateList * certList; andre@0: PRTime signingTime; andre@0: NSSCMSVerificationStatus verificationStatus; andre@0: SECKEYPrivateKey * signingKey; /* Used if we're using subjKeyID*/ andre@0: SECKEYPublicKey * pubKey; andre@0: }; andre@0: #define NSS_CMS_SIGNER_INFO_VERSION_ISSUERSN 1 /* what we *create* */ andre@0: #define NSS_CMS_SIGNER_INFO_VERSION_SUBJKEY 3 /* what we *create* */ andre@0: andre@0: typedef enum { andre@0: NSSCMSCM_None = 0, andre@0: NSSCMSCM_CertOnly = 1, andre@0: NSSCMSCM_CertChain = 2, andre@0: NSSCMSCM_CertChainWithRoot = 3 andre@0: } NSSCMSCertChainMode; andre@0: andre@0: /* ============================================================================= andre@0: * ENVELOPED DATA andre@0: */ andre@0: struct NSSCMSEnvelopedDataStr { andre@0: SECItem version; andre@0: NSSCMSOriginatorInfo * originatorInfo; /* optional */ andre@0: NSSCMSRecipientInfo ** recipientInfos; andre@0: NSSCMSContentInfo contentInfo; andre@0: NSSCMSAttribute ** unprotectedAttr; andre@0: /* --------- local; not part of encoding --------- */ andre@0: NSSCMSMessage * cmsg; /* back pointer to message */ andre@0: }; andre@0: #define NSS_CMS_ENVELOPED_DATA_VERSION_REG 0 /* what we *create* */ andre@0: #define NSS_CMS_ENVELOPED_DATA_VERSION_ADV 2 /* what we *create* */ andre@0: andre@0: struct NSSCMSOriginatorInfoStr { andre@0: SECItem ** rawCerts; andre@0: CERTSignedCrl ** crls; andre@0: /* --------- local; not part of encoding --------- */ andre@0: CERTCertificate ** certs; andre@0: }; andre@0: andre@0: /* ----------------------------------------------------------------------------- andre@0: * key transport recipient info andre@0: */ andre@0: typedef enum { andre@0: NSSCMSRecipientID_IssuerSN = 0, andre@0: NSSCMSRecipientID_SubjectKeyID = 1, andre@0: NSSCMSRecipientID_BrandNew = 2 andre@0: } NSSCMSRecipientIDSelector; andre@0: andre@0: struct NSSCMSRecipientIdentifierStr { andre@0: NSSCMSRecipientIDSelector identifierType; andre@0: union { andre@0: CERTIssuerAndSN *issuerAndSN; andre@0: SECItem *subjectKeyID; andre@0: } id; andre@0: }; andre@0: typedef struct NSSCMSRecipientIdentifierStr NSSCMSRecipientIdentifier; andre@0: andre@0: struct NSSCMSKeyTransRecipientInfoStr { andre@0: SECItem version; andre@0: NSSCMSRecipientIdentifier recipientIdentifier; andre@0: SECAlgorithmID keyEncAlg; andre@0: SECItem encKey; andre@0: }; andre@0: typedef struct NSSCMSKeyTransRecipientInfoStr NSSCMSKeyTransRecipientInfo; andre@0: andre@0: /* andre@0: * View comments before NSSCMSRecipientInfoStr for purpose of this andre@0: * structure. andre@0: */ andre@0: struct NSSCMSKeyTransRecipientInfoExStr { andre@0: NSSCMSKeyTransRecipientInfo recipientInfo; andre@0: int version; /* version of this structure (0) */ andre@0: SECKEYPublicKey *pubKey; andre@0: }; andre@0: andre@0: typedef struct NSSCMSKeyTransRecipientInfoExStr NSSCMSKeyTransRecipientInfoEx; andre@0: andre@0: #define NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN 0 /* what we *create* */ andre@0: #define NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY 2 /* what we *create* */ andre@0: andre@0: /* ----------------------------------------------------------------------------- andre@0: * key agreement recipient info andre@0: */ andre@0: struct NSSCMSOriginatorPublicKeyStr { andre@0: SECAlgorithmID algorithmIdentifier; andre@0: SECItem publicKey; /* bit string! */ andre@0: }; andre@0: typedef struct NSSCMSOriginatorPublicKeyStr NSSCMSOriginatorPublicKey; andre@0: andre@0: typedef enum { andre@0: NSSCMSOriginatorIDOrKey_IssuerSN = 0, andre@0: NSSCMSOriginatorIDOrKey_SubjectKeyID = 1, andre@0: NSSCMSOriginatorIDOrKey_OriginatorPublicKey = 2 andre@0: } NSSCMSOriginatorIDOrKeySelector; andre@0: andre@0: struct NSSCMSOriginatorIdentifierOrKeyStr { andre@0: NSSCMSOriginatorIDOrKeySelector identifierType; andre@0: union { andre@0: CERTIssuerAndSN *issuerAndSN; /* static-static */ andre@0: SECItem *subjectKeyID; /* static-static */ andre@0: NSSCMSOriginatorPublicKey originatorPublicKey; /* ephemeral-static */ andre@0: } id; andre@0: }; andre@0: typedef struct NSSCMSOriginatorIdentifierOrKeyStr NSSCMSOriginatorIdentifierOrKey; andre@0: andre@0: struct NSSCMSRecipientKeyIdentifierStr { andre@0: SECItem * subjectKeyIdentifier; andre@0: SECItem * date; /* optional */ andre@0: SECItem * other; /* optional */ andre@0: }; andre@0: typedef struct NSSCMSRecipientKeyIdentifierStr NSSCMSRecipientKeyIdentifier; andre@0: andre@0: typedef enum { andre@0: NSSCMSKeyAgreeRecipientID_IssuerSN = 0, andre@0: NSSCMSKeyAgreeRecipientID_RKeyID = 1 andre@0: } NSSCMSKeyAgreeRecipientIDSelector; andre@0: andre@0: struct NSSCMSKeyAgreeRecipientIdentifierStr { andre@0: NSSCMSKeyAgreeRecipientIDSelector identifierType; andre@0: union { andre@0: CERTIssuerAndSN *issuerAndSN; andre@0: NSSCMSRecipientKeyIdentifier recipientKeyIdentifier; andre@0: } id; andre@0: }; andre@0: typedef struct NSSCMSKeyAgreeRecipientIdentifierStr NSSCMSKeyAgreeRecipientIdentifier; andre@0: andre@0: struct NSSCMSRecipientEncryptedKeyStr { andre@0: NSSCMSKeyAgreeRecipientIdentifier recipientIdentifier; andre@0: SECItem encKey; andre@0: }; andre@0: typedef struct NSSCMSRecipientEncryptedKeyStr NSSCMSRecipientEncryptedKey; andre@0: andre@0: struct NSSCMSKeyAgreeRecipientInfoStr { andre@0: SECItem version; andre@0: NSSCMSOriginatorIdentifierOrKey originatorIdentifierOrKey; andre@0: SECItem * ukm; /* optional */ andre@0: SECAlgorithmID keyEncAlg; andre@0: NSSCMSRecipientEncryptedKey ** recipientEncryptedKeys; andre@0: }; andre@0: typedef struct NSSCMSKeyAgreeRecipientInfoStr NSSCMSKeyAgreeRecipientInfo; andre@0: andre@0: #define NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION 3 /* what we *create* */ andre@0: andre@0: /* ----------------------------------------------------------------------------- andre@0: * KEK recipient info andre@0: */ andre@0: struct NSSCMSKEKIdentifierStr { andre@0: SECItem keyIdentifier; andre@0: SECItem * date; /* optional */ andre@0: SECItem * other; /* optional */ andre@0: }; andre@0: typedef struct NSSCMSKEKIdentifierStr NSSCMSKEKIdentifier; andre@0: andre@0: struct NSSCMSKEKRecipientInfoStr { andre@0: SECItem version; andre@0: NSSCMSKEKIdentifier kekIdentifier; andre@0: SECAlgorithmID keyEncAlg; andre@0: SECItem encKey; andre@0: }; andre@0: typedef struct NSSCMSKEKRecipientInfoStr NSSCMSKEKRecipientInfo; andre@0: andre@0: #define NSS_CMS_KEK_RECIPIENT_INFO_VERSION 4 /* what we *create* */ andre@0: andre@0: /* ----------------------------------------------------------------------------- andre@0: * recipient info andre@0: */ andre@0: andre@0: typedef enum { andre@0: NSSCMSRecipientInfoID_KeyTrans = 0, andre@0: NSSCMSRecipientInfoID_KeyAgree = 1, andre@0: NSSCMSRecipientInfoID_KEK = 2 andre@0: } NSSCMSRecipientInfoIDSelector; andre@0: andre@0: /* andre@0: * In order to preserve backwards binary compatibility when implementing andre@0: * creation of Recipient Info's that uses subjectKeyID in the andre@0: * keyTransRecipientInfo we need to stash a public key pointer in this andre@0: * structure somewhere. We figured out that NSSCMSKeyTransRecipientInfo andre@0: * is the smallest member of the ri union. We're in luck since that's andre@0: * the very structure that would need to use the public key. So we created andre@0: * a new structure NSSCMSKeyTransRecipientInfoEx which has a member andre@0: * NSSCMSKeyTransRecipientInfo as the first member followed by a version andre@0: * and a public key pointer. This way we can keep backwards compatibility andre@0: * without changing the size of this structure. andre@0: * andre@0: * BTW, size of structure: andre@0: * NSSCMSKeyTransRecipientInfo: 9 ints, 4 pointers andre@0: * NSSCMSKeyAgreeRecipientInfo: 12 ints, 8 pointers andre@0: * NSSCMSKEKRecipientInfo: 10 ints, 7 pointers andre@0: * andre@0: * The new structure: andre@0: * NSSCMSKeyTransRecipientInfoEx: sizeof(NSSCMSKeyTransRecipientInfo) + andre@0: * 1 int, 1 pointer andre@0: */ andre@0: andre@0: struct NSSCMSRecipientInfoStr { andre@0: NSSCMSRecipientInfoIDSelector recipientInfoType; andre@0: union { andre@0: NSSCMSKeyTransRecipientInfo keyTransRecipientInfo; andre@0: NSSCMSKeyAgreeRecipientInfo keyAgreeRecipientInfo; andre@0: NSSCMSKEKRecipientInfo kekRecipientInfo; andre@0: NSSCMSKeyTransRecipientInfoEx keyTransRecipientInfoEx; andre@0: } ri; andre@0: /* --------- local; not part of encoding --------- */ andre@0: NSSCMSMessage * cmsg; /* back pointer to message */ andre@0: CERTCertificate * cert; /* recipient's certificate */ andre@0: }; andre@0: andre@0: /* ============================================================================= andre@0: * DIGESTED DATA andre@0: */ andre@0: struct NSSCMSDigestedDataStr { andre@0: SECItem version; andre@0: SECAlgorithmID digestAlg; andre@0: NSSCMSContentInfo contentInfo; andre@0: SECItem digest; andre@0: /* --------- local; not part of encoding --------- */ andre@0: NSSCMSMessage * cmsg; /* back pointer */ andre@0: SECItem cdigest; /* calculated digest */ andre@0: }; andre@0: #define NSS_CMS_DIGESTED_DATA_VERSION_DATA 0 /* what we *create* */ andre@0: #define NSS_CMS_DIGESTED_DATA_VERSION_ENCAP 2 /* what we *create* */ andre@0: andre@0: /* ============================================================================= andre@0: * ENCRYPTED DATA andre@0: */ andre@0: struct NSSCMSEncryptedDataStr { andre@0: SECItem version; andre@0: NSSCMSContentInfo contentInfo; andre@0: NSSCMSAttribute ** unprotectedAttr; /* optional */ andre@0: /* --------- local; not part of encoding --------- */ andre@0: NSSCMSMessage * cmsg; /* back pointer */ andre@0: }; andre@0: #define NSS_CMS_ENCRYPTED_DATA_VERSION 0 /* what we *create* */ andre@0: #define NSS_CMS_ENCRYPTED_DATA_VERSION_UPATTR 2 /* what we *create* */ andre@0: andre@0: /* andre@0: * ***************************************************************************** andre@0: * ***************************************************************************** andre@0: * ***************************************************************************** andre@0: */ andre@0: andre@0: /* andre@0: * See comment above about this type not really belonging to CMS. andre@0: */ andre@0: struct NSSCMSAttributeStr { andre@0: /* The following fields make up an encoded Attribute: */ andre@0: SECItem type; andre@0: SECItem ** values; /* data may or may not be encoded */ andre@0: /* The following fields are not part of an encoded Attribute: */ andre@0: SECOidData * typeTag; andre@0: PRBool encoded; /* when true, values are encoded */ andre@0: }; andre@0: andre@0: #endif /* _CMST_H_ */