ASN_CMS_NewRC2CBCParameter( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRC2CBCParameter( ASN_CMS_CONTEXT *ctx, ASN_CMS_RC2CBCParameter *f); size_t ASN_CMS_SizeofRC2CBCParameter ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RC2CBCParameter *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRC2CBCParameter( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RC2CBCParameter *asnstruct, int *erret); size_t ASN_CMS_UnpackRC2CBCParameter( ASN_CMS_CONTEXT *ctx, ASN_CMS_RC2CBCParameter **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewRC2wrapParameter (ASN_CMS_RC2wrapParameter *)ASN_CMS_NewRC2ParameterVersion #define ASN_CMS_FreeRC2wrapParameter ASN_CMS_FreeRC2ParameterVersion #define ASN_CMS_SizeofRC2wrapParameter ASN_CMS_SizeofRC2ParameterVersion #define ASN_CMS_PackRC2wrapParameter ASN_CMS_PackRC2ParameterVersion #define ASN_CMS_UnpackRC2wrapParameter ASN_CMS_UnpackRC2ParameterVersion ASN_CMS_Time *ASN_CMS_NewTime( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeTime( ASN_CMS_CONTEXT *ctx, ASN_CMS_Time *f); size_t ASN_CMS_SizeofTime ( ASN_CMS_CONTEXT *ctx, ASN_CMS_Time *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackTime( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_Time *asnstruct, int *erret); size_t ASN_CMS_UnpackTime( ASN_CMS_CONTEXT *ctx, ASN_CMS_Time **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_attrValues_SET_OF *ASN_CMS_NewattrValues_SET_OF( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeattrValues_SET_OF( ASN_CMS_CONTEXT *ctx, ASN_CMS_attrValues_SET_OF *f); size_t ASN_CMS_SizeofattrValues_SET_OF ( ASN_CMS_CONTEXT *ctx, ASN_CMS_attrValues_SET_OF *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackattrValues_SET_OF( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_attrValues_SET_OF *asnstruct, int *erret); size_t ASN_CMS_UnpackattrValues_SET_OF( ASN_CMS_CONTEXT *ctx, ASN_CMS_attrValues_SET_OF **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_Attribute *ASN_CMS_NewAttribute( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeAttribute( ASN_CMS_CONTEXT *ctx, ASN_CMS_Attribute *f); size_t ASN_CMS_SizeofAttribute ( ASN_CMS_CONTEXT *ctx, ASN_CMS_Attribute *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackAttribute( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_Attribute *asnstruct, int *erret); size_t ASN_CMS_UnpackAttribute( ASN_CMS_CONTEXT *ctx, ASN_CMS_Attribute **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewContentEncryptionAlgorithmIdentifier (ASN_CMS_ContentEncryptionAlgorithmIdentifier *)ASN_CMS_NewAlgorithmIdentifier #define ASN_CMS_FreeContentEncryptionAlgorithmIdentifier ASN_CMS_FreeAlgorithmIdentifier #define ASN_CMS_SizeofContentEncryptionAlgorithmIdentifier ASN_CMS_SizeofAlgorithmIdentifier #define ASN_CMS_PackContentEncryptionAlgorithmIdentifier ASN_CMS_PackAlgorithmIdentifier #define ASN_CMS_UnpackContentEncryptionAlgorithmIdentifier ASN_CMS_UnpackAlgorithmIdentifier #define ASN_CMS_NewDigestAlgorithmIdentifier (ASN_CMS_DigestAlgorithmIdentifier *)ASN_CMS_NewAlgorithmIdentifier #define ASN_CMS_FreeDigestAlgorithmIdentifier ASN_CMS_FreeAlgorithmIdentifier #define ASN_CMS_SizeofDigestAlgorithmIdentifier ASN_CMS_SizeofAlgorithmIdentifier #define ASN_CMS_PackDigestAlgorithmIdentifier ASN_CMS_PackAlgorithmIdentifier #define ASN_CMS_UnpackDigestAlgorithmIdentifier ASN_CMS_UnpackAlgorithmIdentifier ASN_CMS_Extensions *ASN_CMS_NewExtensions( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeExtensions( ASN_CMS_CONTEXT *ctx, ASN_CMS_Extensions *f); size_t ASN_CMS_SizeofExtensions ( ASN_CMS_CONTEXT *ctx, ASN_CMS_Extensions *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackExtensions( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_Extensions *asnstruct, int *erret); size_t ASN_CMS_UnpackExtensions( ASN_CMS_CONTEXT *ctx, ASN_CMS_Extensions **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_KEKIdentifier *ASN_CMS_NewKEKIdentifier( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeKEKIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_KEKIdentifier *f); size_t ASN_CMS_SizeofKEKIdentifier ( ASN_CMS_CONTEXT *ctx, ASN_CMS_KEKIdentifier *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackKEKIdentifier( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_KEKIdentifier *asnstruct, int *erret); size_t ASN_CMS_UnpackKEKIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_KEKIdentifier **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewKeyEncryptionAlgorithmIdentifier (ASN_CMS_KeyEncryptionAlgorithmIdentifier *)ASN_CMS_NewAlgorithmIdentifier #define ASN_CMS_FreeKeyEncryptionAlgorithmIdentifier ASN_CMS_FreeAlgorithmIdentifier #define ASN_CMS_SizeofKeyEncryptionAlgorithmIdentifier ASN_CMS_SizeofAlgorithmIdentifier #define ASN_CMS_PackKeyEncryptionAlgorithmIdentifier ASN_CMS_PackAlgorithmIdentifier #define ASN_CMS_UnpackKeyEncryptionAlgorithmIdentifier ASN_CMS_UnpackAlgorithmIdentifier #define ASN_CMS_NewKeyWrapAlgorithm (ASN_CMS_KeyWrapAlgorithm *)ASN_CMS_NewAlgorithmIdentifier #define ASN_CMS_FreeKeyWrapAlgorithm ASN_CMS_FreeAlgorithmIdentifier #define ASN_CMS_SizeofKeyWrapAlgorithm ASN_CMS_SizeofAlgorithmIdentifier #define ASN_CMS_PackKeyWrapAlgorithm ASN_CMS_PackAlgorithmIdentifier #define ASN_CMS_UnpackKeyWrapAlgorithm ASN_CMS_UnpackAlgorithmIdentifier #define ASN_CMS_NewMessageAuthenticationCodeAlgorithm (ASN_CMS_MessageAuthenticationCodeAlgorithm *)ASN_CMS_NewAlgorithmIdentifier #define ASN_CMS_FreeMessageAuthenticationCodeAlgorithm ASN_CMS_FreeAlgorithmIdentifier #define ASN_CMS_SizeofMessageAuthenticationCodeAlgorithm ASN_CMS_SizeofAlgorithmIdentifier #define ASN_CMS_PackMessageAuthenticationCodeAlgorithm ASN_CMS_PackAlgorithmIdentifier #define ASN_CMS_UnpackMessageAuthenticationCodeAlgorithm ASN_CMS_UnpackAlgorithmIdentifier ASN_CMS_OriginatorPublicKey *ASN_CMS_NewOriginatorPublicKey( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeOriginatorPublicKey( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorPublicKey *f); size_t ASN_CMS_SizeofOriginatorPublicKey ( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorPublicKey *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackOriginatorPublicKey( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OriginatorPublicKey *asnstruct, int *erret); size_t ASN_CMS_UnpackOriginatorPublicKey( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorPublicKey **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RecipientIdentifier *ASN_CMS_NewRecipientIdentifier( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRecipientIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientIdentifier *f); size_t ASN_CMS_SizeofRecipientIdentifier ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientIdentifier *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRecipientIdentifier( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RecipientIdentifier *asnstruct, int *erret); size_t ASN_CMS_UnpackRecipientIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientIdentifier **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RecipientKeyIdentifier *ASN_CMS_NewRecipientKeyIdentifier( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRecipientKeyIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientKeyIdentifier *f); size_t ASN_CMS_SizeofRecipientKeyIdentifier ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientKeyIdentifier *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRecipientKeyIdentifier( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RecipientKeyIdentifier *asnstruct, int *erret); size_t ASN_CMS_UnpackRecipientKeyIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientKeyIdentifier **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RelativeDistinguishedName *ASN_CMS_NewRelativeDistinguishedName( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRelativeDistinguishedName( ASN_CMS_CONTEXT *ctx, ASN_CMS_RelativeDistinguishedName *f); size_t ASN_CMS_SizeofRelativeDistinguishedName ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RelativeDistinguishedName *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRelativeDistinguishedName( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RelativeDistinguishedName *asnstruct, int *erret); size_t ASN_CMS_UnpackRelativeDistinguishedName( ASN_CMS_CONTEXT *ctx, ASN_CMS_RelativeDistinguishedName **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewSignatureAlgorithmIdentifier (ASN_CMS_SignatureAlgorithmIdentifier *)ASN_CMS_NewAlgorithmIdentifier #define ASN_CMS_FreeSignatureAlgorithmIdentifier ASN_CMS_FreeAlgorithmIdentifier #define ASN_CMS_SizeofSignatureAlgorithmIdentifier ASN_CMS_SizeofAlgorithmIdentifier #define ASN_CMS_PackSignatureAlgorithmIdentifier ASN_CMS_PackAlgorithmIdentifier #define ASN_CMS_UnpackSignatureAlgorithmIdentifier ASN_CMS_UnpackAlgorithmIdentifier ASN_CMS_SignerIdentifier *ASN_CMS_NewSignerIdentifier( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSignerIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerIdentifier *f); size_t ASN_CMS_SizeofSignerIdentifier ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerIdentifier *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSignerIdentifier( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SignerIdentifier *asnstruct, int *erret); size_t ASN_CMS_UnpackSignerIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerIdentifier **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewSigningTime (ASN_CMS_SigningTime *)ASN_CMS_NewTime #define ASN_CMS_FreeSigningTime ASN_CMS_FreeTime #define ASN_CMS_SizeofSigningTime ASN_CMS_SizeofTime #define ASN_CMS_PackSigningTime ASN_CMS_PackTime #define ASN_CMS_UnpackSigningTime ASN_CMS_UnpackTime ASN_CMS_SubjectPublicKeyInfo *ASN_CMS_NewSubjectPublicKeyInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSubjectPublicKeyInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_SubjectPublicKeyInfo *f); size_t ASN_CMS_SizeofSubjectPublicKeyInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SubjectPublicKeyInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSubjectPublicKeyInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SubjectPublicKeyInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackSubjectPublicKeyInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_SubjectPublicKeyInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_Validity *ASN_CMS_NewValidity( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeValidity( ASN_CMS_CONTEXT *ctx, ASN_CMS_Validity *f); size_t ASN_CMS_SizeofValidity ( ASN_CMS_CONTEXT *ctx, ASN_CMS_Validity *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackValidity( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_Validity *asnstruct, int *erret); size_t ASN_CMS_UnpackValidity( ASN_CMS_CONTEXT *ctx, ASN_CMS_Validity **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_AuthAttributes *ASN_CMS_NewAuthAttributes( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeAuthAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthAttributes *f); size_t ASN_CMS_SizeofAuthAttributes ( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthAttributes *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackAuthAttributes( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_AuthAttributes *asnstruct, int *erret); size_t ASN_CMS_UnpackAuthAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthAttributes **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_DigestAlgorithmIdentifiers *ASN_CMS_NewDigestAlgorithmIdentifiers( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeDigestAlgorithmIdentifiers( ASN_CMS_CONTEXT *ctx, ASN_CMS_DigestAlgorithmIdentifiers *f); size_t ASN_CMS_SizeofDigestAlgorithmIdentifiers ( ASN_CMS_CONTEXT *ctx, ASN_CMS_DigestAlgorithmIdentifiers *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackDigestAlgorithmIdentifiers( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_DigestAlgorithmIdentifiers *asnstruct, int *erret); size_t ASN_CMS_UnpackDigestAlgorithmIdentifiers( ASN_CMS_CONTEXT *ctx, ASN_CMS_DigestAlgorithmIdentifiers **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_DigestedData *ASN_CMS_NewDigestedData( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeDigestedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_DigestedData *f); size_t ASN_CMS_SizeofDigestedData ( ASN_CMS_CONTEXT *ctx, ASN_CMS_DigestedData *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackDigestedData( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_DigestedData *asnstruct, int *erret); size_t ASN_CMS_UnpackDigestedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_DigestedData **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_EncryptedContentInfo *ASN_CMS_NewEncryptedContentInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeEncryptedContentInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_EncryptedContentInfo *f); size_t ASN_CMS_SizeofEncryptedContentInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_EncryptedContentInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackEncryptedContentInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_EncryptedContentInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackEncryptedContentInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_EncryptedContentInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_KEKRecipientInfo *ASN_CMS_NewKEKRecipientInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeKEKRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_KEKRecipientInfo *f); size_t ASN_CMS_SizeofKEKRecipientInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_KEKRecipientInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackKEKRecipientInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_KEKRecipientInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackKEKRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_KEKRecipientInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_KeyAgreeRecipientIdentifier *ASN_CMS_NewKeyAgreeRecipientIdentifier( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeKeyAgreeRecipientIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyAgreeRecipientIdentifier *f); size_t ASN_CMS_SizeofKeyAgreeRecipientIdentifier ( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyAgreeRecipientIdentifier *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackKeyAgreeRecipientIdentifier( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_KeyAgreeRecipientIdentifier *asnstruct, int *erret); size_t ASN_CMS_UnpackKeyAgreeRecipientIdentifier( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyAgreeRecipientIdentifier **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_KeyTransRecipientInfo *ASN_CMS_NewKeyTransRecipientInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeKeyTransRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyTransRecipientInfo *f); size_t ASN_CMS_SizeofKeyTransRecipientInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyTransRecipientInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackKeyTransRecipientInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_KeyTransRecipientInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackKeyTransRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyTransRecipientInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_OriginatorIdentifierOrKey *ASN_CMS_NewOriginatorIdentifierOrKey( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeOriginatorIdentifierOrKey( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorIdentifierOrKey *f); size_t ASN_CMS_SizeofOriginatorIdentifierOrKey ( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorIdentifierOrKey *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackOriginatorIdentifierOrKey( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OriginatorIdentifierOrKey *asnstruct, int *erret); size_t ASN_CMS_UnpackOriginatorIdentifierOrKey( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorIdentifierOrKey **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RDNSequence *ASN_CMS_NewRDNSequence( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRDNSequence( ASN_CMS_CONTEXT *ctx, ASN_CMS_RDNSequence *f); size_t ASN_CMS_SizeofRDNSequence ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RDNSequence *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRDNSequence( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RDNSequence *asnstruct, int *erret); size_t ASN_CMS_UnpackRDNSequence( ASN_CMS_CONTEXT *ctx, ASN_CMS_RDNSequence **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_SignedAttributes *ASN_CMS_NewSignedAttributes( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSignedAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignedAttributes *f); size_t ASN_CMS_SizeofSignedAttributes ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignedAttributes *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSignedAttributes( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SignedAttributes *asnstruct, int *erret); size_t ASN_CMS_UnpackSignedAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignedAttributes **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_ToBeSigned *ASN_CMS_NewToBeSigned( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeToBeSigned( ASN_CMS_CONTEXT *ctx, ASN_CMS_ToBeSigned *f); size_t ASN_CMS_SizeofToBeSigned ( ASN_CMS_CONTEXT *ctx, ASN_CMS_ToBeSigned *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackToBeSigned( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_ToBeSigned *asnstruct, int *erret); size_t ASN_CMS_UnpackToBeSigned( ASN_CMS_CONTEXT *ctx, ASN_CMS_ToBeSigned **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_UnauthAttributes *ASN_CMS_NewUnauthAttributes( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeUnauthAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnauthAttributes *f); size_t ASN_CMS_SizeofUnauthAttributes ( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnauthAttributes *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackUnauthAttributes( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_UnauthAttributes *asnstruct, int *erret); size_t ASN_CMS_UnpackUnauthAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnauthAttributes **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_UnprotectedAttributes *ASN_CMS_NewUnprotectedAttributes( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeUnprotectedAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnprotectedAttributes *f); size_t ASN_CMS_SizeofUnprotectedAttributes ( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnprotectedAttributes *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackUnprotectedAttributes( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_UnprotectedAttributes *asnstruct, int *erret); size_t ASN_CMS_UnpackUnprotectedAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnprotectedAttributes **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_UnsignedAttributes *ASN_CMS_NewUnsignedAttributes( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeUnsignedAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnsignedAttributes *f); size_t ASN_CMS_SizeofUnsignedAttributes ( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnsignedAttributes *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackUnsignedAttributes( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_UnsignedAttributes *asnstruct, int *erret); size_t ASN_CMS_UnpackUnsignedAttributes( ASN_CMS_CONTEXT *ctx, ASN_CMS_UnsignedAttributes **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE *ASN_CMS_NewrevokedCertificates_SEQ_OF_SEQUENCE( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreerevokedCertificates_SEQ_OF_SEQUENCE( ASN_CMS_CONTEXT *ctx, ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE *f); size_t ASN_CMS_SizeofrevokedCertificates_SEQ_OF_SEQUENCE ( ASN_CMS_CONTEXT *ctx, ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackrevokedCertificates_SEQ_OF_SEQUENCE( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE *asnstruct, int *erret); size_t ASN_CMS_UnpackrevokedCertificates_SEQ_OF_SEQUENCE( ASN_CMS_CONTEXT *ctx, ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_Certificate *ASN_CMS_NewCertificate( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeCertificate( ASN_CMS_CONTEXT *ctx, ASN_CMS_Certificate *f); size_t ASN_CMS_SizeofCertificate ( ASN_CMS_CONTEXT *ctx, ASN_CMS_Certificate *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackCertificate( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_Certificate *asnstruct, int *erret); size_t ASN_CMS_UnpackCertificate( ASN_CMS_CONTEXT *ctx, ASN_CMS_Certificate **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_EncryptedData *ASN_CMS_NewEncryptedData( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeEncryptedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_EncryptedData *f); size_t ASN_CMS_SizeofEncryptedData ( ASN_CMS_CONTEXT *ctx, ASN_CMS_EncryptedData *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackEncryptedData( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_EncryptedData *asnstruct, int *erret); size_t ASN_CMS_UnpackEncryptedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_EncryptedData **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewName (ASN_CMS_Name *)ASN_CMS_NewRDNSequence #define ASN_CMS_FreeName ASN_CMS_FreeRDNSequence #define ASN_CMS_SizeofName ASN_CMS_SizeofRDNSequence #define ASN_CMS_PackName ASN_CMS_PackRDNSequence #define ASN_CMS_UnpackName ASN_CMS_UnpackRDNSequence ASN_CMS_RecipientEncryptedKey *ASN_CMS_NewRecipientEncryptedKey( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRecipientEncryptedKey( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientEncryptedKey *f); size_t ASN_CMS_SizeofRecipientEncryptedKey ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientEncryptedKey *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRecipientEncryptedKey( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RecipientEncryptedKey *asnstruct, int *erret); size_t ASN_CMS_UnpackRecipientEncryptedKey( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientEncryptedKey **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_SignerInfo *ASN_CMS_NewSignerInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSignerInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerInfo *f); size_t ASN_CMS_SizeofSignerInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSignerInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SignerInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackSignerInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_revokedCertificates_SEQ_OF *ASN_CMS_NewrevokedCertificates_SEQ_OF( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreerevokedCertificates_SEQ_OF( ASN_CMS_CONTEXT *ctx, ASN_CMS_revokedCertificates_SEQ_OF *f); size_t ASN_CMS_SizeofrevokedCertificates_SEQ_OF ( ASN_CMS_CONTEXT *ctx, ASN_CMS_revokedCertificates_SEQ_OF *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackrevokedCertificates_SEQ_OF( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_revokedCertificates_SEQ_OF *asnstruct, int *erret); size_t ASN_CMS_UnpackrevokedCertificates_SEQ_OF( ASN_CMS_CONTEXT *ctx, ASN_CMS_revokedCertificates_SEQ_OF **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_CertificateList *ASN_CMS_NewCertificateList( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeCertificateList( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateList *f); size_t ASN_CMS_SizeofCertificateList ( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateList *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackCertificateList( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_CertificateList *asnstruct, int *erret); size_t ASN_CMS_UnpackCertificateList( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateList **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #define ASN_CMS_NewCountersignature (ASN_CMS_Countersignature *)ASN_CMS_NewSignerInfo #define ASN_CMS_FreeCountersignature ASN_CMS_FreeSignerInfo #define ASN_CMS_SizeofCountersignature ASN_CMS_SizeofSignerInfo #define ASN_CMS_PackCountersignature ASN_CMS_PackSignerInfo #define ASN_CMS_UnpackCountersignature ASN_CMS_UnpackSignerInfo ASN_CMS_ExtendedCertificateInfo *ASN_CMS_NewExtendedCertificateInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeExtendedCertificateInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_ExtendedCertificateInfo *f); size_t ASN_CMS_SizeofExtendedCertificateInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_ExtendedCertificateInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackExtendedCertificateInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_ExtendedCertificateInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackExtendedCertificateInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_ExtendedCertificateInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RecipientEncryptedKeys *ASN_CMS_NewRecipientEncryptedKeys( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRecipientEncryptedKeys( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientEncryptedKeys *f); size_t ASN_CMS_SizeofRecipientEncryptedKeys ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientEncryptedKeys *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRecipientEncryptedKeys( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RecipientEncryptedKeys *asnstruct, int *erret); size_t ASN_CMS_UnpackRecipientEncryptedKeys( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientEncryptedKeys **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_SignerInfos *ASN_CMS_NewSignerInfos( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSignerInfos( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerInfos *f); size_t ASN_CMS_SizeofSignerInfos ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerInfos *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSignerInfos( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SignerInfos *asnstruct, int *erret); size_t ASN_CMS_UnpackSignerInfos( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignerInfos **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_CertificateRevocationLists *ASN_CMS_NewCertificateRevocationLists( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeCertificateRevocationLists( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateRevocationLists *f); size_t ASN_CMS_SizeofCertificateRevocationLists ( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateRevocationLists *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackCertificateRevocationLists( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_CertificateRevocationLists *asnstruct, int *erret); size_t ASN_CMS_UnpackCertificateRevocationLists( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateRevocationLists **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_ExtendedCertificate *ASN_CMS_NewExtendedCertificate( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeExtendedCertificate( ASN_CMS_CONTEXT *ctx, ASN_CMS_ExtendedCertificate *f); size_t ASN_CMS_SizeofExtendedCertificate ( ASN_CMS_CONTEXT *ctx, ASN_CMS_ExtendedCertificate *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackExtendedCertificate( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_ExtendedCertificate *asnstruct, int *erret); size_t ASN_CMS_UnpackExtendedCertificate( ASN_CMS_CONTEXT *ctx, ASN_CMS_ExtendedCertificate **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_KeyAgreeRecipientInfo *ASN_CMS_NewKeyAgreeRecipientInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeKeyAgreeRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyAgreeRecipientInfo *f); size_t ASN_CMS_SizeofKeyAgreeRecipientInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyAgreeRecipientInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackKeyAgreeRecipientInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_KeyAgreeRecipientInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackKeyAgreeRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_KeyAgreeRecipientInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_CertificateChoices *ASN_CMS_NewCertificateChoices( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeCertificateChoices( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateChoices *f); size_t ASN_CMS_SizeofCertificateChoices ( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateChoices *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackCertificateChoices( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_CertificateChoices *asnstruct, int *erret); size_t ASN_CMS_UnpackCertificateChoices( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateChoices **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RecipientInfo *ASN_CMS_NewRecipientInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientInfo *f); size_t ASN_CMS_SizeofRecipientInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRecipientInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RecipientInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackRecipientInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_CertificateSet *ASN_CMS_NewCertificateSet( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeCertificateSet( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateSet *f); size_t ASN_CMS_SizeofCertificateSet ( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateSet *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackCertificateSet( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_CertificateSet *asnstruct, int *erret); size_t ASN_CMS_UnpackCertificateSet( ASN_CMS_CONTEXT *ctx, ASN_CMS_CertificateSet **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_RecipientInfos *ASN_CMS_NewRecipientInfos( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeRecipientInfos( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientInfos *f); size_t ASN_CMS_SizeofRecipientInfos ( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientInfos *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackRecipientInfos( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_RecipientInfos *asnstruct, int *erret); size_t ASN_CMS_UnpackRecipientInfos( ASN_CMS_CONTEXT *ctx, ASN_CMS_RecipientInfos **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_OriginatorInfo *ASN_CMS_NewOriginatorInfo( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeOriginatorInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorInfo *f); size_t ASN_CMS_SizeofOriginatorInfo ( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorInfo *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackOriginatorInfo( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OriginatorInfo *asnstruct, int *erret); size_t ASN_CMS_UnpackOriginatorInfo( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorInfo **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_SignedData *ASN_CMS_NewSignedData( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSignedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignedData *f); size_t ASN_CMS_SizeofSignedData ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignedData *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSignedData( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SignedData *asnstruct, int *erret); size_t ASN_CMS_UnpackSignedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_SignedData **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_AuthenticatedData *ASN_CMS_NewAuthenticatedData( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeAuthenticatedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthenticatedData *f); size_t ASN_CMS_SizeofAuthenticatedData ( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthenticatedData *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackAuthenticatedData( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_AuthenticatedData *asnstruct, int *erret); size_t ASN_CMS_UnpackAuthenticatedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthenticatedData **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_EnvelopedData *ASN_CMS_NewEnvelopedData( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeEnvelopedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_EnvelopedData *f); size_t ASN_CMS_SizeofEnvelopedData ( ASN_CMS_CONTEXT *ctx, ASN_CMS_EnvelopedData *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackEnvelopedData( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_EnvelopedData *asnstruct, int *erret); size_t ASN_CMS_UnpackEnvelopedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_EnvelopedData **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #endif /* pgpASN_CMS_ASN_H_ */ ock for it */ bytesused = ASN_CMS_UnpkInPlacerevokedCertificates_SEQ_OF_SEQUENCE(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreerevokedCertificates_SEQ_OF_SEQUENCE(ctx, local); return 0; } *asnstruct = local; return bytesused; } /* ASN_CMS_UnpackrevokedCertificates_SEQ_OF_SEQUENCEInternal */ /****************************************************************** * Routines for Certificate ******************************************************************/ size_t ASN_CMS_SizeofCertificateInternal( ASN_CMS_Certificate *asnstruct, int outerSizeFlag, int expTaggedFlag) { size_t body_size = 0; if (asnstruct == NULL) return 0; body_size = ASN_CMS_SizeofToBeSignedInternal(&asnstruct->tbsCertificate, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofAlgorithmIdentifierInternal(&asnstruct->signatureAlgorithm, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofBIT_STRINGInternal(&asnstruc/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ /****************************************************************** * * Defines for OIDs * *******************************************************************/ #ifndef _pgpASN_CMS_oid_H_ #define _pgpASN_CMS_oid_H_ extern unsigned char ASN_CMS_pkcs_OID[]; #define ASN_CMS_pkcs_OID_LEN 7 extern unsigned char ASN_CMS_dhKeyAgreement_OID[]; #define ASN_CMS_dhKeyAgreement_OID_LEN 9 extern unsigned char ASN_CMS_des_ede3_cbc_OID[]; #define ASN_CMS_des_ede3_cbc_OID_LEN 8 extern unsigned char ASN_CMS_aes_OID[]; #define ASN_CMS_aes_OID_LEN 8 extern unsigned char ASN_CMS_md5_OID[]; #define ASN_CMS_md5_OID_LEN 8 extern unsigned char ASN_CMS_id_dsa_with_sha1_OID[]; #define ASN_CMS_id_dsa_with_sha1_OID_LEN 7 extern unsigned char ASN_CMS_dh_public_number_OID[]; #define ASN_CMS_dh_public_number_OID_LEN 7 extern unsigned char ASN_CMS_id_alg_ESDH_OID[]; #define ASN_CMS_id_alg_ESDH_OID_LEN 11 extern unsigned char ASN_CMS_id_alg_CMS3DESwrap_OID[]; #define ASN_CMS_id_alg_CMS3DESwrap_OID_LEN 11 extern unsigned char ASN_CMS_hMAC_SHA1_OID[]; #define ASN_CMS_hMAC_SHA1_OID_LEN 8 extern unsigned char ASN_CMS_id_RSAES_OAEP_OID[]; #define ASN_CMS_id_RSAES_OAEP_OID_LEN 9 extern unsigned char ASN_CMS_id_aes128_CBC_OID[]; #define ASN_CMS_id_aes128_CBC_OID_LEN 9 extern unsigned char ASN_CMS_id_aes192_CBC_OID[]; #define ASN_CMS_id_aes192_CBC_OID_LEN 9 extern unsigned char ASN_CMS_id_aes256_CBC_OID[]; #define ASN_CMS_id_aes256_CBC_OID_LEN 9 extern unsigned char ASN_CMS_id_alg_CMSRC2wrap_OID[]; #define ASN_CMS_id_alg_CMSRC2wrap_OID_LEN 11 extern unsigned char ASN_CMS_id_ct_contentInfo_OID[]; #define ASN_CMS_id_ct_contentInfo_OID_LEN 11 extern unsigned char ASN_CMS_id_ct_authData_OID[]; #define ASN_CMS_id_ct_authData_OID_LEN 11 extern unsigned char ASN_CMS_id_contentType_OID[]; #define ASN_CMS_id_contentType_OID_LEN 9 extern unsigned char ASN_CMS_id_ce_OID[]; #define ASN_CMS_id_ce_OID_LEN 2 extern unsigned char ASN_CMS_id_ce_subjectKeyIdentifier_OID[]; #define ASN_CMS_id_ce_subjectKeyIdentifier_OID_LEN 3 extern unsigned char ASN_CMS_id_countersignature_OID[]; #define ASN_CMS_id_countersignature_OID_LEN 9 extern unsigned char ASN_CMS_id_data_OID[]; #define ASN_CMS_id_data_OID_LEN 9 extern unsigned char ASN_CMS_id_digestedData_OID[]; #define ASN_CMS_id_digestedData_OID_LEN 9 extern unsigned char ASN_CMS_id_signedData_OID[]; #define ASN_CMS_id_signedData_OID_LEN 9 extern unsigned char ASN_CMS_id_envelopedData_OID[]; #define ASN_CMS_id_envelopedData_OID_LEN 9 extern unsigned char ASN_CMS_id_encryptedData_OID[]; #define ASN_CMS_id_encryptedData_OID_LEN 9 extern unsigned char ASN_CMS_id_messageDigest_OID[]; #define ASN_CMS_id_messageDigest_OID_LEN 9 extern unsigned char ASN_CMS_id_signingTime_OID[]; #define ASN_CMS_id_signingTime_OID_LEN 9 extern unsigned char ASN_CMS_pkcs_1_OID[]; #define ASN_CMS_pkcs_1_OID_LEN 8 extern unsigned char ASN_CMS_pkcs_3_OID[]; #define ASN_CMS_pkcs_3_OID_LEN 8 extern unsigned char ASN_CMS_pkcs_7_OID[]; #define ASN_CMS_pkcs_7_OID_LEN 8 extern unsigned char ASN_CMS_pkcs_9_OID[]; #define ASN_CMS_pkcs_9_OID_LEN 8 extern unsigned char ASN_CMS_sha_1_OID[]; #define ASN_CMS_sha_1_OID_LEN 5 extern unsigned char ASN_CMS_rsaEncryption_OID[]; #define ASN_CMS_rsaEncryption_OID_LEN 9 extern unsigned char ASN_CMS_rc2_cbc_OID[]; #define ASN_CMS_rc2_cbc_OID_LEN 8 #endif /* _pgpASN_CMS_H_*/ /******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Sun Apr 20 19:54:44 2003 * ******************************************************************/ #ifndef pgpASN_CMS_STRUCT_H_ #define pgpASN_CMS_STRUCT_H_ #include "pgpASN_CMS_util.h" /******************************************************************* * * Structure and type definitions * ******************************************************************/ typedef ASN_CMS_BIT_STRING ASN_CMS_AttributeCertificate; #define ASN_CMS_ID_AttributeCertificate ASN_CMS_ID_BIT_STRING typedef ASN_CMS_OBJECT_ID ASN_CMS_AttributeType; #define ASN_CMS_ID_AttributeType ASN_CMS_ID_OBJECT_ID typedef ASN_CMS_ANY ASN_CMS_AttributeValue; #define ASN_CMS_ID_AttributeValue ASN_CMS_ID_ANY typedef ASN_CMS_INTEGER ASN_CMS_CMSVersion; #define ASN_CMS_ID_CMSVersion ASN_CMS_ID_INTEGER /* define values for ASN_CMS_CMSVersion */ #define ASN_CMS_CMSVersion_v0 0 #define ASN_CMS_CMSVersion_v1 1 #define ASN_CMS_CMSVersion_v2 2 #define ASN_CMS_CMSVersion_v3 3 #define ASN_CMS_CMSVersion_v4 4 /* end of values for ASN_CMS_CMSVersion */ typedef ASN_CMS_INTEGER ASN_CMS_CertificateSerialNumber; #define ASN_CMS_ID_CertificateSerialNumber ASN_CMS_ID_INTEGER typedef ASN_CMS_OBJECT_ID ASN_CMS_ContentType; #define ASN_CMS_ID_ContentType ASN_CMS_ID_OBJECT_ID typedef ASN_CMS_OCTET_STRING ASN_CMS_Digest; #define ASN_CMS_ID_Digest ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_EncryptedContent; #define ASN_CMS_ID_EncryptedContent ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_EncryptedKey; #define ASN_CMS_ID_EncryptedKey ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_IV; #define ASN_CMS_ID_IV ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_MessageAuthenticationCode; #define ASN_CMS_ID_MessageAuthenticationCode ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_MessageDigest; #define ASN_CMS_ID_MessageDigest ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_ANY ASN_CMS_Name_opaque; #define ASN_CMS_ID_Name_opaque ASN_CMS_ID_ANY typedef ASN_CMS_INTEGER ASN_CMS_RC2ParameterVersion; #define ASN_CMS_ID_RC2ParameterVersion ASN_CMS_ID_INTEGER typedef ASN_CMS_BIT_STRING ASN_CMS_Signature; #define ASN_CMS_ID_Signature ASN_CMS_ID_BIT_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_SignatureValue; #define ASN_CMS_ID_SignatureValue ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_SubjectKeyIdentifier; #define ASN_CMS_ID_SubjectKeyIdentifier ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_BIT_STRING ASN_CMS_UniqueIdentifier; #define ASN_CMS_ID_UniqueIdentifier ASN_CMS_ID_BIT_STRING typedef ASN_CMS_OCTET_STRING ASN_CMS_UserKeyingMaterial; #define ASN_CMS_ID_UserKeyingMaterial ASN_CMS_ID_OCTET_STRING typedef ASN_CMS_INTEGER ASN_CMS_Version; #define ASN_CMS_ID_Version ASN_CMS_ID_INTEGER /* define values for ASN_CMS_Version */ #define ASN_CMS_Version_v1 0 #define ASN_CMS_Version_v2 1 #define ASN_CMS_Version_v3 2 /* end of values for ASN_CMS_Version */ typedef struct { ASN_CMS_OBJECT_ID algorithm; ASN_CMS_ANY *parameters; } ASN_CMS_AlgorithmIdentifier; #define ASN_CMS_ID_AlgorithmIdentifier ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_AttributeType type; ASN_CMS_AttributeValue value; } ASN_CMS_AttributeTypeAndDistinguishedValue; #define ASN_CMS_ID_AttributeTypeAndDistinguishedValue ASN_CMS_ID_SEQUENCE typedef ASN_CMS_IV ASN_CMS_CBCParameter; #define ASN_CMS_ID_CBCParameter ASN_CMS_ID_IV typedef struct { ASN_CMS_ContentType contentType; ASN_CMS_ANY content; } ASN_CMS_ContentInfo; #define ASN_CMS_ID_ContentInfo ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_ContentType eContentType; ASN_CMS_OCTET_STRING *eContent; } ASN_CMS_EncapsulatedContentInfo; #define ASN_CMS_ID_EncapsulatedContentInfo ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_OBJECT_ID extnID; ASN_CMS_BOOLEAN *critical; ASN_CMS_OCTET_STRING extnValue; } ASN_CMS_Extension; #define ASN_CMS_ID_Extension ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_Name_opaque issuer; ASN_CMS_CertificateSerialNumber serialNumber; } ASN_CMS_IssuerAndSerialNumber; #define ASN_CMS_ID_IssuerAndSerialNumber ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_OBJECT_ID keyAttrId; ASN_CMS_ANY *keyAttr; } ASN_CMS_OtherKeyAttribute; #define ASN_CMS_ID_OtherKeyAttribute ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_INTEGER rc2ParameterVersion; ASN_CMS_OCTET_STRING iv; } ASN_CMS_RC2CBCParameter; #define ASN_CMS_ID_RC2CBCParameter ASN_CMS_ID_SEQUENCE typedef ASN_CMS_RC2ParameterVersion ASN_CMS_RC2wrapParameter; #define ASN_CMS_ID_RC2wrapParameter ASN_CMS_ID_RC2ParameterVersion typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_Time; #define ASN_CMS_ID_Time ASN_CMS_ID_CHOICE /* tags for fields defined for Time */ #define ASN_CMS_utcTime_TimeFieldTag ASN_CMS_ID_UTCTime #define ASN_CMS_generalTime_TimeFieldTag ASN_CMS_ID_GeneralizedTime typedef struct { long n; /* number of elements */ ASN_CMS_AttributeValue **elt; } ASN_CMS_attrValues_SET_OF; #define ASN_CMS_ID_attrValues_SET_OF ASN_CMS_ID_SET_OF typedef struct { ASN_CMS_OBJECT_ID attrType; ASN_CMS_attrValues_SET_OF attrValues; } ASN_CMS_Attribute; #define ASN_CMS_ID_Attribute ASN_CMS_ID_SEQUENCE typedef ASN_CMS_AlgorithmIdentifier ASN_CMS_ContentEncryptionAlgorithmIdentifier; #define ASN_CMS_ID_ContentEncryptionAlgorithmIdentifier ASN_CMS_ID_AlgorithmIdentifier typedef ASN_CMS_AlgorithmIdentifier ASN_CMS_DigestAlgorithmIdentifier; #define ASN_CMS_ID_DigestAlgorithmIdentifier ASN_CMS_ID_AlgorithmIdentifier typedef struct { long n; /* number of elements */ ASN_CMS_Extension **elt; } ASN_CMS_Extensions; #define ASN_CMS_ID_Extensions ASN_CMS_ID_SEQUENCE_OF typedef struct { ASN_CMS_OCTET_STRING keyIdentifier; ASN_CMS_GeneralizedTime *date; ASN_CMS_OtherKeyAttribute *other; } ASN_CMS_KEKIdentifier; #define ASN_CMS_ID_KEKIdentifier ASN_CMS_ID_SEQUENCE typedef ASN_CMS_AlgorithmIdentifier ASN_CMS_KeyEncryptionAlgorithmIdentifier; #define ASN_CMS_ID_KeyEncryptionAlgorithmIdentifier ASN_CMS_ID_AlgorithmIdentifier typedef ASN_CMS_AlgorithmIdentifier ASN_CMS_KeyWrapAlgorithm; #define ASN_CMS_ID_KeyWrapAlgorithm ASN_CMS_ID_AlgorithmIdentifier typedef ASN_CMS_AlgorithmIdentifier ASN_CMS_MessageAuthenticationCodeAlgorithm; #define ASN_CMS_ID_MessageAuthenticationCodeAlgorithm ASN_CMS_ID_AlgorithmIdentifier typedef struct { ASN_CMS_AlgorithmIdentifier algorithm; ASN_CMS_BIT_STRING publicKey; } ASN_CMS_OriginatorPublicKey; #define ASN_CMS_ID_OriginatorPublicKey ASN_CMS_ID_SEQUENCE typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_RecipientIdentifier; #define ASN_CMS_ID_RecipientIdentifier ASN_CMS_ID_CHOICE /* tags for fields defined for RecipientIdentifier */ #define ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag ASN_CMS_ID_IssuerAndSerialNumber #define ASN_CMS_subjectKeyIdentifier_RecipientIdentifierFieldTag 0x80|0x00 typedef struct { ASN_CMS_SubjectKeyIdentifier subjectKeyIdentifier; ASN_CMS_GeneralizedTime *date; ASN_CMS_OtherKeyAttribute *other; } ASN_CMS_RecipientKeyIdentifier; #define ASN_CMS_ID_RecipientKeyIdentifier ASN_CMS_ID_SEQUENCE typedef struct { long n; /* number of elements */ ASN_CMS_AttributeTypeAndDistinguishedValue **elt; } ASN_CMS_RelativeDistinguishedName; #define ASN_CMS_ID_RelativeDistinguishedName ASN_CMS_ID_SET_OF typedef ASN_CMS_AlgorithmIdentifier ASN_CMS_SignatureAlgorithmIdentifier; #define ASN_CMS_ID_SignatureAlgorithmIdentifier ASN_CMS_ID_AlgorithmIdentifier typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_SignerIdentifier; #define ASN_CMS_ID_SignerIdentifier ASN_CMS_ID_CHOICE /* tags for fields defined for SignerIdentifier */ #define ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag ASN_CMS_ID_IssuerAndSerialNumber #define ASN_CMS_subjectKeyIdentifier_SignerIdentifierFieldTag 0x80|0x00 typedef ASN_CMS_Time ASN_CMS_SigningTime; #define ASN_CMS_ID_SigningTime ASN_CMS_ID_Time typedef struct { ASN_CMS_AlgorithmIdentifier algorithm; ASN_CMS_BIT_STRING subjectPublicKey; } ASN_CMS_SubjectPublicKeyInfo; #define ASN_CMS_ID_SubjectPublicKeyInfo ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_Time notBefore; ASN_CMS_Time notAfter; } ASN_CMS_Validity; #define ASN_CMS_ID_Validity ASN_CMS_ID_SEQUENCE typedef struct { long n; /* number of elements */ ASN_CMS_Attribute **elt; } ASN_CMS_AuthAttributes; #define ASN_CMS_ID_AuthAttributes ASN_CMS_ID_SET_OF typedef struct { long n; /* number of elements */ ASN_CMS_DigestAlgorithmIdentifier **elt; } ASN_CMS_DigestAlgorithmIdentifiers; #define ASN_CMS_ID_DigestAlgorithmIdentifiers ASN_CMS_ID_SET_OF typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_DigestAlgorithmIdentifier digestAlgorithm; ASN_CMS_EncapsulatedContentInfo encapContentInfo; ASN_CMS_Digest digest; } ASN_CMS_DigestedData; #define ASN_CMS_ID_DigestedData ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_ContentType contentType; ASN_CMS_ContentEncryptionAlgorithmIdentifier contentEncryptionAlgorithm; ASN_CMS_EncryptedContent encryptedContent; } ASN_CMS_EncryptedContentInfo; #define ASN_CMS_ID_EncryptedContentInfo ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_KEKIdentifier kekid; ASN_CMS_KeyEncryptionAlgorithmIdentifier keyEncryptionAlgorithm; ASN_CMS_EncryptedKey encryptedKey; } ASN_CMS_KEKRecipientInfo; #define ASN_CMS_ID_KEKRecipientInfo ASN_CMS_ID_SEQUENCE typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_KeyAgreeRecipientIdentifier; #define ASN_CMS_ID_KeyAgreeRecipientIdentifier ASN_CMS_ID_CHOICE /* tags for fields defined for KeyAgreeRecipientIdentifier */ #define ASN_CMS_issuerAndSerialNumber_KeyAgreeRecipientIdentifierFieldTag ASN_CMS_ID_IssuerAndSerialNumber #define ASN_CMS_rKeyId_KeyAgreeRecipientIdentifierFieldTag 0x80|0x00 typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_RecipientIdentifier rid; ASN_CMS_KeyEncryptionAlgorithmIdentifier keyEncryptionAlgorithm; ASN_CMS_EncryptedKey encryptedKey; } ASN_CMS_KeyTransRecipientInfo; #define ASN_CMS_ID_KeyTransRecipientInfo ASN_CMS_ID_SEQUENCE typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_OriginatorIdentifierOrKey; #define ASN_CMS_ID_OriginatorIdentifierOrKey ASN_CMS_ID_CHOICE /* tags for fields defined for OriginatorIdentifierOrKey */ #define ASN_CMS_issuerAndSerialNumber_OriginatorIdentifierOrKeyFieldTag ASN_CMS_ID_IssuerAndSerialNumber #define ASN_CMS_subjectKeyIdentifier_OriginatorIdentifierOrKeyFieldTag 0x80|0x00 #define ASN_CMS_originatorKey_OriginatorIdentifierOrKeyFieldTag 0x80|0x01 typedef struct { long n; /* number of elements */ ASN_CMS_RelativeDistinguishedName **elt; } ASN_CMS_RDNSequence; #define ASN_CMS_ID_RDNSequence ASN_CMS_ID_SEQUENCE_OF typedef struct { long n; /* number of elements */ ASN_CMS_Attribute **elt; } ASN_CMS_SignedAttributes; #define ASN_CMS_ID_SignedAttributes ASN_CMS_ID_SET_OF typedef struct { ASN_CMS_Version *version; ASN_CMS_CertificateSerialNumber serialNumber; ASN_CMS_AlgorithmIdentifier signature; ASN_CMS_Name_opaque issuer; ASN_CMS_Validity validity; ASN_CMS_Name_opaque subject; ASN_CMS_SubjectPublicKeyInfo subjectPublicKeyInfo; ASN_CMS_UniqueIdentifier *issuerUniqueIdentifier; ASN_CMS_UniqueIdentifier *subjectUniqueIdentifier; ASN_CMS_Extensions *extensions; } ASN_CMS_ToBeSigned; #define ASN_CMS_ID_ToBeSigned ASN_CMS_ID_SEQUENCE typedef struct { long n; /* number of elements */ ASN_CMS_Attribute **elt; } ASN_CMS_UnauthAttributes; #define ASN_CMS_ID_UnauthAttributes ASN_CMS_ID_SET_OF typedef struct { long n; /* number of elements */ ASN_CMS_Attribute **elt; } ASN_CMS_UnprotectedAttributes; #define ASN_CMS_ID_UnprotectedAttributes ASN_CMS_ID_SET_OF typedef struct { long n; /* number of elements */ ASN_CMS_Attribute **elt; } ASN_CMS_UnsignedAttributes; #define ASN_CMS_ID_UnsignedAttributes ASN_CMS_ID_SET_OF typedef struct { ASN_CMS_CertificateSerialNumber userCertificate; ASN_CMS_Time revocationDate; ASN_CMS_Extensions *crlEntryExtensions; } ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE; #define ASN_CMS_ID_revokedCertificates_SEQ_OF_SEQUENCE ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_ToBeSigned tbsCertificate; ASN_CMS_AlgorithmIdentifier signatureAlgorithm; ASN_CMS_BIT_STRING signature; } ASN_CMS_Certificate; #define ASN_CMS_ID_Certificate ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_EncryptedContentInfo encryptedContentInfo; ASN_CMS_UnprotectedAttributes *unprotectedAttrs; } ASN_CMS_EncryptedData; #define ASN_CMS_ID_EncryptedData ASN_CMS_ID_SEQUENCE typedef ASN_CMS_RDNSequence ASN_CMS_Name; #define ASN_CMS_ID_Name ASN_CMS_ID_RDNSequence typedef struct { ASN_CMS_KeyAgreeRecipientIdentifier rid; ASN_CMS_EncryptedKey encryptedKey; } ASN_CMS_RecipientEncryptedKey; #define ASN_CMS_ID_RecipientEncryptedKey ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_SignerIdentifier sid; ASN_CMS_DigestAlgorithmIdentifier digestAlgorithm; ASN_CMS_SignedAttributes *signedAttrs; ASN_CMS_SignatureAlgorithmIdentifier signatureAlgorithm; ASN_CMS_SignatureValue signature; ASN_CMS_UnsignedAttributes *unsignedAttrs; } ASN_CMS_SignerInfo; #define ASN_CMS_ID_SignerInfo ASN_CMS_ID_SEQUENCE typedef struct { long n; /* number of elements */ ASN_CMS_revokedCertificates_SEQ_OF_SEQUENCE **elt; } ASN_CMS_revokedCertificates_SEQ_OF; #define ASN_CMS_ID_revokedCertificates_SEQ_OF ASN_CMS_ID_SEQUENCE_OF typedef struct { ASN_CMS_Version *version; ASN_CMS_AlgorithmIdentifier signature; ASN_CMS_Name_opaque issuer; ASN_CMS_Time thisUpdate; ASN_CMS_Time *nextUpdate; ASN_CMS_revokedCertificates_SEQ_OF *revokedCertificates; ASN_CMS_Extensions *crlExtensions; } ASN_CMS_CertificateList; #define ASN_CMS_ID_CertificateList ASN_CMS_ID_SEQUENCE typedef ASN_CMS_SignerInfo ASN_CMS_Countersignature; #define ASN_CMS_ID_Countersignature ASN_CMS_ID_SignerInfo typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_Certificate certificate; ASN_CMS_UnauthAttributes attributes; } ASN_CMS_ExtendedCertificateInfo; #define ASN_CMS_ID_ExtendedCertificateInfo ASN_CMS_ID_SEQUENCE typedef struct { long n; /* number of elements */ ASN_CMS_RecipientEncryptedKey **elt; } ASN_CMS_RecipientEncryptedKeys; #define ASN_CMS_ID_RecipientEncryptedKeys ASN_CMS_ID_SEQUENCE_OF typedef struct { long n; /* number of elements */ ASN_CMS_SignerInfo **elt; } ASN_CMS_SignerInfos; #define ASN_CMS_ID_SignerInfos ASN_CMS_ID_SET_OF typedef struct { long n; /* number of elements */ ASN_CMS_CertificateList **elt; } ASN_CMS_CertificateRevocationLists; #define ASN_CMS_ID_CertificateRevocationLists ASN_CMS_ID_SET_OF typedef struct { ASN_CMS_ExtendedCertificateInfo extendedCertificateInfo; ASN_CMS_SignatureAlgorithmIdentifier signatureAlgorithm; ASN_CMS_Signature signature; } ASN_CMS_ExtendedCertificate; #define ASN_CMS_ID_ExtendedCertificate ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_OriginatorIdentifierOrKey originator; ASN_CMS_UserKeyingMaterial *ukm; ASN_CMS_KeyEncryptionAlgorithmIdentifier keyEncryptionAlgorithm; ASN_CMS_RecipientEncryptedKeys recipientEncryptedKeys; } ASN_CMS_KeyAgreeRecipientInfo; #define ASN_CMS_ID_KeyAgreeRecipientInfo ASN_CMS_ID_SEQUENCE typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_CertificateChoices; #define ASN_CMS_ID_CertificateChoices ASN_CMS_ID_CHOICE /* tags for fields defined for CertificateChoices */ #define ASN_CMS_certificate_CertificateChoicesFieldTag ASN_CMS_ID_Certificate #define ASN_CMS_extendedCertificate_CertificateChoicesFieldTag 0x80|0x00 #define ASN_CMS_attrCert_CertificateChoicesFieldTag 0x80|0x01 typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_RecipientInfo; #define ASN_CMS_ID_RecipientInfo ASN_CMS_ID_CHOICE /* tags for fields defined for RecipientInfo */ #define ASN_CMS_ktri_RecipientInfoFieldTag ASN_CMS_ID_KeyTransRecipientInfo #define ASN_CMS_kari_RecipientInfoFieldTag 0x80|0x01 #define ASN_CMS_kekri_RecipientInfoFieldTag 0x80|0x02 typedef struct { long n; /* number of elements */ ASN_CMS_CertificateChoices **elt; } ASN_CMS_CertificateSet; #define ASN_CMS_ID_CertificateSet ASN_CMS_ID_SET_OF typedef struct { long n; /* number of elements */ ASN_CMS_RecipientInfo **elt; } ASN_CMS_RecipientInfos; #define ASN_CMS_ID_RecipientInfos ASN_CMS_ID_SET_OF typedef struct { ASN_CMS_CertificateSet *certs; ASN_CMS_CertificateRevocationLists *crls; } ASN_CMS_OriginatorInfo; #define ASN_CMS_ID_OriginatorInfo ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_DigestAlgorithmIdentifiers digestAlgorithms; ASN_CMS_EncapsulatedContentInfo encapContentInfo; ASN_CMS_CertificateSet *certificates; ASN_CMS_CertificateRevocationLists *crls; ASN_CMS_SignerInfos signerInfos; } ASN_CMS_SignedData; #define ASN_CMS_ID_SignedData ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_OriginatorInfo *originatorInfo; ASN_CMS_RecipientInfos recipientInfos; ASN_CMS_MessageAuthenticationCodeAlgorithm macAlgorithm; ASN_CMS_DigestAlgorithmIdentifier *digestAlgorithm; ASN_CMS_EncapsulatedContentInfo encapContentInfo; ASN_CMS_AuthAttributes *authenticatedAttributes; ASN_CMS_MessageAuthenticationCode mac; ASN_CMS_UnauthAttributes *unauthenticatedAttributes; } ASN_CMS_AuthenticatedData; #define ASN_CMS_ID_AuthenticatedData ASN_CMS_ID_SEQUENCE typedef struct { ASN_CMS_CMSVersion version; ASN_CMS_OriginatorInfo *originatorInfo; ASN_CMS_RecipientInfos recipientInfos; ASN_CMS_EncryptedContentInfo encryptedContentInfo; ASN_CMS_UnprotectedAttributes *unprotectedAttrs; } ASN_CMS_EnvelopedData; #define ASN_CMS_ID_EnvelopedData ASN_CMS_ID_SEQUENCE #endif /* pgpASN_CMS_STRUCT_H_ */ (ctx, f->signedAttrs); f->signedAttrs = NULL; ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier(ctx, &(f->signatureAlgorithm)); ASN_CMS_DropInPlaceSignatureValue(ctx, &(f->signature)); ASN_CMS_FreeUnsignedAttributes(ctx, f->unsignedAttrs); f->unsignedAttrs = NULL; } /* ASN_CMS_DropInPlaceSignerInfo */ size_t ASN_CMS_PackSignerInfoInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SignerInfo *asnstruct, unsigned char tag, int *erret) { size_t bytesused; size_t tagsize; size_t datasize; if (erret == NULL) return 0; /* can't report errors */ if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) return 0; /* lth of the block body */ datasize = ASN_CMS_SizeofSignerInfo(ctx, asnstruct, ASN_CMS_FALSE); tagsize = 1 + ASN_CMS_LengthSize(datasize); if (datasize+tagsize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackBufferTooShort); return 0; } /* this is a SEQUENCE */ bytesused = ASN_CMS_PutTag(buf, (unsigned char)(tag|0x20), datasize); if (bytesused != tagsize) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return bytesused; } datasize += tagsize; do { /* field version of SignerInfo */ bytesused += ASN_CMS_PackCMSVersionInternal(ctx, buf+bytesused, buflen-bytesused, &(asnstruct->version), ASN_CMS_ID_CMSVersion, erret); if (bytesused > datasize || *erret != 0) break; /******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Sun Apr 20 19:54:44 2003 * ******************************************************************/ #ifndef pgpASN_CMS_UTIL_H_ #define pgpASN_CMS_UTIL_H_ #include #include #ifndef ASN_CMS_TRUE #define ASN_CMS_FALSE (0) #define ASN_CMS_TRUE (1) #endif #ifndef NULL #define NULL ((void *) 0) #endif /***** * * Primitive type definitions * *****/ /* BOOLEAN */ typedef struct { size_t len; /* # of bytes in value */ int val; /* the boolean */ } ASN_CMS_BooleanBlock; /* NULL */ typedef struct { size_t len; /* unused */ } ASN_CMS_NullBlock; /* Variable Length Entity */ typedef struct { size_t len; /* # of bytes in value */ unsigned char *val; /* pointer to the bytes of value */ } ASN_CMS_VariableBlock; /* Bit String Entity */ typedef struct { size_t len; /* # of bytes in value */ unsigned char *val; /* pointer to the bytes of value */ int nuub; /* number of unused bits in LSByte */ } ASN_CMS_BitstringBlock; typedef ASN_CMS_NullBlock ASN_CMS_NULL; typedef ASN_CMS_BooleanBlock ASN_CMS_BOOLEAN ; typedef ASN_CMS_VariableBlock ASN_CMS_OBJECT_ID ; typedef ASN_CMS_VariableBlock ASN_CMS_GeneralizedTime ; typedef ASN_CMS_VariableBlock ASN_CMS_IA5String ; typedef ASN_CMS_VariableBlock ASN_CMS_INTEGER ; typedef ASN_CMS_BitstringBlock ASN_CMS_BIT_STRING ; typedef ASN_CMS_VariableBlock ASN_CMS_OCTET_STRING ; typedef ASN_CMS_VariableBlock ASN_CMS_T61String ; typedef ASN_CMS_VariableBlock ASN_CMS_ANY ; typedef ASN_CMS_VariableBlock ASN_CMS_UTCTime ; typedef ASN_CMS_VariableBlock ASN_CMS_NumericString ; typedef ASN_CMS_VariableBlock ASN_CMS_PrintableString ; typedef ASN_CMS_VariableBlock ASN_CMS_VisibleString ; /* * #define ID values for defines for asn types. */ #define ASN_CMS_ID_reserved 0x00 #define ASN_CMS_ID_BOOLEAN 0x01 #define ASN_CMS_ID_INTEGER 0x02 #define ASN_CMS_ID_BIT_STRING 0x03 #define ASN_CMS_ID_OCTET_STRING 0x04 #define ASN_CMS_ID_NULL 0x05 #define ASN_CMS_ID_OBJECT_IDENTIFIER 0x06 #define ASN_CMS_ID_OBJECT_ID 0x06 #define ASN_CMS_ID_ObjectDescriptor 0x07 #define ASN_CMS_ID_EXTERNAL 0x08 #define ASN_CMS_ID_REAL 0x09 #define ASN_CMS_ID_SEQUENCE 0x10 #define ASN_CMS_ID_SEQUENCE_OF 0x10 #define ASN_CMS_ID_SET 0x11 #define ASN_CMS_ID_SET_OF 0x011 #define ASN_CMS_ID_NumericString 0x12 #define ASN_CMS_ID_PrintableString 0x13 #define ASN_CMS_ID_T61String 0x14 #define ASN_CMS_ID_TeletexString 0x14 #define ASN_CMS_ID_VideotexString 0x15 #define ASN_CMS_ID_IA5String 0x16 #define ASN_CMS_ID_UTCTime 0x17 #define ASN_CMS_ID_GeneralizedTime 0x18 #define ASN_CMS_ID_GraphicString 0x19 #define ASN_CMS_ID_VisibleString 0x1a #define ASN_CMS_ID_ISO646String 0x1a #define ASN_CMS_ID_GeneralString 0x1b #define ASN_CMS_ID_IMPORTED 0xFA #define ASN_CMS_ID_UNIVERSAL 0xFB #define ASN_CMS_ID_CHOICE 0xFC #define ASN_CMS_ID_SYNONYM 0xFD #define ASN_CMS_ID_ANY 0xFE /********************************************************************* * Error return codes from pack and unpack (uip). **********************************************************************/ #define ASN_CMS_ErrPackUnderrun (-1) #define ASN_CMS_ErrPackOverrun (-2) #define ASN_CMS_ErrPackSEQOFArrayTooLong (-3) /* lth > MAX of that type */ #define ASN_CMS_ErrPackNoBlock (-5) /* ASN block ptr is NULL */ #define ASN_CMS_ErrUnpackNoStructure (-6) /* block pointer is NULL */ #define ASN_CMS_ErrUnpackNoBlockPtr (-7) /* ASN block pointer pointer is NULL */ #define ASN_CMS_ErrUnpackNoBlock (-8) /* ASN block pointer is NULL */ #define ASN_CMS_ErrUnpackOverrun (-9) #define ASN_CMS_ErrUnpackUnderrun (-10) #define ASN_CMS_ErrUnpackBooleanLth (-11) /* a boolean block with lth != 1 */ #define ASN_CMS_ErrUnpackTaggedLth (-12) /* a context tag lth failed to match the length of the contents */ #define ASN_CMS_ErrUnpackReqMissing (-13) /* a required substructure is missing */ #define ASN_CMS_ErrUnpackNullLth (-14) /* a NULL block with lth != 0 */ #define ASN_CMS_ErrPackSETOFArrayTooLong (-15) /* lth > MAX of that type */ #define ASN_CMS_ErrPackSETOFUnsortable (-16) /* SET OF with identical elements */ #define ASN_CMS_ErrOutOfMemory (-17) /* Out of memory */ #define ASN_CMS_ErrPackBufferTooShort (-18) /* provided buffer space too short */ #define ASN_CMS_ErrUnpackInvalidEncoding (-19) #define ASN_CMS_ErrBadContext (-20) #define ASN_CMS_ErrUnpackSetBadType (-21) #define ASN_CMS_ErrUnpackDuplicateField (-22) /* * Error code for choice when it has a bad type */ #define ASN_CMS_ErrChoiceBadType (-50) /* * Error codes for bad characters in strings */ #define ASN_CMS_ErrBadNumericString (-60) #define ASN_CMS_ErrBadPrintableString (-61) #define ASN_CMS_ErrNotFoundInDict (-70) /********************************************************************* * ASN_CMS_ERR macro * * This can be re-defined as exit(x) for debugging **********************************************************************/ #define ASN_CMS_ERR( x ) { *erret = x; ASN_CMS_ErrorHalt(x); } void ASN_CMS_ErrorHalt ( int x ); /********************************************************************* * Memory Mgmt Callbacks **********************************************************************/ typedef struct ASN_CMS_MemoryMgr ASN_CMS_MemoryMgr; extern ASN_CMS_MemoryMgr ASN_CMS_defaultMemoryMgrStruct; typedef void *(*ASN_CMS_MemoryMgrAllocationProc)( ASN_CMS_MemoryMgr *mgr, size_t requestSize); typedef int (*ASN_CMS_MemoryMgrReallocationProc)( ASN_CMS_MemoryMgr *mgr, void **allocation, size_t newAllocationSize); typedef int (*ASN_CMS_MemoryMgrDeallocationProc)( ASN_CMS_MemoryMgr *mgr, void *allocation); /* memory management structure */ struct ASN_CMS_MemoryMgr { void *customValue; ASN_CMS_MemoryMgrAllocationProc allocProc; ASN_CMS_MemoryMgrReallocationProc reallocProc; ASN_CMS_MemoryMgrDeallocationProc deallocProc; }; #define ASN_CMS_Alloc(mgr, size) (*(mgr)->allocProc)(mgr, size) #define ASN_CMS_Realloc(mgr, ptr, newsize) \ (*(mgr)->reallocProc)(mgr, ptr, newsize) #define ASN_CMS_Free(mgr, ptr) (*(mgr)->deallocProc)(mgr, ptr) struct ASN_CMS_CONTEXT { void *customValue; ASN_CMS_MemoryMgr *memMgr; }; typedef struct ASN_CMS_CONTEXT ASN_CMS_CONTEXT; /********************************************************************* * Utility routine definitions **********************************************************************/ size_t ASN_CMS_LengthSize(size_t x); size_t ASN_CMS_Tagged(size_t inner, int seqlike ); size_t ASN_CMS_PutByte(unsigned char *buf, unsigned char byte ); size_t ASN_CMS_PutLength(unsigned char *buf, size_t length ); size_t ASN_CMS_GetByte(const unsigned char *buf, unsigned char *byte); size_t ASN_CMS_GetLength(const unsigned char *buf, size_t *length); size_t ASN_CMS_PutTag(unsigned char *buf, unsigned char tagbyte, size_t length ); size_t ASN_CMS_TakeTag(const unsigned char *buf, unsigned char tag, size_t *length); int ASN_CMS_CompareElems(const void *a, const void *b); long ASN_CMS_GetIntVal (ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *b, int *error); int ASN_CMS_PutIntVal (ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *b, long v); int ASN_CMS_PutUIntBytes(ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *b, const unsigned char *v, size_t lth); int ASN_CMS_PutOctVal(ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *b, const unsigned char *v, size_t lth); char *ASN_CMS_GetStrVal(ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *b); int ASN_CMS_PutStrVal(ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *b, const char *v); int ASN_CMS_PutBitString (ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING *b, const unsigned char *str, size_t len, int nuub); int ASN_CMS_GetBoolVal(ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *b); int ASN_CMS_PutBoolVal(ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *b, int val); int ASN_CMS_AddOfElement(ASN_CMS_CONTEXT *ctx, void *element, void *seqofsetof); /********************************************************************* * For tracing ASN.1 processing via compiler-generated routines. **********************************************************************/ #ifdef ASN_CMS_TRACE extern int ASN_CMS_TRACE_LEVEL; int ASN_CMS_TRACE_trval(const unsigned char *enc, int len, int lev); #define ASN_CMS_TRACE_INCR_LEVEL \ ASN_CMS_TRACE_LEVEL++ #define ASN_CMS_TRACE_DECR_LEVEL \ ASN_CMS_TRACE_LEVEL-- #define ASN_CMS_TRACE_PRINT_LENGTH(n) \ fprintf(stderr, "<%d>", n) #define ASN_CMS_TRACE_PRINT_TAG(tag, rtag) \ { int j; fprintf(stderr, "\n"); \ for ( j=0 ; jmemMgr, sizeof(ASN_CMS_BOOLEAN) ); if (f != NULL) memset(f, 0, sizeof(ASN_CMS_BOOLEAN) ); return ((ASN_CMS_BOOLEAN *) f); } /* NewBOOLEAN */ void ASN_CMS_DropInPlaceBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *f) { (void)ctx; (void)f; return ; } /* ASN_CMS_DropInPlaceBOOLEAN */ void ASN_CMS_FreeBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *g ) { if (ctx == NULL) return; if (g != NULL) ASN_CMS_Free(ctx->memMgr, g); } /* ASN_CMS_FreeBOOLEAN */ size_t ASN_CMS_SizeofBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *boolblock, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofBOOLEANInternal(boolblock, outerSizeFlag, ASN_CMS_FALSE); } size_t ASN_CMS_SizeofBOOLEANInternal( ASN_CMS_BOOLEAN *boolblock, int outerSizeFlag, int expTaggedSize) { size_t length = 1; if (boolblock == NULL) return 0; if (outerSizeFlag == ASN_CMS_TRUE) length = 3; if (expTaggedSize == ASN_CMS_TRUE) length = ASN_CMS_Tagged(length, 0); return length; } /* ASN_CMS_SizeofBOOLEANInternal */ size_t ASN_CMS_PackBOOLEAN( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_BOOLEAN *boolblock, int *erret ) { return(ASN_CMS_PackBOOLEANInternal(ctx, buf, buflen, boolblock, ASN_CMS_ID_BOOLEAN, erret)); } /* ASN_CMS_PackBOOLEAN */ size_t ASN_CMS_PackBOOLEANInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_BOOLEAN *boolblock, unsigned char tag, int *erret ) { unsigned char value = 0x00; size_t bytesused; (void)ctx; /* for future use */ if (boolblock == NULL) return 0; if (boolblock->val != 0) value = 0xff; bytesused = ASN_CMS_PutByte(buf, tag); /* this is a ASN_CMS_BOOLEAN */ bytesused += ASN_CMS_PutByte(buf+bytesused, 1); /* length = 1 byte */ bytesused += ASN_CMS_PutByte(buf+bytesused, value); /* the value */ if (bytesused > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); /* note this error */ return 0; } return bytesused; } /* ASN_CMS_PackBOOLEANInternal */ size_t ASN_CMS_UnpkInPlaceBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *boolstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { size_t bytesused; size_t datasize; (void)ctx; ASN_CMS_TRACE_PRINT_FM(tag, 0x01, "BOOLEAN"); if/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Sun Apr 20 19:54:44 2003 * ******************************************************************/ /********************************************************************** * pgpASN_CMS_util.c * * Utility routines for ASN.1 coding ************************************************************************/ #include #include #include #include #include "pgpASN_CMS_util.h" #ifdef ASN_CMS_TRACE int ASN_CMS_TRACE_LEVEL = 0; #endif /*********************************************************************** * ASN_CMS_ErrorHalt * * a dummy routine, called if error, on which one can halt/ *************************************************************************/ void ASN_CMS_ErrorHalt(int x) { (void)x; /* not usted */ return; } /* err_halt */ /********************************************************************** * Default mem. mgmt callbacks * * These are defaults that the user can use if desired, or use them * as models for your own set of memory mgmt. callbacks. ***********************************************************************/ /* default memory allocator */ static void * ASN_CMS_DefaultMemoryAllocationProc( ASN_CMS_MemoryMgr *mgr, size_t requestSize) { (void)mgr; return ( malloc(requestSize) ); } /* ASN_CMS_DefaultMemoryAllocationProc */ /* default memory reallocator */ static int ASN_CMS_DefaultMemoryReallocationProc( ASN_CMS_MemoryMgr *mgr, void **allocation, size_t newAllocationSize) { int err; void *newPtr = NULL; void *oldPtr = *allocation; (void)mgr; newPtr = realloc(oldPtr, newAllocationSize); if (newPtr == NULL) { err = ASN_CMS_ErrOutOfMemory; } else { err = 0; *allocation = newPtr; } return err; } /* ASN_CMS_MemoryMgrReallocationProc */ /* default memory deallocation routine */ static int ASN_CMS_DefaultMemoryDeallocationProc( ASN_CMS_MemoryMgr *mgr, void *allocation) { (void)mgr; free(allocation); return 0; } /* ASN_CMS_MemoryMgrDeallocationProc */ /* the default ASN_CMS_MemoryMgr structure for the user */ ASN_CMS_MemoryMgr ASN_CMS_defaultMemoryMgrStruct = { NULL, ASN_CMS_DefaultMemoryAllocationProc, ASN_CMS_DefaultMemoryReallocationProc, ASN_CMS_DefaultMemoryDeallocationProc }; /*************************************************************************** * ASN_CMS_AddOfElement * A routine to add an element to a SEQUENCE OF or SET OF structure. * The routine will only allocate space for the pointer being added, * the user must allocate and fill in the element's data. ****************************************************************************/ struct seqsetofstruct { long n; void **elems; }; int ASN_CMS_AddOfElement( ASN_CMS_CONTEXT *ctx, void *element, void *seqofsetof) { struct seqsetofstruct *local; int err; if ( ctx == NULL ) return ASN_CMS_ErrBadContext; if ( seqofsetof == NULL ) return (-1); local = (struct seqsetofstruct *)seqofsetof; if (local->n == 0) { local->elems = (void **)ASN_CMS_Alloc(ctx->memMgr, sizeof(void *)); if (local->elems == NULL) return (-1); local->elems[0] = element; local->n = 1; } else { err = ASN_CMS_Realloc(ctx->memMgr, (void **)&(local->elems), ((local->n+1)*sizeof(void *)) ); if (local->elems == NULL || err != 0) return (-1); local->elems[local->n] = element; local->n++; } return 0; } /* ASN_CMS_AddOfElement */ /*************************************************************************** * ASN_CMS_CompareElems * A routine to provide to the qsort routine for comparing two * PrimVariableBlock blocks. This is used by the pack * routines for SET OF structures. This assumes the compare should * use the length of the longer element provided and for SET OF, then* provided elements should have 0's at the ends of shorter elements. ****************************************************************************/ int ASN_CMS_CompareElems(const void *a, const void *b) { int length; ASN_CMS_VariableBlock *locala = (ASN_CMS_VariableBlock *)a; ASN_CMS_VariableBlock *localb = (ASN_CMS_VariableBlock *)b; if (locala->len > localb->len) length = locala->len; else length = localb->len; return(memcmp(locala->val, localb->val, length)); } /* ASN_CMS_CompareElems */ /************************************************************************ * ASN_CMS_LengthSize -- for scanning the length of a basic integer * for the ASN.1 length field after the tag. *************************************************************************/ size_t ASN_CMS_LengthSize(size_t x) { if ( x <= 127 ) return 1; else if ( x < 0x100 ) return 2; else if ( x < 0x10000 ) return 3; else if ( x < 0x1000000 ) return 4; else return 5; } /* LengthSize */ /************************************************************************ * Tagged -- compute and return the size of a tagged ASN.1 object * whose size without the tag would be (inner). *************************************************************************/ size_t ASN_CMS_Tagged(size_t inner, int seqlike ) { if ( inner == 0 && ! seqlike ) return (0); return ( 1 + inner + ASN_CMS_LengthSize(inner) ); } /* Tagged */ /************************************************************************ * ASN_CMS_PutByte -- put an ASN.1 type byte to op *************************************************************************/ size_t ASN_CMS_PutByte( unsigned char *buf, unsigned char byte ) { *buf = byte; return 1; } /* ASN_CMS_PutByte */ /************************************************************************ * ASN_CMS_PutLength -- put a length field to opp ************************************************************************/ size_t ASN_CMS_PutLength( unsigned char *buf, size_t length ) { unsigned char *bufptr = buf; size_t size = ASN_CMS_LengthSize(length) - 1; unsigned char bytes[4] ; unsigned char *bp = &(bytes[3]) ; /* pointer for unpacking */ switch (size) { case 4: *(bp--) = (unsigned char)length & 0xff ; length >>= 8 ; case 3: *(bp--) = (unsigned char)length & 0xff ; length >>= 8 ; case 2: *(bp--) = (unsigned char)length & 0xff ; length >>= 8 ; case 1: *(bp--) = (unsigned char)length & 0xff ; length >>= 8 ; default: /* fall through */ ; } /* turn x into bytes */ /* only need one byte for length */ if (size == 0) *(bufptr++) = (unsigned char)(length & 0x7f); /* otherwise first byte is number of bytes needed for size */ else *(bufptr++) = (unsigned char)(0x80 | size) ; size = 4 - size; /* as an index into bytes[] */ while (size < 4) *(bufptr++) = bytes[size++] ; /* return the number of bytes used */ return (size_t)(bufptr-buf); } /* ASN_CMS_PutLength */ /************************************************************************ * ASN_CMS_GetByte -- get an ASN.1 type byte to op *************************************************************************/ size_t ASN_CMS_GetByte(const unsigned char *buf, unsigned char *byte) { *byte = *buf; return 1; } /* ASN_CMS_GetByte */ /************************************************************************ * ASN_CMS_GetLength -- fetch a length field from opp and return it * If this is indefinite length, then return -1 for the length. *************************************************************************/ size_t ASN_CMS_GetLength(const unsigned char *buf, size_t *length) { size_t bytesused; unsigned long x ; unsigned char c ; c = *buf; /* get the control byte (or length) */ bytesused = 1; if (c == 0x80) { /* this is indefinite length */ *length = -1; return bytesused; } if ((c & 0x80) == 0) { /* have the length already */ *length = (size_t)c; /* note the byte we used */ ASN_CMS_TRACE_PRINT_LENGTH(c); return bytesused; /* return the length */ } /* if */ c &= 0x7f ; /* get the number of bytes of length */ x = 0 ; /* clear x */ while ((c--) > 0) { x <<= 8 ; /* shift up the word */ x |= (unsigned long)*(buf + bytesused); /* gather the next byte */ bytesused++; } /* pack as integer */ ASN_CMS_TRACE_PRINT_LENGTH((int)x); *length = (size_t)x; /* note the bytes used */ return bytesused; /* return the length */ } /* ASN_CMS_GetLength */ /************************************************************************ * ASN_CMS_PutTag * * Put a tag field (tag + length) to the output block *************************************************************************/ size_t ASN_CMS_PutTag( unsigned char *buf, unsigned char tagbyte, size_t length ) { size_t bytesused; bytesused = ASN_CMS_PutByte(buf, tagbyte); bytesused += ASN_CMS_PutLength(buf+bytesused, length); return bytesused; } /* ASN_CMS_PutTag */ /************************************************************************ * ASN_CMS_TakeTag * * Get a tag field from the input block and return its length *************************************************************************/ size_t ASN_CMS_TakeTag(const unsigned char *buf, unsigned char tag, size_t *length) { size_t bytesused = 0; *length = 0; if (buf == NULL) return 0; if (*buf != tag) return 0; /* have that tag */ bytesused = 1; /* consume the tag byte */ bytesused += ASN_CMS_GetLength(buf+bytesused, length); return bytesused; } /* ASN_CMS_TakeTag */ /************************************************************************ * Basic variable block routines *************************************************************************/ void *ASN_CMS_NewVariableBlock(ASN_CMS_CONTEXT *ctx) { ASN_CMS_VariableBlock *block = NULL ; if (ctx == NULL) return NULL; block = (ASN_CMS_VariableBlock *) ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_VariableBlock) ); if (block != NULL) memset(block, 0, sizeof(ASN_CMS_VariableBlock)) ; return (void *)block; } /* ASN_CMS_NewVariableBlock */ size_t ASN_CMS_SizeofVariableBlock(ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *block, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofVariableBlockInternal(block, outerSizeFlag, ASN_CMS_FALSE); } /***** * * internal ASN_CMS_SizeofVariableBlock * * This internal routine handles the case where there is an * explicitly tagged field in a constructed ASN block. The final length * returned will be increased by the explicit tag bits (using the tagged() * routine) only if the previous calculations don't result in zero. * * It is assumed that outerSizeFlag will not be FALSE when expTaggedSize * is TRUE. This is handled by the generated code. It does not call * _sizeof with this case. Also, the wrapper routine above calls this * routine with expTaggedSize as FALSE. So, this routine doesn't do any * error checking in that respect. * *****/ size_t ASN_CMS_SizeofVariableBlockInternal( ASN_CMS_VariableBlock *block, int outerSizeFlag, int expTaggedSize) { size_t length; if (block == NULL) return (0); length = (size_t)block->len; if (outerSizeFlag == ASN_CMS_TRUE) length = length + 1 + ASN_CMS_LengthSize(block->len); if (expTaggedSize == ASN_CMS_TRUE) length = ASN_CMS_Tagged(length, 0); return length; } /* ASN_CMS_SizeofVariableBlockInternal */ void ASN_CMS_DropInPlaceVariableBlock(ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *f ) { if (ctx == NULL) return; if (f != NULL && f->val != NULL) { ASN_CMS_Free(ctx->memMgr, f->val); f->val = NULL; } } /* ASN_CMS_DropInPlaceVariableBlock */ void ASN_CMS_FreeVariableBlock(ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *f) { if (ctx == NULL) return; ASN_CMS_DropInPlaceVariableBlock(ctx, f); if (f != NULL) ASN_CMS_Free(ctx->memMgr, f); return; } /* ASN_CMS_FreeVariableBlock */ /************************************************************************ * pack and unpack -- taking block type as a parameter/ *************************************************************************/ static size_t UnpkInPlaceSegments( ASN_CMS_CONTEXT *ctx, int indefFlag, /* is this an indefinite length block or not? */ unsigned char exptag, /* my expected block tag */ ASN_CMS_VariableBlock *asnblock, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ int *erret) /* error return location */ { size_t bytesused = 0; size_t datasize; /* validity of ctx and erret checked in UnpkInPlaceVariableBlock */ if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } /* validity of asnblock checked in UnpkInPlaceVariableBlock */ asnblock->val = NULL; asnblock->len = 0; /* while there are segments */ while (1) { /* For indef length end-of-contents is 0x00 0x00 and we have to eat those two bytes, otherwise we see if we've used up all the available data yet */ if ( indefFlag == 1 && (*(buf+bytesused) == 0x00 && *(buf+bytesused+1) == 0x00) ) { bytesused += 2; break; } else if (indefFlag == 0 && bytesused == buflen) break; if (*buf != exptag) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } bytesused++; /* skip the tag byte */ datasize = 0; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); /* no nested indef lengths for string types */ if ((int)datasize == -1) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } if (bytesused + datasize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); /* note this error */ return 0; } if (datasize == 0) continue; ASN_CMS_Realloc(ctx->memMgr, (void **)&asnblock->val, asnblock->len+datasize); if (asnblock->val == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } memcpy(asnblock->val + asnblock->len, buf+bytesused, datasize); asnblock->len += datasize; bytesused += datasize; } /* while there are segments */ return bytesused; } /* UnpkInPlaceSegments */ static size_t UnpkInPlaceVariableBlock( ASN_CMS_CONTEXT *ctx, unsigned char exptag, /* my expected block tag */ const char *name, /* my block name */ unsigned char tag, /* my real tag */ ASN_CMS_VariableBlock *asnblock, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ int *erret) /* error return location */ { size_t bytesused; size_t datasize; int constructed = 0; int indef = 0; ASN_CMS_TRACE_name(name); ASN_CMS_TRACE_PRINT_FM(exptag, tag, name); if (erret == NULL) return 0; /* can't report errors */ if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnblock == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ /* we need to ignore the 6th bit for this check, if this is BER then it may be set, the checks below test for those cases */ if ( (*buf & 0xDF) != (exptag & 0xDF) ) return 0; /* no error code, just no block */ if ( (*buf & 0x20) == 0x20) constructed = 1; bytesused = 1; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if ((int)datasize == -1) { /* indef length */ datasize = 0; indef = 1; } if (bytesused+datasize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); /* note this error */ return 0; } if (indef == 1 && constructed != 1) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } if (asnblock->val != NULL) ASN_CMS_Free(ctx->memMgr, asnblock->val); /* about to carve it */ ASN_CMS_TRACE_PRINT_DATA(buf+bytesused,datasize); if (constructed == 0) { /* primitive */ asnblock->len = datasize; /* record the length */ asnblock->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, datasize); if (asnblock->val == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } memcpy(asnblock->val, buf+bytesused, datasize); bytesused += datasize; } else if (indef == 1) { /* constructed, indefinite length */ bytesused += UnpkInPlaceSegments(ctx, indef, tag, asnblock, buf+bytesused, buflen-bytesused, erret); } else { /* constructed, definite length */ bytesused += UnpkInPlaceSegments(ctx, indef, (unsigned char)(exptag & 0xDF), asnblock, buf+bytesused, datasize, erret); } return bytesused; } /* UnpkInPlaceVariableBlock */ /************************************************************************ * PackVariableBlock * * Pack up an ASN_CMS_VariableBlock -- which could be an INTEGER, BIT STRING or * OCTET STRING. * * Those three differ in padding (or its inverse). * * For OCTET STRING, pad = 0 * For BIT STRING, pad = 1, padb = # unused bits in the LSByte * For INTEGER, pad = 0..-N, where N is the # of unnecesary leading * 0x00 or 0xff bytes * * pad and padb have to be filled in by the caller. *************************************************************************/ static size_t PackVariableBlock( ASN_CMS_CONTEXT *ctx, unsigned char blockType, /* my block type */ int pad, /* padding? (boolean) */ unsigned char padbyte, /* pad byte if (pad) */ unsigned char *buf, /* the output pointer pointer */ size_t buflen, ASN_CMS_VariableBlock *block, /* the block I'm packing */ int *erret) /* an error */ { size_t bytesused = 0; unsigned char *lastbyte; unsigned char mask = 0xFF; (void)ctx; /* for future use */ if (block == NULL) return 0; if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrPackNoBlock); return 0; } /* need room for tag + length bytes*/ if (buflen < (1 + ASN_CMS_LengthSize(block->len+pad)) ) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return 0; } bytesused = ASN_CMS_PutTag(buf, blockType, block->len+pad); if (pad) { /* error here if padbyte > 7??? */ if (buflen < (bytesused + 1 + block->len) ) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return 0; } /* add the pad byte before the data */ bytesused += ASN_CMS_PutByte( buf+bytesused, padbyte); memcpy(buf+bytesused, block->val, block->len); bytesused += block->len; /* for DER bit strings, the padding bits must be zeros */ if (padbyte != 0) { lastbyte = buf + bytesused - 1; mask = mask << padbyte; /* zeros are shifted in */ *lastbyte = *lastbyte & mask; } } else { if (buflen < (bytesused + block->len) ) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return 0; } /* just add the data */ memcpy(buf+bytesused, block->val, block->len); bytesused += block->len; } return bytesused; } /* PackVariableBlock */ /************************************************************************ * ASN_CMS_PutOctVal * * Put a octet buffer value away in a vbl block. *************************************************************************/ int ASN_CMS_PutOctVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *block, /* the block for the value */ const unsigned char *value, /* the value */ size_t lth) /* the length */ { if (ctx == NULL) return ASN_CMS_ErrBadContext; if (block == NULL) return (-1); if (block->val != NULL) ASN_CMS_Free(ctx->memMgr, block->val); memset (block, 0, sizeof(ASN_CMS_VariableBlock)); block->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, lth); if (block->val == NULL) return (-1); memcpy( block->val, value, lth ) ; block->len = lth ; return (0); } /* ASN_CMS_PutOctVal */ /************************************************************************ * ASN_CMS_PutStrVal * * Put a string value away in a vbl block. *************************************************************************/ int ASN_CMS_PutStrVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *block, /* the block for the value */ const char *value) /* the value */ { if (ctx == NULL) return ASN_CMS_ErrBadContext; if (block == NULL) return (-1); if (block->val != NULL) ASN_CMS_Free(ctx->memMgr, block->val); memset(block, 0, sizeof(ASN_CMS_VariableBlock)); block->len = strlen(value); block->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, block->len); if (block->val == NULL) return (-1); memcpy(block->val, value, block->len); return (0); } /* ASN_CMS_PutStrVal */ /************************************************************************ *ASN_CMS_GetStrVal * * Return a string value found in a vbl block. *************************************************************************/ char *ASN_CMS_GetStrVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_VariableBlock *block) { char *string; if (ctx == NULL) return NULL; if (block == NULL) return NULL; if (block->val == NULL || block->len == 0) return NULL; /* '+1' for NULL char */ string = (char *)ASN_CMS_Alloc(ctx->memMgr, block->len + 1); if (string == NULL) return NULL; memcpy(string, block->val, block->len); string[block->len] = '\0'; return string; } /* ASN_CMS_GetStrVal */ /************************************************************************ * ASN_CMS_PutBitString * * Put a bit string value away in a bitstring block. ************************************************************************/ int ASN_CMS_PutBitString ( ASN_CMS_CONTEXT *ctx, ASN_CMS_BitstringBlock *block, /* the block for the value */ const unsigned char *string, /* the value */ size_t lth, /* the length */ int nuub) /* number of unused bits LSB */ { if (ctx == NULL) return ASN_CMS_ErrBadContext; if (block == NULL) return (-1); if ((block->val) != NULL) ASN_CMS_Free(ctx->memMgr, block->val); memset (block, 0, sizeof(ASN_CMS_BitstringBlock)); block->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, lth); if (block->val == NULL) return (-1); memcpy(block->val, string, lth); block->len = lth; block->nuub = nuub; return 0; } /************************************************************************ * ASN_CMS_PutBoolVal * * Put a boolean value in an ASN_CMS_BOOLEAN block. *************************************************************************/ int ASN_CMS_PutBoolVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *block, /* the block for the value */ int val) /* */ { (void)ctx; /* for future use */ if (block == NULL) return (-1); if (val != 0) block->val = ASN_CMS_TRUE; else block->val = ASN_CMS_FALSE; block->len = 1; return 0; } /************************************************************************ * ASN_CMS_GetBoolVal * * Put a boolean value in an ASN_CMS_BOOLEAN block. *************************************************************************/ int ASN_CMS_GetBoolVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *block) /* the block for the value */ { (void)ctx; /* for future use */ if (block == NULL) return (-1); if (block->val != 0) return ASN_CMS_TRUE; else return ASN_CMS_FALSE; } /************************************************************************ * NULL routines *************************************************************************/ ASN_CMS_NULL *ASN_CMS_NewNULL( ASN_CMS_CONTEXT *ctx) { ASN_CMS_NULL *f = NULL; if (ctx == NULL) return NULL; f = (ASN_CMS_NULL *)ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_NULL)); if (f != NULL) memset(f, 0, sizeof(ASN_CMS_NULL) ); return ((ASN_CMS_NULL *) f); } /* ASN_CMS_NewNULL */ void ASN_CMS_DropInPlaceNULL( ASN_CMS_CONTEXT *ctx, ASN_CMS_NULL *f) { (void)ctx; (void)f; return ; } /* ASN_CMS_DropInPlaceNULL */ void ASN_CMS_FreeNULL( ASN_CMS_CONTEXT *ctx, ASN_CMS_NULL *g) { if (ctx == NULL) return; if (g != NULL) ASN_CMS_Free(ctx->memMgr, g); } /* ASN_CMS_FreeNULL */ size_t ASN_CMS_SizeofNULL( ASN_CMS_CONTEXT *ctx, ASN_CMS_NULL *b, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofNULLInternal(b, outerSizeFlag, ASN_CMS_FALSE); } /* ASN_CMS_SizeofNULL */ size_t ASN_CMS_SizeofNULLInternal( ASN_CMS_NULL *b, int outerSizeFlag, int expTaggedFlag) { size_t length = 0; if (b == NULL) return 0; if (outerSizeFlag == ASN_CMS_TRUE) length = 2; if (expTaggedFlag == ASN_CMS_TRUE) length = ASN_CMS_Tagged(length, 0); return length; } /* ASN_CMS_SizeofNULLInternal */ size_t ASN_CMS_PackNULL( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_NULL *asnblock, int *erret) { return (ASN_CMS_PackNULLInternal(ctx, buf, buflen, asnblock, ASN_CMS_ID_NULL, erret)); } size_t ASN_CMS_PackNULLInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_NULL *asnblock, unsigned char tag, int *erret) { size_t bytesused; (void)ctx; /* for future use */ if (erret == NULL) return 0; if (asnblock == NULL) return 0; bytesused = ASN_CMS_PutByte(buf, tag); bytesused += ASN_CMS_PutByte(buf+bytesused, 0x00); /* length = 0 bytes */ if (bytesused > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); /* note this error */ return 0; } return bytesused; } /* ASN_CMS_PackNULLInternal */ size_t ASN_CMS_UnpkInPlaceNULL( ASN_CMS_CONTEXT *ctx, ASN_CMS_NULL *nullstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, /* tag to use */ int *erret /* error return location */ ) { size_t bytesused; size_t datasize; ASN_CMS_TRACE_PRINT_FM(tag, 0x05, "NULL"); (void)ctx; if (erret == NULL) return 0; /* can't report errors */ if (nullstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ if (*buf != tag) return 0; /* no error, no block */ bytesused = 1; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if (datasize != 0) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNullLth); return 0; } if (bytesused > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); /* note this error */ return 0; } nullstruct->len = 0; return bytesused; } /* ASN_CMS_UnpkInPlaceNULL */ size_t ASN_CMS_UnpackNULL( ASN_CMS_CONTEXT *ctx, ASN_CMS_NULL **nullstruct, const unsigned char *buf, size_t buflen, int *erret) /* error return */ { return(ASN_CMS_UnpackNULLInternal(ctx, nullstruct, buf, buflen, ASN_CMS_ID_NULL, erret)); } /* ASN_CMS_UnpackNULL */ size_t ASN_CMS_UnpackNULLInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_NULL **nullstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_NULL *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (nullstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *nullstruct = NULL; if (buflen <= 0) return 0; if (*buf != tag) return 0; local = ASN_CMS_NewNULL(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceNULL(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeNULL(ctx, local); return 0; } *nullstruct = local; return bytesused; } /* ASN_CMS_UnpackNULLInternal */ /************************************************************************ * ASN_CMS_BOOLEAN routines *************************************************************************/ ASN_CMS_BOOLEAN *ASN_CMS_NewBOOLEAN( ASN_CMS_CONTEXT *ctx) { ASN_CMS_BOOLEAN *f = NULL; if (ctx == NULL) return NULL; f = (ASN_CMS_BOOLEAN *)ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_BOOLEAN) ); if (f != NULL) memset(f, 0, sizeof(ASN_CMS_BOOLEAN) ); return ((ASN_CMS_BOOLEAN *) f); } /* NewBOOLEAN */ void ASN_CMS_DropInPlaceBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *f) { (void)ctx; (void)f; return ; } /* ASN_CMS_DropInPlaceBOOLEAN */ void ASN_CMS_FreeBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *g ) { if (ctx == NULL) return; if (g != NULL) ASN_CMS_Free(ctx->memMgr, g); } /* ASN_CMS_FreeBOOLEAN */ size_t ASN_CMS_SizeofBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *boolblock, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofBOOLEANInternal(boolblock, outerSizeFlag, ASN_CMS_FALSE); } size_t ASN_CMS_SizeofBOOLEANInternal( ASN_CMS_BOOLEAN *boolblock, int outerSizeFlag, int expTaggedSize) { size_t length = 1; if (boolblock == NULL) return 0; if (outerSizeFlag == ASN_CMS_TRUE) length = 3; if (expTaggedSize == ASN_CMS_TRUE) length = ASN_CMS_Tagged(length, 0); return length; } /* ASN_CMS_SizeofBOOLEANInternal */ size_t ASN_CMS_PackBOOLEAN( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_BOOLEAN *boolblock, int *erret ) { return(ASN_CMS_PackBOOLEANInternal(ctx, buf, buflen, boolblock, ASN_CMS_ID_BOOLEAN, erret)); } /* ASN_CMS_PackBOOLEAN */ size_t ASN_CMS_PackBOOLEANInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_BOOLEAN *boolblock, unsigned char tag, int *erret ) { unsigned char value = 0x00; size_t bytesused; (void)ctx; /* for future use */ if (boolblock == NULL) return 0; if (boolblock->val != 0) value = 0xff; bytesused = ASN_CMS_PutByte(buf, tag); /* this is a ASN_CMS_BOOLEAN */ bytesused += ASN_CMS_PutByte(buf+bytesused, 1); /* length = 1 byte */ bytesused += ASN_CMS_PutByte(buf+bytesused, value); /* the value */ if (bytesused > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); /* note this error */ return 0; } return bytesused; } /* ASN_CMS_PackBOOLEANInternal */ size_t ASN_CMS_UnpkInPlaceBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN *boolstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { size_t bytesused; size_t datasize; (void)ctx; ASN_CMS_TRACE_PRINT_FM(tag, 0x01, "BOOLEAN"); if (erret == NULL) return 0; /* can't report errors */ if (boolstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ if (*buf != tag) return 0; bytesused = 1; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if (datasize != 1) { ASN_CMS_ERR( ASN_CMS_ErrUnpackBooleanLth); return 0; } if (bytesused+datasize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); /* note this error */ return 0; } ASN_CMS_TRACE_PRINT_DATA(buf+bytesused,1); bytesused += ASN_CMS_GetByte(buf+bytesused, (unsigned char *)&(boolstruct->val)); if (boolstruct->val != 0) boolstruct->val = ASN_CMS_TRUE; return bytesused; } /* ASN_CMS_UnpkInPlaceBOOLEAN */ size_t ASN_CMS_UnpackBOOLEAN( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN **boolstruct, const unsigned char *buf, size_t buflen, int *erret) /* error return */ { return(ASN_CMS_UnpackBOOLEANInternal(ctx, boolstruct, buf, buflen, ASN_CMS_ID_BOOLEAN, erret)); } size_t ASN_CMS_UnpackBOOLEANInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_BOOLEAN **boolstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_BOOLEAN *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (boolstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *boolstruct = NULL; if (buflen <= 0) return 0; if (*buf != tag) return 0; local = ASN_CMS_NewBOOLEAN(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceBOOLEAN(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeBOOLEAN(ctx, local); return 0; } *boolstruct = local; return bytesused; } /* ASN_CMS_UnpackBOOLEANInternal */ /************************************************************************ * Routines for ASN_CMS_BIT_STRING *************************************************************************/ ASN_CMS_BIT_STRING *ASN_CMS_NewBIT_STRING( ASN_CMS_CONTEXT *ctx) { ASN_CMS_BIT_STRING *f = NULL ; if (ctx == NULL) return NULL; f = (ASN_CMS_BIT_STRING *)ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_BIT_STRING) ); if (f != NULL) memset( f, 0, sizeof(ASN_CMS_BIT_STRING) ); return ((ASN_CMS_BIT_STRING *) f); } /* ASN_CMS_NewBIT_STRING */ void ASN_CMS_DropInPlaceBIT_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING *f ) { if (ctx == NULL) return; if (f != NULL) { if ((f->val) != NULL) { ASN_CMS_Free(ctx->memMgr, f->val); } f->val = NULL ; } return ; } /* ASN_CMS_DropInPlaceBIT_STRING */ void ASN_CMS_FreeBIT_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING *f ) { if (ctx == NULL) return; ASN_CMS_DropInPlaceBIT_STRING(ctx, f); if (f != NULL) ASN_CMS_Free(ctx->memMgr, f); } /* ASN_CMS_FreeBIT_STRING */ size_t ASN_CMS_SizeofBIT_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING *bitblock, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofBIT_STRINGInternal(bitblock, outerSizeFlag, ASN_CMS_FALSE); } size_t ASN_CMS_SizeofBIT_STRINGInternal( ASN_CMS_BIT_STRING *bitblock, int outerSizeFlag, int expTaggedSize) { size_t body_size; if (bitblock == NULL) return (0); body_size = 1 + bitblock->len; if (outerSizeFlag == ASN_CMS_TRUE) body_size = ASN_CMS_Tagged(body_size, 0); if (expTaggedSize == ASN_CMS_TRUE) body_size = ASN_CMS_Tagged(body_size, 0); return body_size; } /* ASN_CMS_SizeofBIT_STRINGInternal */ size_t ASN_CMS_PackBIT_STRING( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_BIT_STRING *bitblock, int *erret) { return (PackVariableBlock(ctx, ASN_CMS_ID_BIT_STRING, ASN_CMS_TRUE, (unsigned char)bitblock->nuub, buf, buflen, (ASN_CMS_VariableBlock *)bitblock, erret)); } size_t ASN_CMS_PackBIT_STRINGInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_BIT_STRING *bitblock, unsigned char tag, int *erret) { return (PackVariableBlock(ctx, tag, ASN_CMS_TRUE, (unsigned char)bitblock->nuub, buf, buflen, (ASN_CMS_VariableBlock *)bitblock, erret)); } /* ASN_CMS_PackBIT_STRINGInternal */ static size_t uipBitSegments( ASN_CMS_CONTEXT *ctx, int indefFlag, /* is this an indefinite length block or not? */ unsigned char exptag, /* my expected block tag */ ASN_CMS_BIT_STRING *bitblock, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ int *erret) /* error return location */ { size_t bytesused = 0; size_t datasize; /* validity of erret and ctx checked in UnpkInPlaceBIT_STRING */ if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } /* validity of bitblock checked in UnpkInPlaceBIT_STRING */ bitblock->val = NULL; bitblock->len = 0; bitblock->nuub = 0; /* while there are segments */ while (1) { /* For indef length end-of-contents is 0x00 0x00 and we have to eat those two bytes, otherwise we see if we've used up all the available data yet */ if ( indefFlag == 1 && (*(buf+bytesused) == 0x00 && *(buf+bytesused+1) == 0x00) ) { bytesused += 2; break; } else if (indefFlag == 0 && bytesused == buflen) break; if (*buf != exptag) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } bytesused++; /* skip the tag byte */ datasize = 0; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if ((int)datasize == -1) { /* no nested indef lengths for bit string types */ ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } if (bytesused + datasize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); /* note this error */ return 0; } if (datasize == 0) continue; /* All segments but the last must be multiples of 8 bits, so the nuub value for all segments but the last must have 0 for the nuub. So we check for 0 nuub here, if the previous segment did not have 0 nuub, then its an error. If this is the last segment, we will exit the loop so the new nuub can be other then 0. */ if (bitblock->nuub == 0) { /* the first byte of the data is the number of unused bits */ bitblock->nuub = *(buf+bytesused); bytesused++; ASN_CMS_Realloc(ctx->memMgr, (void **)&bitblock->val, bitblock->len+datasize-1); if (bitblock->val == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } memcpy(bitblock->val + bitblock->len, buf+bytesused, datasize-1); bitblock->len += datasize-1; bytesused += datasize-1; } else { /* error */ ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } } /* while there are segments */ return bytesused; } /* UnpkInPlacebit_segments */ size_t ASN_CMS_UnpkInPlaceBIT_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING *bitstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { size_t bytesused; size_t datasize; int constructed = 0; int indef = 0; if (erret == NULL) return 0; /* can't report errors */ *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (bitstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } ASN_CMS_TRACE_PRINT_FM(tag, 0x03, "BIT STRING"); if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; if ( (*buf & 0x20) == 0x20) constructed = 1; bytesused = 1; /* eat the tag byte */ bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if ((int)datasize == -1) { /* indef length */ datasize = 0; indef = 1; } if (bytesused+datasize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); /* note this error */ return 0; } if (indef == 1 && constructed != 1) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } if (bitstruct->val != NULL) ASN_CMS_Free(ctx->memMgr, bitstruct->val); ASN_CMS_TRACE_PRINT_DATA(buf+bytesused,datasize); if (constructed == 0) { /* primitive */ /* the first byte of the data is the number of unused bits */ bitstruct->nuub = *(buf+bytesused); bytesused++; /* the len is -1 since we just used one byte for the nuub value */ bitstruct->len = datasize-1; bitstruct->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, bitstruct->len); if (bitstruct->val == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } memcpy(bitstruct->val, buf+bytesused, bitstruct->len); bytesused += bitstruct->len; } else if (indef == 1) { /* constructed, indefinite length */ bytesused += uipBitSegments(ctx, indef, (unsigned char)(tag & 0xDF), bitstruct, buf+bytesused, buflen-bytesused, erret); } else { /* constructed, definite length */ bytesused += uipBitSegments(ctx, indef, (unsigned char)(tag & 0xDF), bitstruct, buf+bytesused, datasize, erret); } return bytesused; } /* ASN_CMS_UnpkInPlaceBIT_STRING */ size_t ASN_CMS_UnpackBIT_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING **bitstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackBIT_STRINGInternal(ctx, bitstruct, buf, buflen, ASN_CMS_ID_BIT_STRING, erret)); } size_t ASN_CMS_UnpackBIT_STRINGInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_BIT_STRING **bitstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_BIT_STRING *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (bitstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *bitstruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewBIT_STRING(ctx); bytesused = ASN_CMS_UnpkInPlaceBIT_STRING(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeBIT_STRING(ctx, local); return 0; } *bitstruct = local; return bytesused; } /* ASN_CMS_UnpackBIT_STRINGInternal */ /************************************************************************ * Routines for ASN_CMS_GeneralizedTime *************************************************************************/ size_t ASN_CMS_PackGeneralizedTime( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_GeneralizedTime *timeblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_GeneralizedTime, ASN_CMS_FALSE, 0, buf, buflen, timeblock, erret)); } size_t ASN_CMS_PackGeneralizedTimeInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_GeneralizedTime *timeblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, timeblock, erret)); } /* ASN_CMS_PackGeneralizedTimeInternal */ size_t ASN_CMS_UnpkInPlaceGeneralizedTime( ASN_CMS_CONTEXT *ctx, ASN_CMS_GeneralizedTime *timestruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { return(UnpkInPlaceVariableBlock(ctx, tag, "GeneralizedTime", 0x18, timestruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceGeneralizedTime */ size_t ASN_CMS_UnpackGeneralizedTime( ASN_CMS_CONTEXT *ctx, ASN_CMS_GeneralizedTime **timestruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackGeneralizedTimeInternal(ctx, timestruct, buf, buflen, ASN_CMS_ID_GeneralizedTime, erret)); } size_t ASN_CMS_UnpackGeneralizedTimeInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_GeneralizedTime **timestruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_GeneralizedTime *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (timestruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *timestruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewGeneralizedTime(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceGeneralizedTime(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeGeneralizedTime(ctx, local); return 0; } *timestruct = local; return bytesused; } /* ASN_CMS_UnpackGeneralizedTimeInternal */ /************************************************************************ * Routines for ASN_CMS_IA5String *************************************************************************/ size_t ASN_CMS_PackIA5String( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_IA5String *strblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_IA5String, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret)); } /* ASN_CMS_PackIA5String */ size_t ASN_CMS_PackIA5StringInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_IA5String *strblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret)); } /* ASN_CMS_PackIA5StringInternal */ size_t ASN_CMS_UnpkInPlaceIA5String( ASN_CMS_CONTEXT *ctx, ASN_CMS_IA5String *strblock, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { return (UnpkInPlaceVariableBlock(ctx, tag, "IA5String", 0x16, strblock, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceIA5String */ size_t ASN_CMS_UnpackIA5String( ASN_CMS_CONTEXT *ctx, ASN_CMS_IA5String **strblock, const unsigned char *buf, size_t buflen, /* my end pointer */ int *erret) { return(ASN_CMS_UnpackIA5StringInternal(ctx, strblock, buf, buflen, ASN_CMS_ID_IA5String, erret)); } size_t ASN_CMS_UnpackIA5StringInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_IA5String **strblock, const unsigned char *buf, size_t buflen, /* my end pointer */ unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_IA5String *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (strblock == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *strblock = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewIA5String(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceIA5String(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeIA5String(ctx, local); return 0; } *strblock = local; return bytesused; } /* ASN_CMS_UnpackIA5StringInternal */ /************************************************************************ * Routines for ASN_CMS_INTEGER *************************************************************************/ /************************************************************************ * normalize * * remove leading 0's from the integer byte string/ * This routine isn't the most efficient, but it should never have to * move any bytes because all numbers should be normalized already. *************************************************************************/ static void normalize( ASN_CMS_INTEGER *b ) { size_t i ; unsigned char *x ; if (b == NULL) return ; if ((b->val) == NULL) { b->len = 0 ; /* no bytes, no length */ return ; } x = b->val ; /* point to the array */ while ( (((x[0]^x[1])&0x80) == 0) && ((x[0] == 0)||(x[0] == 0xff)) && ((b->len) > 1) ) { /* shorten this by 1 byte */ (b->len)-- ; /* note the shortening */ for (i=0; i<(b->len); i++) x[i] = x[i+1] ; /* do it */ } /* while */ return ; } /* normalize */ size_t ASN_CMS_SizeofINTEGER( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *intblock, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofINTEGERInternal(intblock, outerSizeFlag, ASN_CMS_FALSE); } size_t ASN_CMS_SizeofINTEGERInternal( ASN_CMS_INTEGER *intblock, int outerSizeFlag, int expTaggedSize) { size_t length; if (intblock == NULL) return 0; normalize(intblock); length = intblock->len; if (outerSizeFlag == ASN_CMS_TRUE) length = length + 1 + ASN_CMS_LengthSize(length); if (expTaggedSize == ASN_CMS_TRUE) length = ASN_CMS_Tagged(length, 0); return length; } /* ASN_CMS_SizeofINTEGERInternal */ size_t ASN_CMS_PackINTEGER( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_INTEGER *intblock, int *erret) { return(ASN_CMS_PackINTEGERInternal(ctx, buf, buflen, intblock, ASN_CMS_ID_INTEGER, erret)); } size_t ASN_CMS_PackINTEGERInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_INTEGER *intblock, unsigned char tag, int *erret) { if (intblock == NULL) return 0; normalize(intblock); return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, intblock, erret)); } size_t ASN_CMS_UnpkInPlaceINTEGER( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *intstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { return (UnpkInPlaceVariableBlock(ctx, tag, "INTEGER", 0x02, intstruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceINTEGER */ size_t ASN_CMS_UnpackINTEGER( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER **intstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackINTEGERInternal(ctx, intstruct, buf, buflen, ASN_CMS_ID_INTEGER, erret)); } size_t ASN_CMS_UnpackINTEGERInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER **intstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_INTEGER *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (intstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *intstruct = NULL; if (buflen <= 0) return 0; if (*buf != tag) return 0; local = ASN_CMS_NewINTEGER(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceINTEGER(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeINTEGER(ctx, local); return 0; } *intstruct = local; return bytesused; } /* ASN_CMS_UnpackINTEGERInternal */ /************************************************************************ * ASN_CMS_GetIntVal * * Extract a long from the ASN_CMS_INTEGER b. *************************************************************************/ long ASN_CMS_GetIntVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *b, int *error) { long val = 0; size_t i; unsigned char *x; (void)ctx; /* for future use */ if (error == NULL) return 0; *error = 0; if ( b == NULL || b->len > 4 || b->val == NULL ) { *error = -1; return 0; } x = b->val; for (i=0; i < b->len; i++) { val <<= 8; val += x[i]; } return val; } /* ASN_CMS_GetIntVal */ /************************************************************************ * ASN_CMS_PutIntVal * * Pack an integer value into a byte string *************************************************************************/ int ASN_CMS_PutIntVal( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *b, /* the block to take that value */ long v /* the value */ ) { long i ; unsigned char *x ; if (ctx == NULL) return ASN_CMS_ErrBadContext; if (b == NULL) return (-1); if ((b->val) != NULL) ASN_CMS_Free(ctx->memMgr, b->val); memset (b, 0, sizeof (ASN_CMS_INTEGER)); b->val = x = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, 4); if (b->val == NULL) return (-1); b->len = 4 ; for (i=3; i >= 0; i-- ) { x[i] = v & 0xff ; v >>= 8 ; } normalize( b ) ; return 0; } /* ASN_CMS_PutIntVal */ /************************************************************************ * ASN_CMS_PutUIntBytes * * Packs a large (greater than a C integer) unsigned integer value * into a ASN_CMS_INTEGER type. This routine adds a leading zero byte if * the provided data's leading bit is set. *************************************************************************/ int ASN_CMS_PutUIntBytes( ASN_CMS_CONTEXT *ctx, ASN_CMS_INTEGER *block, /* the block for the value */ const unsigned char *value, /* the value */ size_t lth) /* the length */ { size_t newLen = lth; if (ctx == NULL) return ASN_CMS_ErrBadContext; if (block == NULL) return (-1); if (block->val != NULL) ASN_CMS_Free(ctx->memMgr, block->val); memset (block, 0, sizeof(ASN_CMS_INTEGER)); if ( (value[0] & 0x80) == 0x80 ) newLen++; block->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, newLen); if (block->val == NULL) return (-1); memset (block->val, 0, newLen); if ( (value[0] & 0x80) == 0x80 ) memcpy( block->val+1, value, lth); else memcpy( block->val, value, lth); block->len = newLen; return (0); } /* ASN_CMS_PutOctVal */ /************************************************************************ * Routines for ASN_CMS_NumericString *************************************************************************/ size_t ASN_CMS_PackNumericString( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_NumericString *numblock, int *erret ) { return(ASN_CMS_PackNumericStringInternal(ctx, buf, buflen, numblock, ASN_CMS_ID_NumericString, erret)); } /* ASN_CMS_PackNumericString */ size_t ASN_CMS_PackNumericStringInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_NumericString *numblock, unsigned char tag, int *erret ) { size_t bytesused; size_t i; bytesused = PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, numblock, erret); if (bytesused == 0 || *erret != 0) return(bytesused); /* after the pack since then we know numblock is okay */ for ( i = 0; i < numblock->len; i++ ) { if (isdigit(numblock->val[i])) continue; if (numblock->val[i] == (unsigned char)' ' /* space */ ) continue; ASN_CMS_ERR(ASN_CMS_ErrBadNumericString); bytesused = 0; break; } return(bytesused); } /* ASN_CMS_PackNumericStringInternal */ size_t ASN_CMS_UnpkInPlaceNumericString( ASN_CMS_CONTEXT *ctx, ASN_CMS_NumericString *numstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { size_t bytesused; size_t i; bytesused = UnpkInPlaceVariableBlock(ctx, tag, "NumericString", 0x12, numstruct, buf, buflen, erret); if (bytesused == 0 || *erret != 0) return bytesused; for ( i = 0; i < numstruct->len; i++ ) { if (isdigit(numstruct->val[i])) continue; if (numstruct->val[i] == (unsigned char)' ' /* space */ ) continue; ASN_CMS_ERR(ASN_CMS_ErrBadNumericString); bytesused = 0; break; } return bytesused; } /* ASN_CMS_UnpkInPlaceNumericString */ size_t ASN_CMS_UnpackNumericString( ASN_CMS_CONTEXT *ctx, ASN_CMS_NumericString **numstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackNumericStringInternal(ctx, numstruct, buf, buflen, ASN_CMS_ID_NumericString, erret)); } size_t ASN_CMS_UnpackNumericStringInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_NumericString **numstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_NumericString *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (numstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *numstruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewNumericString(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceNumericString(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeNumericString(ctx, local); return 0; } *numstruct = local; return bytesused; } /* ASN_CMS_UnpackNumericStringInternal */ /************************************************************************ * Routines for ASN_CMS_OBJECT_ID *************************************************************************/ size_t ASN_CMS_PackOBJECT_ID( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OBJECT_ID *oidblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_OBJECT_ID, ASN_CMS_FALSE, 0, buf, buflen, oidblock, erret)); } size_t ASN_CMS_PackOBJECT_IDInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OBJECT_ID *oidblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, oidblock, erret)); } /* ASN_CMS_PackOBJECT_IDInternal */ int ASN_CMS_UnpkInPlaceOBJECT_ID( ASN_CMS_CONTEXT *ctx, ASN_CMS_OBJECT_ID *oidstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) { return (UnpkInPlaceVariableBlock(ctx, tag, "OBJECT IDENTIFIER", 0x06, oidstruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceOBJECT_ID */ size_t ASN_CMS_UnpackOBJECT_ID( ASN_CMS_CONTEXT *ctx, ASN_CMS_OBJECT_ID **oidstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackOBJECT_IDInternal(ctx, oidstruct, buf, buflen, ASN_CMS_ID_OBJECT_ID, erret)); } size_t ASN_CMS_UnpackOBJECT_IDInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_OBJECT_ID **oidstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_OBJECT_ID *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (oidstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *oidstruct = NULL; if (buflen <= 0) return 0; if (*buf != tag) return 0; local = ASN_CMS_NewOBJECT_ID(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceOBJECT_ID(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeOBJECT_ID(ctx, local); return 0; } *oidstruct = local; return bytesused; } /* ASN_CMS_UnpackOBJECT_IDInternal */ /************************************************************************ * Routines for ASN_CMS_OCTET_STRING *************************************************************************/ size_t ASN_CMS_PackOCTET_STRING( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OCTET_STRING *octblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_OCTET_STRING, ASN_CMS_FALSE, 0, buf, buflen, octblock, erret)); } size_t ASN_CMS_PackOCTET_STRINGInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_OCTET_STRING *octblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, octblock, erret)); } /* ASN_CMS_PackOCTET_STRINGInternal */ size_t ASN_CMS_UnpkInPlaceOCTET_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_OCTET_STRING *octstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) { return (UnpkInPlaceVariableBlock(ctx, tag, "OCTET STRING", 0x04, octstruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceOCTET_STRING */ size_t ASN_CMS_UnpackOCTET_STRING( ASN_CMS_CONTEXT *ctx, ASN_CMS_OCTET_STRING **octstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackOCTET_STRINGInternal(ctx, octstruct, buf, buflen, ASN_CMS_ID_OCTET_STRING, erret)); } size_t ASN_CMS_UnpackOCTET_STRINGInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_OCTET_STRING **octstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_OCTET_STRING *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (octstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *octstruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewOCTET_STRING(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceOCTET_STRING(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeOCTET_STRING(ctx, local); return 0; } *octstruct = local; return bytesused; } /* ASN_CMS_UnpackOCTET_STRINGInternal */ /************************************************************************ * Routines for ASN_CMS_PrintableString *************************************************************************/ size_t ASN_CMS_PackPrintableString( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_PrintableString *strblock, int *erret ) { return(ASN_CMS_PackPrintableStringInternal(ctx, buf, buflen, strblock, ASN_CMS_ID_PrintableString, erret)); } size_t ASN_CMS_PackPrintableStringInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_PrintableString *strblock, unsigned char tag, int *erret ) { size_t bytesused; size_t i; bytesused = PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret); if (bytesused == 0 || *erret != 0) return(bytesused); for ( i = 0; i < strblock->len; i++ ) { if ( isdigit( strblock->val[i] ) ) continue; if ( isalpha( strblock->val[i] ) ) continue; if ( strchr( "'\"()+,-./:=? ", strblock->val[i] ) != 0 ) continue; ASN_CMS_ERR(ASN_CMS_ErrBadPrintableString); bytesused = 0; break; } return(bytesused); } /* ASN_CMS_PackPrintableStringInternal */ int ASN_CMS_UnpkInPlacePrintableString( ASN_CMS_CONTEXT *ctx, ASN_CMS_PrintableString *printstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) { size_t bytesused; size_t i; bytesused = UnpkInPlaceVariableBlock(ctx, tag, "PrintableString", 0x13, printstruct, buf, buflen, erret); if (bytesused == 0 || *erret != 0) return(bytesused); for ( i = 0; i < printstruct->len; i++ ) { if ( isdigit( printstruct->val[i] ) ) continue; if ( isalpha( printstruct->val[i] ) ) continue; if ( strchr( "'\"()+,-./:=? ", printstruct->val[i] ) != 0 ) continue; ASN_CMS_ERR(ASN_CMS_ErrBadPrintableString); bytesused = 0; break; } return bytesused; } /* ASN_CMS_UnpkInPlacePrintableString */ size_t ASN_CMS_UnpackPrintableString( ASN_CMS_CONTEXT *ctx, ASN_CMS_PrintableString **printstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackPrintableStringInternal(ctx, printstruct, buf, buflen, ASN_CMS_ID_PrintableString, erret)); } size_t ASN_CMS_UnpackPrintableStringInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_PrintableString **printstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_PrintableString *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (printstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *printstruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewPrintableString(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlacePrintableString(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreePrintableString(ctx, local); return 0; } *printstruct = local; return bytesused; } /* ASN_CMS_UnpackPrintablestringInternal */ /************************************************************************ * Routines for ASN_CMS_T61String *************************************************************************/ size_t ASN_CMS_PackT61String( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_T61String *strblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_T61String, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret)); } size_t ASN_CMS_PackT61StringInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_T61String *strblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret)); } size_t ASN_CMS_UnpkInPlaceT61String( ASN_CMS_CONTEXT *ctx, ASN_CMS_T61String *strstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) { return (UnpkInPlaceVariableBlock(ctx, tag, "T61String", 0x14, strstruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceT61String */ size_t ASN_CMS_UnpackT61String( ASN_CMS_CONTEXT *ctx, ASN_CMS_T61String **strstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackT61StringInternal(ctx, strstruct, buf, buflen, ASN_CMS_ID_T61String, erret)); } size_t ASN_CMS_UnpackT61StringInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_T61String **strstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_T61String *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (strstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *strstruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewT61String(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceT61String(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeT61String(ctx, local); return 0; } *strstruct = local; return bytesused; } /* ASN_CMS_UnpackT61StringInternal */ /************************************************************************ * Routines for ASN_CMS_ANY *************************************************************************/ size_t ASN_CMS_SizeofANY( ASN_CMS_CONTEXT *ctx, ASN_CMS_ANY *block, int outerSizeFlag) { (void)ctx; /* for future use */ return ASN_CMS_SizeofANYInternal(block, outerSizeFlag, ASN_CMS_FALSE); } size_t ASN_CMS_SizeofANYInternal( ASN_CMS_ANY *block, int outerSizeFlag, int expTaggedSize) { size_t length; /* for this inner always equals full, so we can ignore outerSizeFlag */ (void)outerSizeFlag; if (block == NULL) return (0); length = block->len; /* and an ANY may be constructed */ if (expTaggedSize == ASN_CMS_TRUE) length = ASN_CMS_Tagged(length, 0); return length; } /* ASN_CMS_SizeofANYInternal */ size_t ASN_CMS_PackANY( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_ANY *block, int *erret) { return(ASN_CMS_PackANYInternal(ctx, buf, buflen, block, ASN_CMS_ID_ANY, erret)); } size_t ASN_CMS_PackANYInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_ANY *block, unsigned char tag, int *erret) { (void)ctx; /* for future use */ if (erret == NULL) return 0; if (block == NULL) return 0; if (buf == NULL) return 0; if (block->len <= 0) return 0; if (block->val == NULL) return 0; if (block->len > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return 0; } if (tag == ASN_CMS_ID_ANY) { memcpy(buf, block->val, block->len); return block->len; } else { memcpy(buf, &tag, 1); memcpy(buf+1, block->val+1, block->len-1); return block->len; } } /* ASN_CMS_PackANYInternal */ static size_t BerBlockSize( const unsigned char *buf, size_t buflen, int *erret) { size_t bytesused; size_t datasize; if (erret == NULL) return 0; if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ /* allow any tag */ bytesused = 1; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if ((int)datasize >= 0) return (bytesused+datasize); /* else its indef length, so loop through all segments */ while (1) { if ( *(buf+bytesused) == 0x00 && *(buf+bytesused+1) == 0x00 ) { bytesused += 2; break; } /* recursive call to process the segment */ bytesused += BerBlockSize(buf + bytesused, buflen - bytesused, erret); if (*erret != 0) break; if (bytesused > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); return 0; } } return bytesused; } /* BerBlockSize */ size_t ASN_CMS_UnpkInPlaceANY( ASN_CMS_CONTEXT *ctx, ASN_CMS_ANY *asnstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) /* error return location */ { size_t bytesused; size_t datasize; /* the block data length */ size_t lth; (void)tag; /* any tag allowed */ if (erret == NULL) return 0; /* can't report errors */ *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ ASN_CMS_TRACE_PRINT_FM(*buf, *buf, "ANY"); bytesused = 1; /* accept ANY type byte */ /* get the block length */ bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); /* if this is indefinite length, we need to parse the ANY's DER data to get the block size. DerBlockSize returns the length of the entire block, including the leading tag and size bytes */ if ((int)datasize == -1) { datasize = 0; bytesused = BerBlockSize(buf, buflen, erret); if (*erret != 0) return 0; } lth = bytesused + datasize; if (lth > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); return 0; } ASN_CMS_TRACE_PRINT_DATA(buf+bytesused,datasize); if ((asnstruct->val) != NULL) ASN_CMS_Free(ctx->memMgr, asnstruct->val); /* We just copy the entire block here, no lower level unpacking takes place; so, the size of the buffer needed is the data plus the tag and size bytes. */ asnstruct->val = (unsigned char *)ASN_CMS_Alloc(ctx->memMgr, lth); if (asnstruct->val == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } /* copy the whole structure */ memcpy(asnstruct->val, buf, lth); asnstruct->len = lth; return lth; } /* ASN_CMS_UnpkInPlaceANY */ size_t ASN_CMS_UnpackANY( ASN_CMS_CONTEXT *ctx, ASN_CMS_ANY **asnstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackANYInternal(ctx, asnstruct, buf, buflen, ASN_CMS_ID_ANY, erret)); } size_t ASN_CMS_UnpackANYInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_ANY **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_ANY *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *asnstruct = NULL; if (buflen <= 0) return 0; local = ASN_CMS_NewANY(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceANY(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeANY(ctx, local); return 0; } *asnstruct = local; return bytesused; } /* ASN_CMS_UnpackANYInternal */ /*************************************************************************n* Routines for ASN_CMS_UTCTime *************************************************************************/ size_t ASN_CMS_PackUTCTime( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_UTCTime *timeblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_UTCTime, ASN_CMS_FALSE, 0, buf, buflen, timeblock, erret)); } size_t ASN_CMS_PackUTCTimeInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_UTCTime *timeblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, timeblock, erret)); } size_t ASN_CMS_UnpkInPlaceUTCTime( ASN_CMS_CONTEXT *ctx, ASN_CMS_UTCTime *timestruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) { return (UnpkInPlaceVariableBlock(ctx, tag, "UTCTime", 0x17, timestruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceUTCTime */ size_t ASN_CMS_UnpackUTCTime( ASN_CMS_CONTEXT *ctx, ASN_CMS_UTCTime **timestruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackUTCTimeInternal(ctx, timestruct, buf, buflen, ASN_CMS_ID_UTCTime, erret)); } size_t ASN_CMS_UnpackUTCTimeInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_UTCTime **timestruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_UTCTime *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (timestruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *timestruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewUTCTime(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceUTCTime(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeUTCTime(ctx, local); return 0; } *timestruct = local; return bytesused; } /* ASN_CMS_UnpackUTCTimeInternal */ /************************************************************************* * Routines for ASN_CMS_VisibleString *************************************************************************/ size_t ASN_CMS_PackVisibleString( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_VisibleString *strblock, int *erret) { return(PackVariableBlock(ctx, ASN_CMS_ID_VisibleString, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret)); } size_t ASN_CMS_PackVisibleStringInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_VisibleString *strblock, unsigned char tag, int *erret) { return(PackVariableBlock(ctx, tag, ASN_CMS_FALSE, 0, buf, buflen, strblock, erret)); } size_t ASN_CMS_UnpkInPlaceVisibleString( ASN_CMS_CONTEXT *ctx, ASN_CMS_VisibleString *strstruct, /* output block */ const unsigned char *buf, /* loc of input pointer */ size_t buflen, /* max end of my region */ unsigned char tag, int *erret) { return (UnpkInPlaceVariableBlock(ctx, tag, "VisibleString", 0x1a, strstruct, buf, buflen, erret)); } /* ASN_CMS_UnpkInPlaceVisibleString */ size_t ASN_CMS_UnpackVisibleString( ASN_CMS_CONTEXT *ctx, ASN_CMS_VisibleString **strstruct, const unsigned char *buf, size_t buflen, int *erret) { return(ASN_CMS_UnpackVisibleStringInternal(ctx, strstruct, buf, buflen, ASN_CMS_ID_VisibleString, erret)); } size_t ASN_CMS_UnpackVisibleStringInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_VisibleString **strstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) /* error return */ { size_t bytesused; ASN_CMS_VisibleString *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (strstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *strstruct = NULL; if (buflen <= 0) return 0; /* see note in UnpkInPlaceVariableBlock */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; local = ASN_CMS_NewVisibleString(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceVisibleString(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeVisibleString(ctx, local); return 0; } *strstruct = local; return bytesused; } /* ASN_CMS_UnpackVisibleStringInternal */ #ifdef ASN_CMS_TRACE #define ASN_CMS_TRACE_WIDTH 8 int ASN_CMS_TRACE_trval(enc, len, lev) const unsigned char *enc; int len; int lev; { int n; int i; int j; for (n = 0; n < len; n++) { if ((n % ASN_CMS_TRACE_WIDTH) == 0) { fprintf(stderr, "\n"); for (i=0; icrls), buf+bytesused, localsize-bytesused, 0x80 | 0x01, erret); if (bytesused > localsize || *erret != 0) break; if (indef) { if ( *(buf+bytesused) != 0x00 && *(buf+bytesused+1) != 0x00 ) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); break; } bytesused += 2; } } while(0); ASN_CMS_TRACE_DECR_LEVEL; if (bytesused > localsize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); if (!indef && bytesused < localsize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrUnpackUnderrun); return bytesused; } /* ASN_CMS_UnpkInPlaceOriginatorInfo */ size_t ASN_CMS_UnpackOriginatorInfoInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_OriginatorInfo **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused; ASN_CMS_OriginatorInfo *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *asnstruct = NULL; if (buflen <= 0) return 0; /* no bytes left */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; /* not correct tag */ local = ASN_CMS_NewOriginatorInfo(ctx); /* carve a block for it */ bytesused = ASN_CMS/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ #include #include #include #include "pgpASN_SMIME_asn.h" /******************************************************************* * * Code for internal routines * * DropInPlaceXXX: drops the contents of a block, in place * * _PackXXX: packs up a structure into an ASN.1 block * * UnpkInPlaceXXX: unpacks an ASN.1 block into a structure in place * * _unPackXXX: carves a structure block and unpacks into it * ******************************************************************/ /****************************************************************** * Routines for SMIMECapability ******************************************************************/ size_t ASN_CMS_SizeofSMIMECapabilityInternal( ASN_CMS_SMIMECapability *asnstruct, int outerSizeFlag, int expTaggedFlag) { size_t body_size = 0; if (asnstruct == NULL) return 0; body_size = ASN_CMS_SizeofOBJECT_IDInternal(&asnstruct->capabilityID, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofANYInternal(asnstruct->parameters, ASN_CMS_TRUE, ASN_CMS_FALSE) ; if (outerSizeFlag == ASN_CMS_TRUE) body_size = ASN_CMS_Tagged(body_size, 1); if (expTaggedFlag == ASN_CMS_TRUE) body_size = ASN_CMS_Tagged(body_size, 1); /* this is seq like */ return body_size; } /* ASN_CMS_SizeofSMIMECapabilityInternal */ void ASN_CMS_DropInPlaceSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *f) { if (ctx == NULL) return; if (f == NULL) return ; ASN_CMS_DropInPlaceOBJECT_ID(ctx, &(f->capabilityID)); ASN_CMS_FreeANY(ctx, f->parameters); f->parameters = NULL; } /* ASN_CMS_DropInPlaceSMIMECapability */ size_t ASN_CMS_PackSMIMECapabilityInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapability *asnstruct, unsigned char tag, int *erret) { size_t bytesused; size_t tagsize; size_t datasize; if (erret == NULL) return 0; /* can't report errors */ if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) return 0; /* lth of the block body */ datasize = ASN_CMS_SizeofSMIMECapability(ctx, asnstruct, ASN_CMS_FALSE); tagsize = 1 + ASN_CMS_LengthSize(datasize); if (datasize+tagsize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackBufferTooShort); return 0; } /* this is a SEQUENCE */ bytesused = ASN_CMS_PutTag(buf, (unsigned char)(tag|0x20), datasize); if (bytesused != tagsize) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return bytesused; } datasize += tagsize; do { /* field capabilityID of SMIMECapability */ bytesused += ASN_CMS_PackOBJECT_IDInternal(ctx, buf+bytesused, buflen-bytesused, &(asnstruct->capabilityID), ASN_CMS_ID_OBJECT_ID, erret); if (bytesused > datasize || *erret != 0) break; /* field parameters of SMIMECapability */ if (asnstruct->parameters != NULL) { /* optional */ bytesused += ASN_CMS_PackANYInternal(ctx, buf+bytesused, buflen-bytesused, asnstruct->parameters, ASN_CMS_ID_ANY, erret ); if (bytesused > datasize || *erret != 0) break; } } while(0); if (bytesused < datasize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrPackUnderrun) else if (bytesused > datasize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrPackOverrun) return bytesused; } /* ASN_CMS_PackSMIMECapabilityInternal */ size_t ASN_CMS_UnpkInPlaceSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused = 0; size_t datasize; size_t localsize; int indef = 0; ASN_CMS_TRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "SMIMECapability" ); if (erret == NULL) return 0; /* can't report errors */ *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; /* no error code, just no block */ if ( (*buf & 0x20) != 0x20) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } /* accept the tag byte */ bytesused++; /* get the block length */ bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if ((int)datasize == -1) { localsize = buflen; indef = 1; } else { localsize = bytesused + datasize; if (localsize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); return 0; } } ASN_CMS_TRACE_INCR_LEVEL; do { /* field capabilityID of SMIMECapability */ bytesused += ASN_CMS_UnpkInPlaceOBJECT_ID(ctx, &(asnstruct->capabilityID), buf+bytesused, localsize-bytesused, ASN_CMS_ID_OBJECT_ID, erret); if (bytesused > localsize || *erret != 0) break; /* field parameters of SMIMECapability */ if (!indef && bytesused >= localsize) { ASN_CMS_TRACE_DECR_LEVEL; return bytesused; } if (indef && *(buf+bytesused) == 0x00 && *(buf+bytesused+1) == 0x00) { ASN_CMS_TRACE_DECR_LEVEL; bytesused += 2; return bytesused; } if (asnstruct->parameters != NULL) ASN_CMS_FreeANY(ctx, asnstruct->parameters); bytesused += ASN_CMS_UnpackANYInternal(ctx, &(asnstruct->parameters), buf+bytesused, localsize-bytesused, ASN_CMS_ID_ANY, erret); if (bytesused > localsize || *erret != 0) break; if (indef) { if ( *(buf+bytesused) != 0x00 && *(buf+bytesused+1) != 0x00 ) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); break; } bytesused += 2; } } while(0); ASN_CMS_TRACE_DECR_LEVEL; if (bytesused > localsize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); if (!indef && bytesused < localsize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrUnpackUnderrun); return bytesused; } /* ASN_CMS_UnpkInPlaceSMIMECapability */ size_t ASN_CMS_UnpackSMIMECapabilityInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused; ASN_CMS_SMIMECapability *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *asnstruct = NULL; if (buflen <= 0) return 0; /* no bytes left */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; /* not correct tag */ local = ASN_CMS_NewSMIMECapability(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceSMIMECapability(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeSMIMECapability(ctx, local); return 0; } *asnstruct = local; return bytesused; } /* ASN_CMS_UnpackSMIMECapabilityInternal */ /****************************************************************** * Routines for SMIMEEncryptionKeyPreference ******************************************************************/ size_t ASN_CMS_SizeofSMIMEEncryptionKeyPreferenceInternal( ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, int outerSizeFlag, int expTaggedFlag) { size_t body_size = 0; if (asnstruct == NULL) return 0; switch (asnstruct->CHOICE_field_type) { case 0x80|0x00: case 0x80|0x20|0x00: body_size = ASN_CMS_SizeofIssuerAndSerialNumberInternal((ASN_CMS_IssuerAndSerialNumber *)(asnstruct->data), outerSizeFlag, expTaggedFlag); break; case 0x80|0x01: case 0x80|0x20|0x01: body_size = ASN_CMS_SizeofRecipientKeyIdentifierInternal((ASN_CMS_RecipientKeyIdentifier *)(asnstruct->data), outerSizeFlag, expTaggedFlag); break; case 0x80|0x02: case 0x80|0x20|0x02: body_size = ASN_CMS_SizeofSubjectKeyIdentifierInternal((ASN_CMS_SubjectKeyIdentifier *)(asnstruct->data), outerSizeFlag, expTaggedFlag); break; default: break; } /* switch */ return (body_size); } /* ASN_CMS_SizeofSMIMEEncryptionKeyPreferenceInternal */ void ASN_CMS_DropInPlaceSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *f) { if (ctx == NULL) return; if (f == NULL) return; switch(f->CHOICE_field_type) { case 0x80|0x00: case 0x80|0x20|0x00: ASN_CMS_FreeIssuerAndSerialNumber(ctx, (ASN_CMS_IssuerAndSerialNumber *)(f->data)); break; case 0x80|0x01: case 0x80|0x20|0x01: ASN_CMS_FreeRecipientKeyIdentifier(ctx, (ASN_CMS_RecipientKeyIdentifier *)(f->data)); break; case 0x80|0x02: case 0x80|0x20|0x02: ASN_CMS_FreeSubjectKeyIdentifier(ctx, (ASN_CMS_SubjectKeyIdentifier *)(f->data)); break; default: break; } /* switch */ } /* ASN_CMS_DropInPlaceSMIMEEncryptionKeyPreference */ size_t ASN_CMS_PackSMIMEEncryptionKeyPreferenceInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, unsigned char tag, int *erret) { size_t bytesused = 0; size_t datasize; (void)tag; /* unused */ if (erret == NULL) return 0; /* can't report errors */ if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) return 0; /* lth of the block body */ datasize = ASN_CMS_SizeofSMIMEEncryptionKeyPreference(ctx, asnstruct, ASN_CMS_TRUE); if (datasize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackBufferTooShort); return 0; } switch ( (asnstruct->CHOICE_field_type & 0xDF) ) { case 0x80|0x00: bytesused += ASN_CMS_PackIssuerAndSerialNumberInternal(ctx, buf+bytesused, buflen-bytesused, (ASN_CMS_IssuerAndSerialNumber *)(asnstruct->data), 0x80|0x00, erret); break; case 0x80|0x01: bytesused += ASN_CMS_PackRecipientKeyIdentifierInternal(ctx, buf+bytesused, buflen-bytesused, (ASN_CMS_RecipientKeyIdentifier *)(asnstruct->data), 0x80|0x01, erret); break; case 0x80|0x02: bytesused += ASN_CMS_PackSubjectKeyIdentifierInternal(ctx, buf+bytesused, buflen-bytesused, (ASN_CMS_SubjectKeyIdentifier *)(asnstruct->data), 0x80|0x02, erret); break; default: ASN_CMS_ERR( ASN_CMS_ErrChoiceBadType ); break; } /* switch */ if (bytesused < datasize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrPackUnderrun) else if (bytesused > datasize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrPackOverrun) return bytesused; } /* ASN_CMS_PackSMIMEEncryptionKeyPreferenceInternal */ size_t ASN_CMS_UnpkInPlaceSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct,/* output block */ const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { (void)tag; /* unused */ if (erret == NULL) return 0; /* can't report errors */ if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* no error -- no block */ switch (*buf) { /* issuerAndSerialNumber */ case 0x80|0x00: case 0x80|0x20|0x00: asnstruct->CHOICE_field_type = *buf; asnstruct->data = (void *)ASN_CMS_NewIssuerAndSerialNumber(ctx); if (asnstruct->data == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } return (ASN_CMS_UnpkInPlaceIssuerAndSerialNumber(ctx, (ASN_CMS_IssuerAndSerialNumber *)(asnstruct->data), buf, buflen, 0x80|0x00, erret)); /*NOTREACHED*/ break; /* receipentKeyId */ case 0x80|0x01: case 0x80|0x20|0x01: asnstruct->CHOICE_field_type = *buf; asnstruct->data = (void *)ASN_CMS_NewRecipientKeyIdentifier(ctx); if (asnstruct->data == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } return (ASN_CMS_UnpkInPlaceRecipientKeyIdentifier(ctx, (ASN_CMS_RecipientKeyIdentifier *)(asnstruct->data), buf, buflen, 0x80|0x01, erret)); /*NOTREACHED*/ break; /* subjectAltKeyIdentifier */ case 0x80|0x02: case 0x80|0x20|0x02: asnstruct->CHOICE_field_type = *buf; asnstruct->data = (void *)ASN_CMS_NewSubjectKeyIdentifier(ctx); if (asnstruct->data == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); return 0; } return (ASN_CMS_UnpkInPlaceSubjectKeyIdentifier(ctx, (ASN_CMS_SubjectKeyIdentifier *)(asnstruct->data), buf, buflen, 0x80|0x02, erret)); /*NOTREACHED*/ break; default: ASN_CMS_ERR(ASN_CMS_ErrChoiceBadType); return 0; } /* switch */ } /* ASN_CMS_UnpkInPlaceSMIMEEncryptionKeyPreference */ size_t ASN_CMS_UnpackSMIMEEncryptionKeyPreferenceInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused; ASN_CMS_SMIMEEncryptionKeyPreference *local = NULL ; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *asnstruct = NULL; if (buflen <= 0) return 0; /* no bytes left */ local = ASN_CMS_NewSMIMEEncryptionKeyPreference(ctx) ; /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceSMIMEEncryptionKeyPreference(ctx, local, buf, buflen, tag, erret); if (*erret == ASN_CMS_ErrChoiceBadType) { *erret = 0; if (local != NULL) ASN_CMS_FreeSMIMEEncryptionKeyPreference(ctx, local); return 0; } if (*erret != 0) { if (local != NULL) ASN_CMS_FreeSMIMEEncryptionKeyPreference(ctx, local); return 0; } *asnstruct = local; return bytesused; } /* ASN_CMS_UnpackSMIMEEncryptionKeyPreferenceInternal */ /****************************************************************** * Routines for SMIMECapabilities ******************************************************************/ size_t ASN_CMS_SizeofSMIMECapabilitiesInternal( ASN_CMS_SMIMECapabilities *asnstruct, int outerSizeFlag, int expTaggedFlag) { long i, lth; size_t body_size = 0; if (asnstruct == NULL) return 0; lth = asnstruct->n ; for (i=0; ielt)[i], ASN_CMS_TRUE, ASN_CMS_FALSE); if (outerSizeFlag == ASN_CMS_TRUE) body_size = ASN_CMS_Tagged(body_size, 1); if (expTaggedFlag == ASN_CMS_TRUE) body_size = ASN_CMS_Tagged(body_size, 1); /* this is seq like */ return body_size; } /* ASN_CMS_SizeofSMIMECapabilitiesInternal */ void ASN_CMS_DropInPlaceSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *f) { long i, lth; if (ctx == NULL) return; if (f == NULL) return; lth = f->n ; for (i=0;ielt)[i]); } ASN_CMS_Free(ctx->memMgr, f->elt); f->elt = (ASN_CMS_SMIMECapability **)0; f->n = 0; } /* ASN_CMS_DropInPlaceSMIMECapabilities */ size_t ASN_CMS_PackSMIMECapabilitiesInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapabilities *asnstruct, unsigned char tag, int *erret ) { size_t bytesused; size_t tagsize; size_t datasize; long numElem; int i; if (erret == NULL) return 0; /* can't report errors */ if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) return 0; numElem = asnstruct->n; /* lth of the block body */ datasize = ASN_CMS_SizeofSMIMECapabilities(ctx, asnstruct, ASN_CMS_FALSE); tagsize = 1 + ASN_CMS_LengthSize(datasize); if (datasize+tagsize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrPackBufferTooShort); return 0; } /* this is a SEQ_OF */ bytesused = ASN_CMS_PutTag(buf, (unsigned char)(tag|0x20), datasize); if (bytesused != tagsize) { ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return bytesused; } datasize += tagsize; for (i=0; ielt)[i], ASN_CMS_ID_SMIMECapability, erret); if (bytesused > datasize || *erret != 0) break; } if (bytesused < datasize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrPackUnderrun) else if (bytesused > datasize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrPackOverrun); return bytesused; } /* ASN_CMS_PackSMIMECapabilitiesInternal */ size_t ASN_CMS_UnpkInPlaceSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused = 0; size_t datasize; size_t localsize; int i ; int indef = 0; ASN_CMS_TRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE OF", "SMIMECapabilities"); if (erret == NULL) return 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } if (buf == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoBlockPtr); return 0; } if (buflen <= 0) return 0; /* out of bytes, no action */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; /* not my kind of block */ if ( (*buf & 0x20) != 0x20) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); return 0; } bytesused ++; /* consume the tag byte */ ASN_CMS_TRACE_INCR_LEVEL; bytesused += ASN_CMS_GetLength(buf+bytesused, &datasize); if ((int)datasize == -1) { localsize = buflen; indef = 1; } else { localsize = bytesused + datasize; if (localsize > buflen) { ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); asnstruct->n = -1 ; /* note where (-1 treated as 0) */ ASN_CMS_TRACE_DECR_LEVEL; return 0; } } for (i=0; (bytesused < localsize); i++) { /* if this is indef length and we have EOC, done */ if (indef && *(buf+bytesused) == 0x00 && *(buf+bytesused+1) == 0x00 ) break; ASN_CMS_Realloc(ctx->memMgr, (void **)&(asnstruct->elt), (i+1)*sizeof(ASN_CMS_SMIMECapability *)); if (asnstruct->elt == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); break; } asnstruct->elt[i] = ASN_CMS_NewSMIMECapability(ctx); if (asnstruct->elt[i] == NULL) { ASN_CMS_ERR(ASN_CMS_ErrOutOfMemory); break; } asnstruct->n = i+1 ; /* note the new element */ bytesused += ASN_CMS_UnpkInPlaceSMIMECapability(ctx, asnstruct->elt[i], buf+bytesused, localsize-bytesused, ASN_CMS_ID_SMIMECapability, erret); if (*erret != 0) break; } /* for */ if (indef) { if ( *(buf+bytesused) != 0x00 && *(buf+bytesused+1) != 0x00 ) { ASN_CMS_ERR(ASN_CMS_ErrUnpackInvalidEncoding); } else bytesused += 2; } ASN_CMS_TRACE_DECR_LEVEL; if (bytesused > localsize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrUnpackOverrun); if (!indef && bytesused < localsize && *erret == 0) ASN_CMS_ERR(ASN_CMS_ErrUnpackUnderrun); return bytesused; } /* ASN_CMS_UnpkInPlaceSMIMECapabilities */ size_t ASN_CMS_UnpackSMIMECapabilitiesInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused; ASN_CMS_SMIMECapabilities *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *asnstruct = NULL; if (buflen <= 0) return 0; /* no bytes left */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; /* not correct tag */ local = ASN_CMS_NewSMIMECapabilities(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceSMIMECapabilities(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeSMIMECapabilities(ctx, local); return 0; } *asnstruct = local; return bytesused; } /* ASN_CMS_UnpackSMIMECapabilitiesInternal */ size_t ASN_CMS_UnpackAuthenticatedDataInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_AuthenticatedData **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused; ASN_CMS_AuthenticatedData *local = NULL; if (erret == NULL) return 0; *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrBadContext); return 0; } if (asnstruct == NULL) { ASN_CMS_ERR(ASN_CMS_ErrUnpackNoStructure); return 0; } *asnstruct = NULL; if (buflen <= 0) return 0; /* no bytes left */ if ( (*buf & 0xDF) != (tag & 0xDF) ) return 0; /* not correct tag */ local = ASN_CMS_NewAuthenticatedData(ctx); /* carve a block for it */ bytesused = ASN_CMS_UnpkInPlaceAuthenticatedData(ctx, local, buf, buflen, tag, erret); if (*erret != 0) { if (local != NULL) ASN_CMS_FreeAuthenticatedData(ctx, local); return 0; } *asnstruct = local; return bytesused; } /* ASN_CMS_UnpackAuthenticatedDataInternal */ /****************************************************************** * Routines for EnvelopedData ******************************************************************/ size_t ASN_CMS_SizeofEnvelopedDataInternal( ASN_CMS_EnvelopedData *asnstruct, int outerSizeFlag, int expTaggedFlag) { size_t body_size = 0; if (asnstruct == NULL) return 0; body_size = ASN_CMS_SizeofCMSVersionInternal(&asnstruct->version, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofOriginatorInfoInternal(asnstruct->originatorInfo, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofRecipientInfosInternal(&asnstruct->recipientInfos, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofEncryptedContentInfoInternal(&asnstruct->encryptedContentInfo, ASN_CMS_TRUE, ASN_CMS_FALSE) + ASN_CMS_SizeofUnprotectedAttributesInternal(asnstruct->unprotectedAttrs, ASN_CMS_TRUE, ASN_CMS_FALSE) ; if (outerSizeFlag == ASN_CMS_TRUE) body_size = AS/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ #ifndef pgpASN_SMIME_H_ #define pgpASN_SMIME_H_ #include "pgpASN_SMIME_struct.h" /******************************************************************* * * Function declarations for internal functions * ******************************************************************/ size_t ASN_CMS_SizeofSMIMECapabilityInternal( ASN_CMS_SMIMECapability *asnstruct, int outerSizeFlag, int expTaggedFlag); void ASN_CMS_DropInPlaceSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *f); size_t ASN_CMS_PackSMIMECapabilityInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapability *asnstruct, unsigned char tag, int *erret); size_t ASN_CMS_UnpkInPlaceSMIMECapability ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret); size_t ASN_CMS_UnpackSMIMECapabilityInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret); size_t ASN_CMS_SizeofSMIMEEncryptionKeyPreferenceInternal( ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, int outerSizeFlag, int expTaggedFlag); void ASN_CMS_DropInPlaceSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *f); size_t ASN_CMS_PackSMIMEEncryptionKeyPreferenceInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, unsigned char tag, int *erret); size_t ASN_CMS_UnpkInPlaceSMIMEEncryptionKeyPreference ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret); size_t ASN_CMS_UnpackSMIMEEncryptionKeyPreferenceInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret); size_t ASN_CMS_SizeofSMIMECapabilitiesInternal( ASN_CMS_SMIMECapabilities *asnstruct, int outerSizeFlag, int expTaggedFlag); void ASN_CMS_DropInPlaceSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *f); size_t ASN_CMS_PackSMIMECapabilitiesInternal( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapabilities *asnstruct, unsigned char tag, int *erret); size_t ASN_CMS_UnpkInPlaceSMIMECapabilities ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret); size_t ASN_CMS_UnpackSMIMECapabilitiesInternal( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities **asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret); #endif /* pgpASN_SMIME_H_ */ pedDataInternal */ size_t ASN_CMS_UnpkInPlaceEnvelopedData( ASN_CMS_CONTEXT *ctx, ASN_CMS_EnvelopedData *asnstruct, const unsigned char *buf, size_t buflen, unsigned char tag, int *erret) { size_t bytesused = 0; size_t datasize; size_t localsize; int indef = 0; ASN_CMS_TRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "EnvelopedData" ); if (erret == NULL) return 0; /* can't report errors */ *erret = 0; if (ctx == NULL) { ASN_CMS_ERR(ASN_CMS_ErrB/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ #include #include "pgpASN_SMIME_asn.h" /******************************************************************* * * Code for manipulating ASN.1 DER data and structure. * * NewXXX: Allocate the top level of a structure. * * FreeXXX: Release all the data of an ASN structure. * * SizeofXXX: Return the size of the DER block that would * be created from the structure. * * PackXXX: Take an ASN structure and return the DER. * * unPackXXX: Take the DER and return an ASN structure. * ******************************************************************/ /****************************************************************** * Routines for SMIMECapability ******************************************************************/ ASN_CMS_SMIMECapability *ASN_CMS_NewSMIMECapability( ASN_CMS_CONTEXT *ctx) { ASN_CMS_SMIMECapability *f; if (ctx == NULL) return NULL; f = (ASN_CMS_SMIMECapability *)ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_SMIMECapability)); if (f != NULL) (void)memset(f, 0, sizeof(ASN_CMS_SMIMECapability)); return (f); } /* ASN_CMS_NewSMIMECapability */ void ASN_CMS_FreeSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *f) { if (ctx == NULL) return; ASN_CMS_DropInPlaceSMIMECapability(ctx, f); if (f != NULL) ASN_CMS_Free(ctx->memMgr, f); } /* ASN_CMS_FreeSMIMECapability */ size_t ASN_CMS_SizeofSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *asnstruct, int outerSizeFlag) { (void)ctx; /* for future use */ return(ASN_CMS_SizeofSMIMECapabilityInternal(asnstruct, outerSizeFlag, ASN_CMS_FALSE)); } /* ASN_CMS_SizeofSMIMECapability */ size_t ASN_CMS_PackSMIMECapability( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapability *asnstruct, int *erret ) { return(ASN_CMS_PackSMIMECapabilityInternal(ctx, buf, buflen, asnstruct, ASN_CMS_ID_SMIMECapability, erret)); } /* ASN_CMS_PackSMIMECapability */ size_t ASN_CMS_UnpackSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability **asnstruct, const unsigned char *buf, size_t buflen, int *erret) { size_t bytesused; bytesused=ASN_CMS_UnpackSMIMECapabilityInternal(ctx, asnstruct, buf, buflen, ASN_CMS_ID_SMIMECapability, erret); if(*erret==0 && bytesused==0) ASN_CMS_ERR(ASN_CMS_ErrUnpackUnderrun); return bytesused; } /****************************************************************** * Routines for SMIMEEncryptionKeyPreference ******************************************************************/ ASN_CMS_SMIMEEncryptionKeyPreference *ASN_CMS_NewSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx) { ASN_CMS_SMIMEEncryptionKeyPreference *f; if (ctx == NULL) return NULL; f = (ASN_CMS_SMIMEEncryptionKeyPreference *)ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_SMIMEEncryptionKeyPreference)); if (f != NULL) (void)memset(f, 0, sizeof(ASN_CMS_SMIMEEncryptionKeyPreference)); return (f); } /* ASN_CMS_NewSMIMEEncryptionKeyPreference */ void ASN_CMS_FreeSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *f) { if (ctx == NULL) return; ASN_CMS_DropInPlaceSMIMEEncryptionKeyPreference(ctx, f); if (f != NULL) ASN_CMS_Free(ctx->memMgr, f); } /* ASN_CMS_FreeSMIMEEncryptionKeyPreference */ size_t ASN_CMS_SizeofSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, int outerSizeFlag) { (void)ctx; /* for future use */ return(ASN_CMS_SizeofSMIMEEncryptionKeyPreferenceInternal(asnstruct, outerSizeFlag, ASN_CMS_FALSE)); } /* ASN_CMS_SizeofSMIMEEncryptionKeyPreference */ size_t ASN_CMS_PackSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, int *erret ) { return(ASN_CMS_PackSMIMEEncryptionKeyPreferenceInternal(ctx, buf, buflen, asnstruct, ASN_CMS_ID_SMIMEEncryptionKeyPreference, erret)); } /* ASN_CMS_PackSMIMEEncryptionKeyPreference */ size_t ASN_CMS_UnpackSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference **asnstruct, const unsigned char *buf, size_t buflen, int *erret) { size_t bytesused; bytesused=ASN_CMS_UnpackSMIMEEncryptionKeyPreferenceInternal(ctx, asnstruct, buf, buflen, ASN_CMS_ID_SMIMEEncryptionKeyPreference, erret); if(*erret==0 && bytesused==0) ASN_CMS_ERR(ASN_CMS_ErrUnpackUnderrun); return bytesused; } /****************************************************************** * Routines for SMIMECapabilities ******************************************************************/ ASN_CMS_SMIMECapabilities *ASN_CMS_NewSMIMECapabilities( ASN_CMS_CONTEXT *ctx) { ASN_CMS_SMIMECapabilities *f; if (ctx == NULL) return NULL; f = (ASN_CMS_SMIMECapabilities *)ASN_CMS_Alloc(ctx->memMgr, sizeof(ASN_CMS_SMIMECapabilities)); if (f != NULL) (void)memset(f, 0, sizeof(ASN_CMS_SMIMECapabilities)); return (f); } /* ASN_CMS_NewSMIMECapabilities */ void ASN_CMS_FreeSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *f) { if (ctx == NULL) return; ASN_CMS_DropInPlaceSMIMECapabilities(ctx, f); if (f != NULL) ASN_CMS_Free(ctx->memMgr, f); } /* ASN_CMS_FreeSMIMECapabilities */ size_t ASN_CMS_SizeofSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *asnstruct, int outerSizeFlag) { (void)ctx; /* for future use */ return(ASN_CMS_SizeofSMIMECapabilitiesInternal(asnstruct, outerSizeFlag, ASN_CMS_FALSE)); } /* ASN_CMS_SizeofSMIMECapabilities */ size_t ASN_CMS_PackSMIMECapabilities( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapabilities *asnstruct, int *erret ) { return(ASN_CMS_PackSMIMECapabilitiesInternal(ctx, buf, buflen, asnstruct, ASN_CMS_ID_SMIMECapabilities, erret)); } /* ASN_CMS_PackSMIMECapabilities */ size_t ASN_CMS_UnpackSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities **asnstruct, const unsigned char *buf, size_t buflen, int *erret) { size_t bytesused; bytesused=ASN_CMS_UnpackSMIMECapabilitiesInternal(ctx, asnstruct, buf, buflen, ASN_CMS_ID_SMIMECapabilities, erret); if(*erret==0 && bytesused==0) ASN_CMS_ERR(ASN_CMS_ErrUnpackUnderrun); return bytesused; } [7R`G":sAN̤icDٓ yt*&=iIt+Fot875v_g]`֕U q4|}'ߝO'IIQvC# TRH_28;() 7$ ֶ,ڤ3&yhF*imh\O3cҲx!#J!?MkZBߪH&3PΕ._}'4w8֚ =>Xn uqܼc?:?}n#&}sqSǯ4dJM#oĤRde?87x L@_9 qoҁg0M_yY|QA$I7Z5Y 3$K_!*=Āk< nC[2'n2 1UmMf1uhď1Ieqe7nb¨I$ndwXMPO?98Ewg(9nhm0 nUҩ>4۲I zڅ{/Y,:F&*IϬ}H 32cʕ}Q%HYdiR"`02?j^vÝ5+V|>y5ܜ'A<0f2:!Ƣ܄ 1Aw1,ntED 8Rʰ S%BI~_LYl%R ^4.[`<>/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ /******************************************************************* * * .h file to declare ASN.1 functions * ******************************************************************/ #ifndef pgpASN_SMIME_ASN_H_ #define pgpASN_SMIME_ASN_H_ #include #include "pgpASN_SMIME.h" /******************************************************************* * * Function declarations * ******************************************************************/ ASN_CMS_SMIMECapability *ASN_CMS_NewSMIMECapability( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *f); size_t ASN_CMS_SizeofSMIMECapability ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSMIMECapability( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapability *asnstruct, int *erret); size_t ASN_CMS_UnpackSMIMECapability( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapability **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_SMIMEEncryptionKeyPreference *ASN_CMS_NewSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *f); size_t ASN_CMS_SizeofSMIMEEncryptionKeyPreference ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMEEncryptionKeyPreference *asnstruct, int *erret); size_t ASN_CMS_UnpackSMIMEEncryptionKeyPreference( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMEEncryptionKeyPreference **asnstruct, const unsigned char *buf, size_t buflen, int *erret); ASN_CMS_SMIMECapabilities *ASN_CMS_NewSMIMECapabilities( ASN_CMS_CONTEXT *ctx); void ASN_CMS_FreeSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *f); size_t ASN_CMS_SizeofSMIMECapabilities ( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities *asnstruct, int outerSizeFlag); size_t ASN_CMS_PackSMIMECapabilities( ASN_CMS_CONTEXT *ctx, unsigned char *buf, size_t buflen, ASN_CMS_SMIMECapabilities *asnstruct, int *erret); size_t ASN_CMS_UnpackSMIMECapabilities( ASN_CMS_CONTEXT *ctx, ASN_CMS_SMIMECapabilities **asnstruct, const unsigned char *buf, size_t buflen, int *erret); #endif /* pgpASN_SMIME_ASN_H_ */  =3' ]c5SmTE%R.Oe%*^VOˉu{Tr8D mUX@3ImQ }*E ƒ7o( S?F1~UJC2G޳]ť& 1s5}ͷ.[̄@"n.;spJ#%m. @*K]d9;ɸAЏz7 bX?E)u{g$ai|!8 tU+k.jۘ@~=hG0w1h7G#s-. 3fZoxąa4Ͱ m*R1s?ZMb#=dji Wb`/z{,& |`7;%|J {쁺Dr1 A-n9#j֦Y81҅[Kn7$Lj"X!Fwx锞;9<}7>˥H,D?"Gҩj1a0d}sQEُ#.X_ t`pdh}ղqGPͷz>q`Kx~$K+̵bPϐ0<3Se>€x6Č [;2`[`PO[ヌzja5l z% ԟ]aP%&hcp6_~tLt#k)P6SK^*֠b>B`Qy3j$8B0d #/u(k7C(Q_#'⽜}fCsI;X+/i3K~v?=6͛F&f?9yu̼xP%ǖ86>J/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ /****************************************************************** * * Defines for OIDs * *******************************************************************/ #ifndef _pgpASN_SMIME_oid_H_ #define _pgpASN_SMIME_oid_H_ extern unsigned char ASN_CMS_id_aa_OID[]; #define ASN_CMS_id_aa_OID_LEN 10 extern unsigned char ASN_CMS_smimeCapabilities_OID[]; #define ASN_CMS_smimeCapabilities_OID_LEN 9 extern unsigned char ASN_CMS_id_aa_encrypKeyPref_OID[]; #define ASN_CMS_id_aa_encrypKeyPref_OID_LEN 11 extern unsigned char ASN_CMS_sha_1WithRSAEncryption_OID[]; #define ASN_CMS_sha_1WithRSAEncryption_OID_LEN 9 #endif /* _pgpASN_SMIME_H_*/ yption: 1.2.840.113549.1.1.5 */ unsigned char ASN_CMS_sha_1WithRSAEncryption_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 }; o{ld%޴?&P,y2IJ1A"%ىKEH@YS QetFu>w&RN:# ]t=+WiUUL *c2iQ6GOΚbܰҏW&QBXqw9n'p6,*œ\$D}sZZ–1X]Ai`'KwjjvLgi]oP dl*R|a+?P[|^X9nXtgY6̌)W-qD OLOQXUHWg}IrX@ m=VDZ HT[o$0S0}2m0p `Ȧ,Ȃ`-Tci7m|Xݘ帞8N7Zw(@kmij f^Iv$H/8}/ Kfߎ;9zsiy?D{6Dr)`X+%܁au}¹q&(њ0VTFI ?m HW 6ϥ)Ųx|h89pΥ0(}tsn+9c%xi˭sH 3NGցm,I `N='3HLzp;9Gufw? IRo͢d94SBU#N-XAv gҗj6w~ydIIʒH"goճS49TWEx3ߢH~sҋ`2K|Ai({M7 I.@//gf+ewl}bVdu ԣ$\fwSnQ@s˴E+(.OϟΥ̦b U(y$+eLUɒLq)լq@j.(PO˕.{*G8*X7+ې.)"zG9f!f:~.;'78rmC~V*.Iǿ*VApښZmA|gȑ cy~i$)]$jO7_YU%nEOb $tڌ39ueH4֭lvzBBtn:I*l)<pI4 Y$ȑ<ԧB"5Er9A$ޚݝ +=2f=P\ RG&#rpJl|@]^Ț@u [V~Q-*eEۡ s~[c,%z֎ˬv ϐ 9c&1%Aimx1%q@H'NoG`F9`t㖻isn-STW;u"FH?(aڡQ?ߕn"PN.n@9o (5TmZr>ޱDa0j(#m𩟱笇T j-Db{<_wvgG?._*8 hz5{I;vUPs2b@(\ I/cq_xrO@@#?t#f>9oi0 l'>Om;H#YWUm }KH}Of~8&'o}$)i $yƵ5R|Bȸ.1kRG0wV;8_޵Mj+R gX= |z^wG3$ UjX>fjQl K癨Ql)>6cl/@B FLO2{%20ltS3@@vuΔݡmkԄ/Oƕy%1q#<>! ݽ6 n0&(M^!/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ /****************************************************************** * * Declarations of OIDs * *******************************************************************/ /* id_aa: 1.2.840.113549.1.9.16.2 */ unsigned char ASN_CMS_id_aa_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02 }; /* smimeCapabilities: 1.2.840.113549.1.9.15 */ unsigned char ASN_CMS_smimeCapabilities_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0f }; /* id_aa_encrypKeyPref: 1.2.840.113549.1.9.16.2.11 */ unsigned char ASN_CMS_id_aa_encrypKeyPref_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0b }; /* sha_1WithRSAEncryption: 1.2.840.113549.1.1.5 */ unsigned char ASN_CMS_sha_1WithRSAEncryption_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05 }; c[kmwldzS_p>QT6*X"Q(BT]izՔX"Z02jj~l_^چnu1<뎵#p ;=ŋKj`.'QD/vrP>DO0uo 91 Tn V6o+%sK=E]Kl0(@'/ފ-m! ycL |3e7@ (+JMA2c<< I5Qi N#Ϊ-_ ~jŠ7%IJd$q?!7.xLfk6xUI&k:MڿI/s}6!g;Tr^vVulG"ze՞ ^&Z  $7BBB~OY~ us1bݻ|*&?8Pp&mDTP4R q* sh\*i bМ*5lHh1n>6U=GW؛z)R> W#jXC8$gYljp X%T3`MxEvU؋p@ ϗZ#"i[}1dNnvwMŸucmL _Z{SzƻC7KDjqq-S(K64 )HR + Q[XXfژ;@3"{=Iۨ |(AĐ7 rf@LſyP յ^+yu=ھ[06@'hP@zzV5lA˙e~턳-!cw,ϟʅ,9ب" XCG{&ʈtK%(f `yP 8HP۷۸?@PEH/b-k!!GDC~_\8 U' 9ݕ{mBHpg>/dYFn\,Lr|5s'% O3 \(V8VX@/֝Vڻ1#h6yN-6\ G\^]uk:2Db|9Gj%RA%D eIJB /q!7_-6VDy=/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ #ifndef pgpASN_SMIME_STRUCT_H_ #define pgpASN_SMIME_STRUCT_H_ #include "pgpASN_CMS_asn.h" /******************************************************************* * * Structure and type definitions * ******************************************************************/ typedef struct { ASN_CMS_OBJECT_ID capabilityID; ASN_CMS_ANY *parameters; } ASN_CMS_SMIMECapability; #define ASN_CMS_ID_SMIMECapability ASN_CMS_ID_SEQUENCE typedef struct { unsigned char CHOICE_field_type; void *data; } ASN_CMS_SMIMEEncryptionKeyPreference; #define ASN_CMS_ID_SMIMEEncryptionKeyPreference ASN_CMS_ID_CHOICE /* tags for fields defined for SMIMEEncryptionKeyPreference */ #define ASN_CMS_issuerAndSerialNumber_SMIMEEncryptionKeyPreferenceFieldTag 0x80|0x00 #define ASN_CMS_receipentKeyId_SMIMEEncryptionKeyPreferenceFieldTag 0x80|0x01 #define ASN_CMS_subjectAltKeyIdentifier_SMIMEEncryptionKeyPreferenceFieldTag 0x80|0x02 typedef struct { long n; /* number of elements */ ASN_CMS_SMIMECapability **elt; } ASN_CMS_SMIMECapabilities; #define ASN_CMS_ID_SMIMECapabilities ASN_CMS_ID_SEQUENCE_OF #endif /* pgpASN_SMIME_STRUCT_H_ */ `QJ`9 RvkE8bbp9?ޣďś<]RaV8 zX#="tS;W`qػ 7C)X3#+{CjXn_Q4Y`I& HGÈ7H`1qE=۠H;ܶt\#[np113f؞5af`O΄ H m 5$}饨bJ]Cmm4NrR !ˁGn*k=^\3q-+`zXeQCG&kBǡ$֘$-C3zzj4 At"b=%H}i/oB.YG&01IrLN^ TUmGx|^tVᠲyMo+PGꉓX\層Uf$r.B"c4$ĦE؂E 7xv1Wvza?) O(ҟ9L16(" yOiP~'܁j\+ @g9ߩSӖ"Y?(51]\ti(3$T[i ;q<iv1d}'QNn?:n(q@'~iIڛ{u3qH81ΖDUS'q9?zIEnAMi_FPFekE÷w?8PnEFK@aA3>x 3\qig>N36F>E[e !R >&V0 Zq2I"][mpI'@`]٢K.e+"`E O~Wm )!^eGA1{`ZRbP>y\W&==";\2Xl'4펄w--m(9=͈$yӕݦ@R Y>366.K+ooe.v]r~~x xr29,{=y":)4ѳq܅xD~tr|bL%.G2w6Ē~tH3]dLcLK4dhக R DLAz-bõݕHDLёJo;}LyS1XlN' š U}7.)V iygScl];#>. DH#@Rs]O,u#h3 wEt9RW' 1C*+EV\]{/FBx;UZ$ɓɊfKiZ6}g)]٢IPQĞIS`5ie[j.}7*6BD OhI D3RTڻT~B=ïm@ed憒^`X,?-I(N٘Ӝ Lvx۪$S!9*nڐȔ"<%=yWYh@uJrБhn!ZVzhF ٝٹB%e]'=M,{Sm<3SI\D1L iT\Ac̴I!-ݬ'qaw<Ñ3 yGxv0 .,iJ>ι[Kn tzSb qB}Lڥ!=BJ%y@}0 ˷a$^(CZr Qˊrw 2'=He(%hXI]82$zVK. `Z=SkGs@ ,QwH@>*иǸg& pl)o` AvËi3p-q9?vr*I 1>U?ʸĄ9s]jhR8QQCJXǰv%)4l0Z峞۴B<껱l!sjB&@,i9i8!˻>n#gA]`Z[فwKJF<$tf_ g:SWCc;VXp V2!!' VklXNWaX=EV Hj5qil%&q̟/J pbΒ.Ap<ƛI3yi>6 җ!n-DyL-C/v+6Wo#? {F/******************************************************************* * * This file was generated by TIS/ASN1COMP Ver. 4.3 (mod 7), an ASN.1 compiler. * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc. * * This file was AUTOMATICALLY GENERATED on Tue May 13 17:29:00 2003 * ******************************************************************/ /****************************************************************** * * Defines for OIDs * *******************************************************************/ #ifndef _pgpASN_SMIME_oid_H_ #define _pgpASN_SMIME_oid_H_ extern unsigned char ASN_CMS_id_aa_OID[]; #define ASN_CMS_id_aa_OID_LEN 10 extern unsigned char ASN_CMS_smimeCapabilities_OID[]; #define ASN_CMS_smimeCapabilities_OID_LEN 9 extern unsigned char ASN_CMS_id_aa_encrypKeyPref_OID[]; #define ASN_CMS_id_aa_encrypKeyPref_OID_LEN 11 extern unsigned char ASN_CMS_sha_1WithRSAEncryption_OID[]; #define ASN_CMS_sha_1WithRSAEncryption_OID_LEN 9 #endif /* _pgpASN_SMIME_H_*/ c~`Q¯U2ܮgOfV0cyZd褰 62zn/.)r9|F6_a*`uHJPBZɻ @XSb3po`#j5nݹ0Gʃ8dV61BCjnIRy"OQK]\s) |.T:= H=ت%D5@ Rr'_/ mcV=pWҋ̦}+sq;z[?hM"2A&(AoYч렳I H'ʖ!EEJ),7(,C6F֝a9*qS>i$&UmnQu6i 626L/ p}!\P63Dhxd"j;$ Rf4|5|N$ 5Di5v4 umLɁ9[cq.Mp{I ˆvAٍ(h\0 ǜ1Kɗ- lź%'(; M݊&u*.kCDIE5SU$vD W3MzvA #Xs5B[O@STxEIR֠ M/~jԲm@̡"rR7Ĺ<@Vm8keь#(}'=EՏC(H mE(,"L֡6e9cj~D@LOںݴ1TN |xrN\;{G{GlwkRKr'Sgyԝ0yy2C^]nʵ͈Ԓy QNNʃQ-I<.Uϔ-SBT@ݶ\%ʵ_kx^'}Ct Fٖ9_?Nh-]um_vAr ' $~Ob.$nie}ke83봷ҊdeC1G⯰({0|>S"nJeˮjӜwokV\UXcB%ĭ,pq (D퍞i|,2*[A i6T T]Bz AʰzA51 m6Fŀ0Z2}v4:clxq&UŴ2AZ6~$@QeJJs-e *KkgxoIjʀTs@ݖ{[gbGeu?ā'ZjH&s95n.`LUp9=Ĵ̛9qYLꦪ o-WUunӾTDr(E,bxYQPBcNA $Iojx#K3 U76"= Y7;لO,ᾔ;QJ‰&.Av>~F[pUu;7?ֶ+I 6Fd\a "A s31 j cvz ėu!7[P3oq5A1߭Zo@`>RMv/ҡfGCKZM%ޟB%'7]H֓XcqX<xdH&{I{bnH#2&|^~m;:QQ^1yD/&MJ=V*9H7杻$3lWn$bnݶJx|%?UbPE7ROf<\C[Y`,awGRhkv۩dοQqQf$YqxRKT@b# # priv/smime/ # # $Id: Makefile.in,v 1.4 2003/06/02 21:41:52 ajivsov Exp $ # ASN1CC=../../../../../misc/asn1comp/src/asn1compile OBJS= pgpSMIME.o pgpSMIMEasn.o \ pgpSMIMEasnVerify.o pgpSMIMEcmsVerify.o \ pgpSMIMEasnDecrypt.o pgpSMIMEcmsDecrypt.o \ pgpSMIMEasnSign.o pgpSMIMEcmsSign.o \ pgpSMIMEasnEncrypt.o pgpSMIMEcmsEncrypt.o \ ASN/pgpASN_CMS_asn.o ASN/pgpASN_CMS.o ASN/pgpASN_CMS_oid.o ASN/pgpASN_CMS_util.o \ ASN/pgpASN_SMIME_asn.o ASN/pgpASN_SMIME.o ASN/pgpASN_SMIME_oid.o PRIVHDRS= pgpSMIME.h LOCALINCLUDES = -I ASN # LOCALDEFINES = PKITRACE=1 # LOCALDEFINES = -D SMIME_TEST=1 -D PGP_USE_TRACE=1 # Enable the following line to invoke ASN.1 compiler # pgpSMIME.o: pgpSMIME.c ASN/CMS_DONE ASN/SMIME_DONE ASN/CMS_DONE: CMS.asn if [ ! -d ASN ]; then mkdir -v ASN; fi cd ASN; $(ASN1CC) -A ASN_CMS_ -p pgpASN_CMS ../CMS.asn touch ASN/CMS_DONE ASN/SMIME_DONE: SMIME.asn if [ ! -d ASN ]; then mkdir -v ASN; fi cd ASN; $(ASN1CC) -A ASN_CMS_ -p pgpASN_SMIME -e pgpASN_CMS ../SMIME.asn # find ASN -name pgpASN_SMIME* -exec perl changeSMIMEids.pl {} \; touch ASN/SMIME_DONE all:: DONE deepclean: clean rm -Rf ASN e could replace this definition by this: Name ::= RDNSequence -- to simplify a code generated by compiler (yes, our compiler is not smart enough -- to handle a single-element CHOICE). -- However, it is actually easier to work with unparsed Name. We use it only for -- matching, so DER of RDNSequence is more convenient. Name-opaque ::= ANY RDNSequence ::= SEQUENCE OF RelativeDistinguishedName RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndDistinguishedValue AttributeType ::= OBJECT IDENTIFIER AttributeTypeAndDistinguishedValue ::= SEQUENCE { type AttributeType, value AttributeValue } -- Cryptographic Message Syntax -- the starting point ContentInfo ::= --snacc isPdu:"TRUE" -- SEQUENCE { contentType ContentType, content [0] EXPLICIT ANY DEFINED BY contentType } ContentType ::= OBJECT IDENTIFIER -- top level, used in ContentInfo.content for signed data SignedData ::= SEQUENCE { version CMSVersion, -- redundant information present also in signerInfos digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncapsulatedContentInfo, certificates [0] IMPLICIT CertificateSet OPTIONAL, crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, signerInfos SignerInfos } DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier SignerInfos ::= SET OF SignerInfo EncapsulatedContentInfo ::= SEQUENCE { eContentType ContentType, -- eContent is absent for multipart/signed eContent [0] EXPLICIT OCTET STRING OPTIONAL } SignerInfo ::= SEQUENCE { version CMSVersion, sid SignerIdentifier, digestAlgorithm DigestAlgorithmIdentifier, -- mandatory for any contentType except id-data -- has at least id-messageDigest signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, signatureAlgorithm SignatureAlgorithmIdentifier, signature SignatureValue, unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } SignerIdentifier ::= CHOICE { issuerAndSerialNumber IssuerAndSerialNumber, subjectKeyIdentifier [0] SubjectKeyIdentifier } SignedAttributes ::= SET SIZE (1..MAX) OF Attribute UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute Attribute ::= SEQUENCE { attrType OBJECT IDENTIFIER, attrValues SET OF AttributeValue } AttributeValue ::= ANY SignatureValue ::= OCTET STRING -- top level, used in ContentInfo.content for encrypted data EnvelopedData ::= SEQUENCE { version CMSVersion, originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, recipientInfos RecipientInfos, encryptedContentInfo EncryptedContentInfo, unprotectedAttrs [1] IMPLICIT -- (c) 2003 PGP Corporation -- -- taken from RFC 2630 with additions from PKCS7 and X.509 to make this module self-contained -- few changed to make some types opaque (new types have form *-opaque) -- added EXPLICIT tags to make asn1comp work CryptographicMessageSyntax { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) modules(0) cms(1) } DEFINITIONS IMPLICIT TAGS ::= BEGIN -- EXPORTS All -- The types and values defined in this module are exported for use in -- the other ASN.1 modules. Other applications may use them for their -- own purposes. --IMPORTS -- Directory Information Framework (X.501) -- Name -- FROM InformationFramework { joint-iso-itu-t ds(5) modules(1) -- informationFramework(1) 3 } -- Directory Authentication Framework (X.509) -- AttributeCertificate, Certificate, -- CertificateSerialNumber -- FROM AuthenticationFramework { joint-iso-itu-t ds(5) -- module(1) authenticationFramework(7) 3 } ; -- pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us (840) rsadsi (113549) 1 } pkcs-1 OBJECT IDENTIFIER ::= { pkcs 1 } pkcs-3 OBJECT IDENTIFIER ::= { pkcs 3 } pkcs-7 OBJECT IDENTIFIER ::= { pkcs 7 } pkcs-9 OBJECT IDENTIFIER ::= { pkcs 9 } dhKeyAgreement OBJECT IDENTIFIER ::= { pkcs-3 1 } -- naming data types -- original Name is defined as a CHOICE bellow: -- Name ::= CHOICE { -- only one possibility for now -- -- rdnSequence RDNSequence --} -- but since there is only one choice we could replace this definition by this: Name ::= RDNSequence -- to simplify a code generated by compiler (yes, our compiler is not smart enough -- to handle a single-element CHOICE). -- However, it is actually easier to work with unparsed Name. We use it only for -- matching, so DER of RDNSequence is more convenient. Name-opaque ::= ANY RDNSequence ::= SEQUENCE OF RelativeDistinguishedName RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndDistinguishedValue AttributeType ::= OBJECT IDENTIFIER AttributeTypeAndDistinguishedValue ::= SEQUENCE { type AttributeType, value AttributeValue } -- Cryptographic Message Syntax -- the starting point ContentInfo ::= --snacc isPdu:"TRUE" -- SEQUENCE { contentType ContentType, content [0] EXPLICIT ANY DEFINED BY contentType } ContentType ::= OBJECT IDENTIFIER -- top level, used in ContentInfo.content for signed data SignedData ::= SEQUENCE { version CMSVersion, -- redundant information present also in signerInfos digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncapsulatedContentInfo, certificates [0] IMPLICIT CertificateSet OPTIONAL, crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, signerInfos SignerInfos } DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier SignerInfos ::= SET OF SignerInfo EncapsulatedContentInfo ::= SEQUENCE { eContentType ContentType, -- eContent is absent for multipart/signed eContent [0] EXPLICIT OCTET STRING OPTIONAL } SignerInfo ::= SEQUENCE { version CMSVersion, sid SignerIdentifier, digestAlgorithm DigestAlgorithmIdentifier, -- mandatory for any contentType except id-data -- has at least id-messageDigest signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, signatureAlgorithm SignatureAlgorithmIdentifier, signature SignatureValue, unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } SignerIdentifier ::= CHOICE { issuerAndSerialNumber IssuerAndSerialNumber, subjectKeyIdentifier [0] SubjectKeyIdentifier } SignedAttributes ::= SET SIZE (1..MAX) OF Attribute UnsignedAttributes ::= SET SIZE (1..MAX) OF Attribute Attribute ::= SEQUENCE { attrType OBJECT IDENTIFIER, attrValues SET OF AttributeValue } AttributeValue ::= ANY SignatureValue ::= OCTET STRING -- top level, used in ContentInfo.content for encrypted data EnvelopedData ::= SEQUENCE { version CMSVersion, originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, recipientInfos RecipientInfos, encryptedContentInfo EncryptedContentInfo, unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL } OriginatorInfo ::= SEQUENCE { certs [0] IMPLICIT CertificateSet OPTIONAL, crls [1] IMPLICIT CertificateRevocationLists OPTIONAL } RecipientInfos ::= SET OF RecipientInfo EncryptedContentInfo ::= SEQUENCE { contentType ContentType, contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, encryptedContent [0] IMPLICIT EncryptedContent --OPTIONAL-- } EncryptedContent ::= OCTET STRING UnprotectedAttributes ::= SET SIZE (1..MAX) OF Attribute RecipientInfo ::= CHOICE { ktri KeyTransRecipientInfo, kari [1] KeyAgreeRecipientInfo, kekri [2] KEKRecipientInfo } EncryptedKey ::= OCTET STRING KeyTransRecipientInfo ::= SEQUENCE { version CMSVersion, -- always set to 0 or 2 rid RecipientIdentifier, keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, encryptedKey EncryptedKey } RecipientIdentifier ::= CHOICE { issuerAndSerialNumber IssuerAndSerialNumber, subjectKeyIdentifier [0] SubjectKeyIdentifier } KeyAgreeRecipientInfo ::= SEQUENCE { version CMSVersion, -- always set to 3 originator [0] EXPLICIT OriginatorIdentifierOrKey, ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL, keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, recipientEncryptedKeys RecipientEncryptedKeys } OriginatorIdentifierOrKey ::= CHOICE { issuerAndSerialNumber IssuerAndSerialNumber, subjectKeyIdentifier [0] SubjectKeyIdentifier, originatorKey [1] OriginatorPublicKey } OriginatorPublicKey ::= SEQUENCE { algorithm AlgorithmIdentifier, publicKey BIT STRING } -- information object classes AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameters ANY DEFINED BY algorithm OPTIONAL } RecipientEncryptedKeys ::= SEQUENCE OF RecipientEncryptedKey RecipientEncryptedKey ::= SEQUENCE { rid KeyAgreeRecipientIdentifier, encryptedKey EncryptedKey } KeyAgreeRecipientIdentifier ::= CHOICE { issuerAndSerialNumber IssuerAndSerialNumber, rKeyId [0] IMPLICIT RecipientKeyIdentifier } RecipientKeyIdentifier ::= SEQUENCE { subjectKeyIdentifier SubjectKeyIdentifier, date GeneralizedTime OPTIONAL, other OtherKeyAttribute OPTIONAL } SubjectKeyIdentifier ::= OCTET STRING KEKRecipientInfo ::= SEQUENCE { version CMSVersion, -- always set to 4 kekid KEKIdentifier, keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, encryptedKey EncryptedKey } KEKIdentifier ::= SEQUENCE { keyIdentifier OCTET STRING, date GeneralizedTime OPTIONAL, other OtherKeyAttribute OPTIONAL } DigestedData ::= SEQUENCE { version CMSVersion, digestAlgorithm DigestAlgorithmIdentifier, encapContentInfo EncapsulatedContentInfo, digest Digest } Digest ::= OCTET STRING EncryptedData ::= SEQUENCE { version CMSVersion, encryptedContentInfo EncryptedContentInfo, unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL } AuthenticatedData ::= SEQUENCE { version CMSVersion, originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, recipientInfos RecipientInfos, macAlgorithm MessageAuthenticationCodeAlgorithm, digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL, encapContentInfo EncapsulatedContentInfo, authenticatedAttributes [2] IMPLICIT AuthAttributes OPTIONAL, mac MessageAuthenticationCode, unauthenticatedAttributes [3] IMPLICIT UnauthAttributes OPTIONAL } AuthAttributes ::= SET SIZE (1..MAX) OF Attribute UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute MessageAuthenticationCode ::= OCTET STRING DigestAlgorithmIdentifier ::= AlgorithmIdentifier SignatureAlgorithmIdentifier ::= AlgorithmIdentifier KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier MessageAuthenticationCodeAlgorithm ::= AlgorithmIdentifier CertificateRevocationLists ::= SET OF CertificateList -- Certificate Revocation List (CRL) -- TODO: this is wrong, do similiar to Certificate CertificateList ::= SEQUENCE { -- SIGNED { version Version OPTIONAL, -- if present, version must be v2 signature AlgorithmIdentifier, issuer Name-opaque, thisUpdate Time, nextUpdate Time OPTIONAL, revokedCertificates SEQUENCE OF SEQUENCE {userCertificate CertificateSerialNumber, revocationDate Time, crlEntryExtensions Extensions OPTIONAL} OPTIONAL, crlExtensions [0] Extensions OPTIONAL} -- } Version ::= INTEGER {v1(0), v2(1), v3(2)} CertificateChoices ::= CHOICE { certificate Certificate, -- See X.509 extendedCertificate [0] IMPLICIT ExtendedCertificate, -- Obsolete attrCert [1] IMPLICIT AttributeCertificate } -- See X.509 & X9.57 CertificateSet ::= SET OF CertificateChoices CertificateSerialNumber ::= INTEGER IssuerAndSerialNumber ::= SEQUENCE { issuer Name-opaque, serialNumber CertificateSerialNumber } CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) } UserKeyingMaterial ::= OCTET STRING OtherKeyAttribute ::= SEQUENCE { keyAttrId OBJECT IDENTIFIER, keyAttr ANY DEFINED BY keyAttrId OPTIONAL } -- CMS Attributes MessageDigest ::= OCTET STRING SigningTime ::= Time Time ::= CHOICE { utcTime UTCTime, generalTime GeneralizedTime } Countersignature ::= SignerInfo -- Algorithm Identifiers sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithm(2) 26 } md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } id-dsa-with-sha1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) x9-57 (10040) x9cm(4) 3 } rsaEncryption OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 1 } dh-public-number OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) ansi-x942(10046) number-type(2) 1 } id-alg-ESDH OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 5 } id-alg-CMS3DESwrap OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 6 } id-alg-CMSRC2wrap OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) alg(3) 7 } des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } rc2-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) encryptionAlgorithm(3) 2 } hMAC-SHA1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) 8 1 2 } -- Algorithm Parameters KeyWrapAlgorithm ::= AlgorithmIdentifier RC2wrapParameter ::= RC2ParameterVersion RC2ParameterVersion ::= INTEGER CBCParameter ::= IV IV ::= OCTET STRING -- exactly 8 octets for DES, 16 for AES RC2CBCParameter ::= SEQUENCE { rc2ParameterVersion INTEGER, iv OCTET STRING } -- exactly 8 octets -- Content Type Object Identifiers id-ct-contentInfo OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 6 } id-data OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 1 } id-signedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 2 } id-envelopedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 3 } id-digestedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 5 } id-encryptedData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs7(7) 6 } id-ct-authData OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 2 } -- Attribute Object Identifiers id-contentType OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) 3 } id-messageDigest OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) 4 } id-signingTime OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) 5 } id-countersignature OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9) 6 } -- Obsolete Extended Certificate syntax from PKCS#6 ExtendedCertificate ::= SEQUENCE { extendedCertificateInfo ExtendedCertificateInfo, signatureAlgorithm SignatureAlgorithmIdentifier, signature Signature } ExtendedCertificateInfo ::= SEQUENCE { version CMSVersion, certificate Certificate, attributes UnauthAttributes } Signature ::= BIT STRING ToBeSigned ::= SEQUENCE { version [0] EXPLICIT Version DEFAULT v1, serialNumber CertificateSerialNumber, signature AlgorithmIdentifier, issuer Name-opaque, validity Validity, subject Name-opaque, subjectPublicKeyInfo SubjectPublicKeyInfo, issuerUniqueIdentifier [1] IMPLICIT UniqueIdentifier OPTIONAL, -- if present, version must be v2 or v3 subjectUniqueIdentifier [2] IMPLICIT UniqueIdentifier OPTIONAL, -- if present, version must be v2 or v3 extensions [3] EXPLICIT Extensions OPTIONAL -- If present, version must be v3 -- } Certificate ::= SEQUENCE { tbsCertificate ToBeSigned, signatureAlgorithm AlgorithmIdentifier, signature BIT STRING } Validity ::= SEQUENCE { notBefore Time, notAfter Time } SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } UniqueIdentifier ::= BIT STRING AttributeCertificate ::= BIT STRING Extension ::= SEQUENCE { extnID OBJECT IDENTIFIER, critical BOOLEAN DEFAULT FALSE, extnValue OCTET STRING } Extensions ::= SEQUENCE OF Extension -- Certificate Extensions id-ce OBJECT IDENTIFIER ::= { 2 5 29 } id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } -- PKCS#1 OAEP padding -- id-RSAES-OAEP OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1) 7 } -- is MGF1 with SHA1 is used, RSAES-OAEP-params must be NULL -- RSAES-OAEP-params ::= SEQUENCE { -- hashFunc [0] AlgorithmIdentifier DEFAULT sha1Identifier, -- maskGenFunc [1] AlgorithmIdentifier DEFAULT mgf1SHA1Identifier, -- pSourceFunc [2] AlgorithmIdentifier DEFAULT -- pSpecifiedEmptyIdentifier } -- sha1Identifier AlgorithmIdentifier ::= { sha-1, NULL } -- -- mgf1SHA1Identifier AlgorithmIdentifier ::= { id-mgf1, sha1Identifier } -- -- pSpecifiedEmptyIdentifier AlgorithmIdentifier ::= { id-pSpecified, nullOctetString } -- -- nullOctetString OCTET STRING (SIZE (0)) ::= { ''H } -- -- id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 } -- -- id-pSpecified OBJECT IDENTIFIER ::= { pkcs-1 9 } -- AES information object identifiers -- aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) 1 } -- AES using CBC-chaining mode for key sizes of 128, 192, 256 id-aes128-CBC OBJECT IDENTIFIER ::= { aes 2 } id-aes192-CBC OBJECT IDENTIFIER ::= { aes 22 } id-aes256-CBC OBJECT IDENTIFIER ::= { aes 42 } END -- of CryptographicMessageSyntax ŹE d䯐8 "Rykth;${RA/B[UTjk!: rv0VM%HAXuw[[mDE(˲Z}zinNIp[hH J9"%Tea{eERsM ͸ӬT5\]oCL}CvIb|QuA-@vjR˱$8Pv;Xv3kًm۝ C$(u3a93䊮RKd(2B֕3p|a-#Pw `vSy:k2'1cU[ҖW*5drU!R2z̃vkQb<:ڔ-iP y"~QXݜu}U SI`A)s )GBK -X0<ȚJ|%5 ` G);AP}k*fM]"w]RVbqQU ŴR0 &勎$ns(CgV"gզMAFԵɣ jI}YNF9N*bPF |K*'':(2r"LqpTԭHVn9K^s1L}iQcR!U|9olWݸ Re5 y*Tm;MP;KezRv0:(]|Ǩ w?ޱZ]wEOnwcWyO⁘kP,>OLp2~#)>FE'iOBζـϓyrm1Ƀ#]E ̔!&ºJVe_o$ǚTE4nvq |hw ]yK )"c2@Fݠv?4jA^3v\\/*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * Common top level routines for SMIME * * $Id: pgpSMIME.c,v 1.13 2004/05/28 19:47:57 ajivsov Exp $ ____________________________________________________________________________*/ /* ----- SDK includes ----- */ #include "pgpConfig.h" /* important configuration defines */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpContext.h" #include "pgpX509Priv.h" #include "pgpKeyPriv.h" #include "pgpSymmetricCipherPriv.h" #include "pgpHashPriv.h" #include "pgpEncodePriv.h" /* ----- end of SDK includes ----- */ #include #include #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" /* SMIME-level functions */ PGPError pgpSMIMENewContext(PGPContextRef sdkcontext, PGPsmimeContextRef /*out*/ *smime) { SMIMEError ret; SMIME_CONTEXT *newsmime; *smime = NULL; /* we use secure alloc because we need a protection for the key_buf */ newsmime = (SMIME_CONTEXT*)PGPNewSecureData( PGPPeekContextMemoryMgr(sdkcontext), sizeof(SMIME_CONTEXT), 0 ); if( newsmime == NULL ) return kPGPError_OutOfMemory; ret = asnInitSMIMEContext( sdkcontext, newsmime ); if( ret ) return pgpSMIMEErrorToPGPError(ret); newsmime->contentHashInternal.p = newsmime->hash_buf; newsmime->contentHashInternal.l = sizeof(newsmime->hash_buf); newsmime->contentHashInternal.dontFree = TRUE; newsmime->contentEncrIVInternal.p = newsmime->IV_buf; newsmime->contentEncrIVInternal.l = sizeof(newsmime->IV_buf); newsmime->contentEncrIVInternal.dontFree = TRUE; newsmime->contentEncrKeyInternal.p = newsmime->key_buf; newsmime->contentEncrKeyInternal.l = sizeof(newsmime->key_buf); newsmime->contentEncrKeyInternal.dontFree = TRUE; newsmime->contentEncrAlgInternal = kPGPCipherAlgorithm_None; *smime = (PGPsmimeContextRef)newsmime; return kPGPError_NoErr; } PGPError pgpSMIMEFreeContext(PGPsmimeContextRef smime) { SMIME_CONTEXT *c = (SMIME_CONTEXT*)smime; if( smime==NULL ) return kPGPError_NoErr; asnFreeSMIMEContext(c); PGPFreeData( c ); return kPGPError_NoErr; } void pgpSMIMEFreePtr(P *p) { pgpAssert(!p || (p->dontFree==FALSE||p->dontFree==TRUE)); if( p && p->p && !p->dontFree ) { PGPFreeData( p->p ); p->p = NULL; p->l = 0; } } /* Some PGP errors of interest kPGPError_BadHashNumber; kPGPError_BadMemAddress kPGPError_BadParams kPGPError_BufferTooSmall kPGPError_CantHash kPGPError_CorruptData kPGPError_OutOfMemory kPGPError_InvalidCertificateExtension kPGPError_InvalidCertificateFormat kPGPError_InvalidDistinguishedName kPGPError_InvalidInputFormat kPGPError_InvalidOutputFormat kPGPError_InvalidPKCS7Encoding kPGPError_InvalidProperty kPGPError_ItemNotFound kPGPError_KeyUnusableForDecryption kPGPError_KeyUnusableForEncryption kPGPError_KeyUnusableForSignature kPGPError_LazyProgrammer kPGPError_MemoryOpFailed kPGPError_MissingX509Certificate kPGPError_NoDecryptionKeyFound kPGPError_OutputBufferTooSmall kPGPError_PKCS7DecryptFailure kPGPError_PKCS7EncryptFailure kPGPError_PKCS7SignFailure kPGPError_PublicKeyNotFound, kPGPError_PublicKeyTooLarge kPGPError_PublicKeyTooSmall kPGPError_TruncatedSignature kPGPError_UnknownSignatureAlgorithm kPGPError_UnknownSignatureType kPGPError_UnknownSignatureVersion kPGPError_UnknownVersion kPGPError_X509AttributeNotSupported kPGPError_X509CertificateParseError kPGPError_X509InvalidCertificateFormat kPGPError_X509InvalidCertificateSignature kPGPError_X509NeededCertNotAvailable kPGPError_X509SelfSignedCert */ PGPError pgpSMIMEErrorToPGPError( int /* SMIMEError */ err ) { if( !err ) return kPGPError_NoErr; #if PGP_USE_TRACE /* TODO: give info about err category bits */ #endif /* Handle ASN.1 compiler errors */ if( (err & SMIME_ERROR_ID_MASK) < SMIMEError_EncodingMax ) return kPGPError_ASNPackFailure; switch(err & SMIME_ERROR_ID_MASK) { case SMIMEError_ErrorOverflow: return kPGPError_LazyProgrammer; case SMIMEError_NotFound: return kPGPError_ItemNotFound; case SMIMEError_Unknown: return kPGPError_UnknownError; case SMIMEError_NoMem: return kPGPError_OutOfMemory; case SMIMEError_CorruptData: case SMIMEError_InconsistentData: return kPGPError_CorruptData; case SMIMEError_BufferTooShort: return kPGPError_BufferTooSmall; case SMIMEError_BadContext: case SMIMEError_BadParam: case SMIMEError_ParameterMismatch: return kPGPError_BadParams; case SMIMEError_UnsupportedHash: return kPGPError_BadHashNumber; case SMIMEError_UnsupportedPubAlg: return kPGPError_UnknownPublicKeyAlgorithm; case SMIMEError_UnsupportedEncrAlg: return kPGPError_BadCipherNumber; case SMIMEError_SizeTooLarge: return kPGPError_SizeTooLarge; case SMIMEError_FieldTooShortToHoldKeyID: return kPGPError_InvalidProperty; default: return kPGPError_UnknownError; } } /* get certificate for given PGPKeyAndUserID */ PGPError pgpSMIMEGetCert( const PGPKeyAndUserID *ID, PGPKeyDBRef keydb, PGPKeyDBObjRef *x509cert ) { PGPKeyIterRef keyiter; PGPKeyDBObjRef keyObj; PGPKeyDBObjRef sigObj; PGPKeyDBObjRef useridObj; PGPUInt useridSize; PGPError err; *x509cert = NULL; #if PGP_USE_TRACE { PGPChar8 keyidstr[kPGPMaxKeyIDStringSize] = ""; PGPUInt32 nkeys; PGPCountKeysInKeyDB( keydb, &nkeys ); PGPGetKeyIDString( &ID->keyid, kPGPKeyIDString_Full, keyidstr ); SMIME_TRACE3("Looking for certificate for '%s' (key %s) among %d keys", ID->userid, keyidstr, nkeys); } #endif err = PGPNewKeyIterFromKeyDB( keydb, &keyiter ); if( IsPGPError(err) ) return err; err = pgpGetKeyByKeyID( keydb, &ID->keyid, /*dummyOK*/FALSE, /*deletedOK*/FALSE, &keyObj ); if( IsPGPError(err) ) { PGPFreeKeyIter( keyiter ); return err; } useridSize = (PGPUInt)strlen( ID->userid ); (void)PGPKeyIterSeek( keyiter, keyObj ); err = PGPKeyIterRewind( keyiter, kPGPKeyDBObjType_UserID ); if( IsPGPError(err) ) { SMIME_TRACE1("Error %d positioning to the first userID for the key", err); return err; } /* find userID */ err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_UserID, &useridObj ); for( ; useridObj; err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_UserID, &useridObj ) ) { const PGPUTF8 *uid; PGPUInt size; uid = (PGPUTF8 const *)pgpUserIDName( useridObj, &size ); if( uid && useridSize==size && memcmp( ID->userid, uid, size )==0 ) break; } if( useridObj==NULL ) { SMIME_TRACE2("Error %d finding a user ID '%s'", err, ID->userid); PGPFreeKeyIter( keyiter ); return IsPGPError(err) ? err : kPGPError_ItemNotFound; } err = PGPKeyIterRewind( keyiter, kPGPKeyDBObjType_Signature ); if( IsPGPError(err) ) { PGPFreeKeyIter( keyiter ); return err; } /* finally, loop over signatures */ err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_Signature, &sigObj ); for( ; sigObj; err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_Signature, &sigObj ) ) { /* user ID must have X509 certificates */ if( !pgpSigIsX509(sigObj) ) continue; break; /* first eligible signature */ } PGPFreeKeyIter( keyiter ); if( err == kPGPError_EndOfIteration ) err = kPGPError_ItemNotFound; /* found certificate */ if( IsntPGPError(err) ) *x509cert = sigObj; #if PGP_USE_TRACE if( sigObj==NULL ) SMIME_TRACE1("Could not find certificate for '%s'", ID->userid); #endif return err; } PGPError pgpSMIMECreateID( PGPContextRef sdkcontext, PGPKeyDBObjRef sig, PGPKeyAndUserID **ID ) { PGPKeyAndUserID *myID; PGPKeyDBObjRef keyObj; const PGPUTF8 *udata; PGPUInt size; PGPError err; *ID = NULL; if( !(pgpSigIsValid(sig) && pgpSigIsX509(sig)) ) return kPGPError_MissingX509Certificate; if( (keyObj = PGPPeekKeyDBObjKey( sig ))==NULL || !pgpKeyIsSec(keyObj) ) return kPGPError_SecretKeyNotFound; myID = pgpContextMemAlloc( sdkcontext, sizeof(PGPKeyAndUserID), 0 ); if( myID == NULL ) return kPGPError_OutOfMemory;; err = PGPGetKeyID( keyObj, &myID->keyid ); if( IsPGPError(err) ) { PGPFreeData( myID ); return err; } udata = (PGPUTF8 const *)pgpUserIDName( PGPPeekKeyDBObjUserID(sig), &size ); if( udata ) { if( size > sizeof(myID->userid)-1 ) size = sizeof(myID->userid)-1; strncpy( myID->userid, udata, size ); myID->userid[size] = '\0'; } else { PGPFreeData( myID ); return kPGPError_CorruptData; } #if PGP_USE_TRACE { PGPChar keyidstr[kPGPMaxKeyIDStringSize] = ""; PGPError sdkerr; sdkerr = PGPGetKeyIDString( &myID->keyid, kPGPKeyIDString_Full, keyidstr ); SMIME_TRACE2("Using explicitly specified signle X.509 cert: %s with keyid %s", myID->userid, keyidstr ); } #endif *ID = myID; return err; } /* Helper function that creates an array of identities in a form {keyID, userID} from given keySet. * Identity can be a signer (for signature generation) or recipient (for encryption). * Can return 0 recipients without an error. */ PGPError pgpSMIMECreateIDs( PGPContextRef sdkcontext, PGPKeySetRef keyset, PGPBoolean privateOnly, int *identities, PGPKeyAndUserID **IDs ) { PGPError err = kPGPError_NoErr; PGPKeyIterRef keyiter; PGPKeyDBObjRef keyObj; PGPKeyAndUserID *myIDs = NULL; int myIdentities=0; *identities = 0; *IDs = NULL; if( keyset == NULL ) { SMIME_TRACE("Empty keySet passed"); return kPGPError_BadParams; } err = PGPNewKeyIterFromKeySet (keyset, &keyiter); if( IsPGPError(err) ) return err; err = PGPKeyIterRewind( keyiter, kPGPKeyDBObjType_Key ); if( IsPGPError(err) ) { PGPFreeKeyIter( keyiter ); return err; } err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_Key, &keyObj ); /* loop over all private keys */ for( ; keyObj; err=PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_Key, &keyObj ) ) { PGPKeyID keyid; PGPKeyDBObjRef userid = kInvalidPGPKeyDBObjRef; PGPBoolean isSecret; if( privateOnly ) { PGPGetKeyDBObjBooleanProperty (keyObj, kPGPKeyProperty_IsSecret, &isSecret); if( !isSecret ) continue; } err = PGPGetKeyID( keyObj, &keyid ); if( IsPGPError(err) ) { SMIME_TRACE2("Error %d getting keyID for %s key", err, privateOnly ? PGPTXT_MACHINE8("private only") : PGPTXT_MACHINE8("private or public") ); break; } err = PGPKeyIterRewind( keyiter, kPGPKeyDBObjType_UserID ); if( IsPGPError(err) ) { SMIME_TRACE2("Error %d positioning to the first userID for the %s key", err, privateOnly ? PGPTXT_MACHINE8("private only") : PGPTXT_MACHINE8("private or public")); continue; } /* loop over all userIDs of the key */ err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_UserID, &userid ); for( ; userid; err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_UserID, &userid ) ) { PGPKeyDBObjRef sig = kInvalidPGPKeyDBObjRef; err = PGPKeyIterRewind( keyiter, kPGPKeyDBObjType_Signature ); if( IsPGPError(err) ) break; /* finally, loop over all signatures */ err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_Signature, &sig ); for( ; sig; err = PGPKeyIterNextKeyDBObj( keyiter, kPGPKeyDBObjType_Signature, &sig ) ) { const PGPUTF8 *udata; PGPUInt size; /* user ID must have X509 certificates */ if( !pgpSigIsX509( sig ) ) continue; err = pgpContextMemRealloc( sdkcontext, (void**)&myIDs, (myIdentities+1) * sizeof(myIDs[0]), 0 ); if( IsPGPError(err) ) { SMIME_TRACE1("Failed to realloc IDs to %d bytes", (myIdentities+1) * sizeof(myIDs[0])); break; } udata = (PGPUTF8 const *)pgpUserIDName( userid, &size ); if( udata ) { if( size > sizeof(myIDs[myIdentities].userid)-1 ) size = sizeof(myIDs[myIdentities].userid)-1; strncpy( myIDs[myIdentities].userid, udata, size ); myIDs[myIdentities].userid[size] = '\0'; } else { err = kPGPError_CorruptData; break; } myIDs[myIdentities].keyid = keyid; #if PGP_USE_TRACE { PGPChar keyidstr[kPGPMaxKeyIDStringSize] = ""; PGPError sdkerr; sdkerr = PGPGetKeyIDString( &keyid, kPGPKeyIDString_Full, keyidstr ); SMIME_TRACE4("Found eligible X.509 cert for identity %d (%s): %s with keyid %s", myIdentities, privateOnly ? PGPTXT_MACHINE8("private only") : PGPTXT_MACHINE8("private or public"), myIDs[myIdentities].userid, keyidstr); } #endif myIdentities ++; break; /* one cert per user ID */ } if( IsPGPError(err) && err != kPGPError_EndOfIteration ) break; } if( IsPGPError(err) && err != kPGPError_EndOfIteration ) break; } PGPFreeKeyIter( keyiter ); if( err == kPGPError_EndOfIteration ) err = kPGPError_NoErr; if( IsntPGPError(err) ) { SMIME_TRACE2("%d %s identities created", myIdentities, privateOnly ? PGPTXT_MACHINE8("private only") : PGPTXT_MACHINE8("private and public")); *identities = myIdentities; *IDs = myIDs; } else { if( myIDs ) PGPFreeData(myIDs); } return err; } /* Efficiently parses few first bytes of CMS block to PGPInputFormat code. Doesn't invoke compiler code * so no need to read whole CMS block into memory. Decoded line of base64 encoding provides sufficient * number of bytes */ PGPError pgpSMIMEContentInfoToInputFormat( PGPsmimeContextRef smime, P *der, PGPInputFormat *format ) { SMIME_CONTEXT *c = (SMIME_CONTEXT*)smime; SMIMEError smimeerr; smimeerr = asnContentInfoToInputFormat( c, der, format ); return pgpSMIMEErrorToPGPError( smimeerr ); } /* Make hashes from PGPIO. There is nothing SMIME-related about this function, just convenient routine * PGPProgressCallBack is (arg, off_sofar, off_total) * Note that PGPFileOffset is a variable on Unix depending on large file support */ PGPError pgpSMIMEMakeHashesFromIO( PGPIORef IOstream, PGPFileOffset off_start, PGPFileOffset off_end, PGPHashListRef hashList, PGPProgressCallBack progressCallback, void *progressCallbackArg ) { PGPFileOffset savedpos, bodysize, bodysizeWithoutTail, large_i; PGPByte buffer[1024+1]; PGPUInt buffer_size = sizeof(buffer)-1;/* keep it power of 2 */ PGPSize readSize; PGPUInt tailSize; int i; const int hashes = pgpHashListGetSize( hashList ); PGPError err; bodysize = off_end - off_start; #if PGP_USE_TRACE memset( buffer, '*', sizeof(buffer) ); buffer[buffer_size] = '\0'; #endif /* save original position from base stream */ err = PGPIOGetPos( IOstream, &savedpos ); if( IsPGPError(err) ) return err; err = PGPIOSetPos( IOstream, off_start ); if( IsPGPError(err) ) { PGPIOSetPos( IOstream, savedpos ); return err; } SMIME_TRACE3("Beginning to hash from %08x-%08x (%d bytes)", (unsigned)off_start, (unsigned)off_end, bodysize ); if( progressCallback ) (*progressCallback)(progressCallbackArg, 0, bodysize); /* clean hashes */ for( i=0; i |^uK:p(\<]˕[-yTbސV  "0*"PJC\D#>u=#k 'h#.,7Y#ݵ 7H *8*}l9% 3]6+4C"`$RaUޱ8 Pt(iOt %VFYfJ2@* ! |sxpP׻$n{[dd[UVez͹~+-k3QUC rhڪ!R} J%?^( nT7#Ę陪t 1gGf ЪF&*0΀!h] A$*BR@3M˒~2tnSrR9K&ꋐahlY@sH?hddcpa)a'y+:q(ep$A$Յ>2G,Yѥ!HOk6ir&4 K+0NEϥR%`."N0f5HBVCs#,F?˟j-iK>'I5JaxU#[H9 7E6#2n@+wAu8ٴ( k/TraUbַo$#1#bj.OTsbD+u4,j!w338b'˔mԴR3M5R4js֍7.Cʌ35^R7 g42ڻvUЖ˴F#Zj=8{`2}Y qE,YAUx@ۚY=h  8d)220'˝]^,_|5*ṞRI-U1$ՈYS.--) _ ݻr&u:mk~@@1+́*lmOL9ԩMp27xCow|΋Bp=0 f}-f84m´WPv" yɢԙ~! j vPMvH bH@0'ZFjTp9DظX c^"e)9{H,0Q 0&OAZV-W\[$燐 `|oU-2Ltv 1S#H՚^I CP%A92m -ذPAs&\%BZIRN}9ʭUX"!T*IhwJ@RP{?jSHS@}[:&W =m@ #/cu w1*cDPL3߆o~Q. qs# W~ιr##z~HZ/x6O╜/Uq!ZL1z hzvxY1ΕZB]mHPҁlrb+eM^iD?^c]nU7(SZo ֌tHLPE ~gXWN/HcrNJ[b)%[u"S)suxv IϋTdp0:.whaghRߨ3?_X8V "H>OqT) 0ސ B&$󊊶EF -3&)P-ɓ6.A |3Ob[ջY A ZzKeD/L„ ~YhhRT7-*́56HPZ9{օT VTI'$ղ.l?0GySmnU,G?<.nQ떟/\kP˨R+9XG>lj"NI`" ΃^IgimpV;=([50r$#aڀ `HR-;D)t^i5!9a 4?QRiwk|RS-iEQR*[d˩1&SiWӹ\"|Onj|;M"hrJC7QOur>jΚ/v%.1L.>r9R߆u$3%p&~TM tRc4>^T E;t0k,wA хm5WZKz\!pA^.VLnwLY÷I (%`[l첲 GS޿ ;{O+&~UԈYem~?cD/vO_`TT{!8DnZA⧤mq\LOʬi{{vcڹe{\WGoٙ+C$(>HUJq8c˲ܓ!DFg8!A+~L[‡m$&ګp'H-m}<#ifndef PGP_SMIME_H #define PGP_SMIME_H #include "pgpIO.h" #include "pgpEncodePriv.h" /* PGPSMIMEPtr is a tuple of byte pointer and its size; * the order is important so we can statically initialize this structure */ typedef struct PGPsmimePtr_ { PGPByte *p; PGPSize l; PGPBoolean dontFree; } PGPSMIMEPtr; /* used to better identify signers. KeyID is not sufficient as we can have more then one * certificate on the key */ typedef struct PGPKeyAndUserID_ { PGPKeyID keyid; PGPUTF8 userid[kPGPMaxUserIDSize]; } PGPKeyAndUserID; typedef PGPByte *** PGPsmimeContextRef; typedef PGPByte **** PGPMIMERef; /* ----- Utility functions for SMIME ----- */ PGPError pgpSMIMENewContext(PGPContextRef sdkcontext, PGPsmimeContextRef /*out*/ *smime); PGPError pgpSMIMEFreeContext(PGPsmimeContextRef smime); void pgpSMIMEFreePtr(PGPSMIMEPtr *p); PGPError pgpSMIMEErrorToPGPError( int ); PGPError pgpSMIMEGetCert( const PGPKeyAndUserID *ID, PGPKeyDBRef keydb, PGPKeyDBObjRef *x509cert ); PGPError pgpSMIMECreateID( PGPContextRef sdkcontext, PGPKeyDBObjRef sig, PGPKeyAndUserID **ID ); PGPError pgpSMIMECreateIDs( PGPContextRef sdkcontext, PGPKeySetRef keyset, PGPBoolean privateOnly, int *identities, PGPKeyAndUserID **IDs ); PGPError pgpSMIMEContentInfoToInputFormat( PGPsmimeContextRef smime, PGPSMIMEPtr *der, PGPInputFormat *format ); PGPError pgpSMIMEMakeHashesFromIO( PGPIORef IOstream, PGPFileOffset off_start, PGPFileOffset off_end, PGPHashListRef hashList, PGPProgressCallBack progressCallback, void *progressCallbackArg ); /* ----- Interface API for SMIME CMS signature verification ----- */ PGPError pgpSMIMEcmsProcessSigned(PGPsmimeContextRef smime, const PGPSMIMEPtr *smimebody); PGPError pgpSMIMEcmsIsSignedDataContentEnclosed(PGPsmimeContextRef smime, PGPBoolean *contentPresent); PGPError pgpSMIMEcmsGetSignedDataContent(PGPsmimeContextRef smime, PGPSMIMEPtr *msg); PGPError pgpSMIMEcmsGetNumberOfSigners(PGPsmimeContextRef smime, int *signers); PGPError pgpSMIMEcmsCreateHashListRef(PGPsmimeContextRef smime, PGPHashListRef /*out*/ *hashList); PGPError pgpSMIMEcmsGetHashAlg(PGPsmimeContextRef smime, int signer, PGPHashAlgorithm /*out*/ *hashAlg); PGPError pgpSMIMEcmsGetMsgHash(PGPsmimeContextRef smime, int signer, PGPSMIMEPtr /*out*/ *hash); PGPError pgpSMIMEcmsGetCerts(PGPsmimeContextRef smime, int signer, PGPKeyDBObjRef /*out*/ *signerCert, PGPKeyDBRef /*out*/ *keydb); PGPError pgpSMIMEcmsVerifySignature(PGPsmimeContextRef smime, int signer, PGPKeyDBObjRef key, PGPTime *signingTime); PGPError pgpSMIMEcmsGetSignerCaps(PGPsmimeContextRef smime, int signer, PGPCipherAlgorithm /* out */encrAlgs[256], int /*out*/ *nEncrAlgs); PGPBoolean pgpSMIMEcmsSignedAttrsValid(PGPKeyDBObjRef sig, PGPKeyDBObjRef key); PGPError pgpUpdateSMIMEPrefAlgs( PGPAlgorithmChoiceRef choice, PGPKeyDBObjRef key, PGPCipherAlgorithm defAlg ); PGPError pgpGetSMIMEPrefAlgs( PGPKeyDBObjRef userid, PGPCipherAlgorithm algs[256], int *nalgs ); /* ----- Interface API for SMIME CMS decryption ----- */ PGPError pgpSMIMEcmsProcessEnveloped(PGPsmimeContextRef smime, const PGPSMIMEPtr *smimebody); PGPError pgpSMIMEcmsGetNumberOfEnvelopeRecipients(PGPsmimeContextRef smime, int *recipients); PGPError pgpSMIMEcmsGetContentEncrAlg(PGPsmimeContextRef smime, PGPCipherAlgorithm *alg); PGPError pgpSMIMEcmsGetRecipientKeyIDs(PGPsmimeContextRef smime, PGPKeyDBRef certDB, PGPKeyID /*out*/ *recipientKeyIDs /*[recipients]*/, PGPSMIMEMatchCriterion criterion); PGPError pgpSMIMEcmsGetRecipientESK(PGPsmimeContextRef smime, int recipient, PGPSMIMEPtr *esk); PGPError pgpSMIMEcmsDecryptContent(PGPsmimeContextRef smime, const PGPSMIMEPtr *key, PGPSMIMEPtr *plaintext, PGPProgressCallBack progressCallback, void *progressCallbackArg); PGPError pgpSMIMEcmsGetRecipientKeyEncrAlg(PGPsmimeContextRef smime, int recipient, PGPPublicKeyAlgorithm *alg); /* two routines bellow are not used in SDK PGPDecode: */ PGPError pgpSMIMEcmsDecryptESK( PGPsmimeContextRef smime, const PGPSMIMEPtr *esk, PGPKeyDBObjRef keyObj, PGPOptionListRef keyUnlockOptions, PGPSMIMEPtr *keyout ); PGPError pgpSMIMEcmsDecryptAll(PGPsmimeContextRef smime, PGPOptionListRef keyUnlockOptions, PGPKeyDBRef keyDB, PGPKeyID /*out*/ recipientsKeyIDs[], PGPSMIMEPtr /*out*/ *plaintext ); /* ----- Interface API for SMIME CMS signing ----- */ PGPError pgpSMIMEcmsCreateSigned( PGPsmimeContextRef smime, PGPKeyDBRef keydb, int signers, const PGPKeyAndUserID *signerIDs ); PGPError pgpSMIMEcmsSetSignedDataContent( PGPsmimeContextRef smime, const PGPSMIMEPtr /*in*/ *msg ); PGPError pgpSMIMEcmsSign( PGPsmimeContextRef smime, PGPHashAlgorithm hashAlg, const PGPSMIMEPtr *hash, PGPKeyDBRef keydb, PGPKeyAndUserID *signerIDs, PGPOptionListRef keyUnlockOptions ); PGPError pgpSMIMEcmsSetSignerSignature( PGPsmimeContextRef smime, int signer, const PGPSMIMEPtr *signature ); PGPError pgpSMIMEcmsExportSigned( PGPsmimeContextRef smime, PGPSMIMEPtr *mime ); /* ----- Interface API for SMIME CMS encryption ----- */ PGPError pgpSMIMEcmsCreateEnveloped( PGPsmimeContextRef smime, PGPKeyDBRef keydb, int recipients, const PGPKeyAndUserID *recipientIDs ); PGPError pgpSMIMEcmsEncrypt( PGPsmimeContextRef smime, PGPCipherAlgorithm encrAlg, PGPKeyDBRef keydb, const PGPKeyAndUserID *recipientIDs ); PGPError pgpSMIMEcmsExportEnveloped( PGPsmimeContextRef smime, const PGPSMIMEPtr *plaintext, PGPProgressCallBack progressCallback, void *progressCallbackArg, PGPSMIMEPtr *mime ); /* ----- Interface to MIME processing routines. These can be moved elsewhere or I could use others ----- */ PGPError pgpMIMEProcess( PGPContextRef sdkcontext, PGPIORef baseIO, PGPMIMERef *mime ); void pgpMIMEFree( PGPMIMERef mime ); PGPError pgpMIMEGetNumberOfBodies( PGPMIMERef mime, int *bodies ); PGPError pgpMIMEGetBodyHeader( PGPMIMERef mime, int body, PGPSMIMEPtr *header ); PGPError pgpMIMEGetBodyContent( PGPMIMERef mime, int body, PGPSMIMEPtr *mimebodyout ); PGPError pgpMIMEGetBodyHashes( PGPMIMERef mime, int body, PGPHashListRef hashList ); #endif /*PGP_SMIME_H*/ =g?j$!@ۋ_vM}>Zp;+,r$*g5nC$ |w޷.N (xkmjXp|!jM)S8+B;mjN T~q}iKj=7}+;KŵuE}RQnKfnZf#3$5aPniˌULH1 e{Ƃj;ҷ{mP]V8PKmqQ\k;@;Q׭U&hTXu6^$`XQp_,ޅu2>Tv* ++APzК] Xm>h@1(<Fކq44bl p` D.GtK(9~{ Vb\_X NyKdkot̺#6Ԩ:*An>Pb*M[ -25vޭ$>lyMdlnۙ˟/qKh»^lbU%wP5mؼvW >W.5A7'Ω7y,RvMWfDOlU4*3&$$d\wmHr wإx }iŰKyCZ݉jA<%BgM'/DF`_XHR. N+bwdy&~Uw^4VO#U>hP~ Ȃ9Zt,NJ}BaTŞ*yڸ[ӡmxB:zU1lnRO&GU,U +kWˏ8K v=I4`[ ;&] ԬV_jLp>c[7AnB9EXP J6Ylϻ1RIeۖ3 j.RpH<"?zEqmިGUąz5Z[_ ַyefIGRB u5sݢs02^pM—%}vHe/'^$a|ʣ%r4.|(q "Z~|?KHBp'$Ȣ#ڲ*Y8 a8P@9 y2 k!jBROچ;Zvkl'~՗Ie" p 򁏑&(l:HRcTrb~tWaaGڞL`D ui')/bTBNФiuVHK zQF4s/3[XAAFSSh<%%*Y?c)6J .&n8NkoKcS)=ÉInr@<;D(>4N< qf*EԀsC\jѽ-" C]mhe uɃ@!a J~M<݄hVZ ‡/Zs7 q/*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 DER decryption * for SMIME. * * $Id: pgpSMIMEasnDecrypt.c,v 1.6 2004/04/23 06:44:50 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" SMIMEError asnProcessEnvelopedData(SMIME_CONTEXT *c, const P *der) { ASN_CMS_ContentInfo *ci; ASN_CMS_EnvelopedData *envelopedData; int err=0; ASN_CMS_UnpackContentInfo( c->asnc, &ci, der->p, der->l, &err ); SMIME_TRACE1( "ASN_CMS_UnpackContentInfo returned %d", err ); if( err ) return ASNErrorToSMIMEError( err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); /* ContentInfo has ANY DEFINED BY 'content' that parser treats as ANY; * now manually direct the parser */ if( OIDCMP( &ci->contentType, ASN_CMS_id_envelopedData_OID )!=0 ) { SMIME_TRACE( "Given SMIME block is not EnvelopedData type" ); ASN_CMS_FreeContentInfo( c->asnc, ci ); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE("ContentType is EnvelopedData"); ASN_CMS_UnpackEnvelopedData( c->asnc, &envelopedData, ci->content.val, ci->content.len, &err ); /* Don't need content into anymore */ ASN_CMS_FreeContentInfo( c->asnc, ci ); SMIME_TRACE("Freed contentInfo, keep envelopedData"); if( err ) { SMIME_TRACE2( "UnpackEnvelopedData returned %d %s", err, asn1comp_err(err) ); return ASNErrorToSMIMEError( err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); } SMIME_TRACE("Unpacked envelopedData OK"); if( c->envelopedData ) { SMIME_TRACE1("Had old envelopedData %p in the context, clean it", c->envelopedData); ASN_CMS_FreeEnvelopedData( c->asnc, c->envelopedData ); } c->envelopedData = envelopedData; SMIME_TRACE1("Added envelopedData %p to the context", c->envelopedData); return 0; } int asnGetNumberOfEnvelopeRecipients(SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData) { (void)c; return ( envelopedData==NULL ? 0 : envelopedData->recipientInfos.n ); } #if 0 if( recipient > envelopedData->recipientInfos.n ) { if( envelopedData->recipientInfos.n==0 ) SMIME_TRACE1("No recipients in enveloped data (should not happen) and we are asked for recipient %d", recipient); else SMIME_TRACE1("Out of range recipient %d for [0..%d]", recipient, envelopedData->recipientInfos.n-1); return FALSE; } #endif /* compare certificate with given identification */ static PGPBoolean match_IssuerAndSerialNumber_with_cert( ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber, ASN_CMS_Certificate *x509cert ) { if( sncmp( &x509cert->tbsCertificate.serialNumber, &issuerAndSerialNumber->serialNumber )!=0 ) { SMIME_TRACE("cert_match_IssuerAndSerialNumber: SN doesn't match"); return FALSE; } if( namecmp( & x509cert->tbsCertificate.issuer, &issuerAndSerialNumber->issuer )!=0 ) { SMIME_TRACE("cert_match_IssuerAndSerialNumber: issuer's DN doesn't match"); return FALSE; } SMIME_TRACE("cert_match_IssuerAndSerialNumber: found a cert based on IssuerAndSerialNumber"); return TRUE; } /* compare certificate with given identification */ static PGPBoolean match_SubjectKeyIdentifier_with_cert( ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier, ASN_CMS_Certificate *x509cert ) { int i; /* look in certificate extensions for OCTET STRING */ if( x509cert->tbsCertificate.extensions->n == 0 ) { SMIME_TRACE("cert_match_for_subjectKeyIdentifier: no extensions"); return FALSE; } for( i=0; itbsCertificate.extensions->n; i++ ) { if( OIDCMP( &x509cert->tbsCertificate.extensions->elt[i]->extnID, ASN_CMS_id_ce_subjectKeyIdentifier_OID )==0 ) break; } if( i == x509cert->tbsCertificate.extensions->n ) { SMIME_TRACE("cert_match_for_subjectKeyIdentifier: no SubjectKeyIdentifier extension"); return FALSE; } SMIME_TRACE1("cert_match_for_subjectKeyIdentifier: match found at extension #%d", i); if( x509cert->tbsCertificate.extensions->elt[i]->extnValue.len != subjectKeyIdentifier->len ) { SMIME_TRACE2("cert_match_for_subjectKeyIdentifier: length of SubjectKeyIdentifier extension don't match: %d vs %d", x509cert->tbsCertificate.extensions->elt[i]->extnValue.len, subjectKeyIdentifier->len); return FALSE; } return memcmp( x509cert->tbsCertificate.extensions->elt[i]->extnValue.val, subjectKeyIdentifier->val, subjectKeyIdentifier->len )==0; } /* returns asnerr */ static int getKTRI( SMIME_CONTEXT *c, ASN_CMS_RecipientInfo *ri, int recipient, ASN_CMS_KeyTransRecipientInfo **ktriout ) { long version; ASN_CMS_KeyTransRecipientInfo *ktri; int asnerr = 0; (void)recipient; *ktriout = NULL; if( ASN_TAG(ri->CHOICE_field_type) != ASN_CMS_ktri_RecipientInfoFieldTag ) { #if PGP_USE_TRACE { char s[80]; switch( ASN_TAG(ri->CHOICE_field_type) ) { case ASN_CMS_kari_RecipientInfoFieldTag: strcpy( s, "KeyAgreeRecipientInfo" ); break; case ASN_CMS_kekri_RecipientInfoFieldTag: strcpy( s, "KEKRecipientInfo" ); break; default: sprintf( s, "Unknown RecipientInfo choice %d", ASN_TAG(ri->CHOICE_field_type) ); break; } SMIME_TRACE2("RecipientInfo %d is not KeyTransRecipientInfo, it is %s", recipient, s); } #endif return 0; } SMIME_TRACE2("Identified RecipientInfo type as KeyTransRecipientInfo (%02x) for recipient %d", ri->CHOICE_field_type, recipient); ktri = (ASN_CMS_KeyTransRecipientInfo *)ri->data; version = ASN_CMS_GetIntVal( c->asnc, &ktri->version, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking version for recipient %d", recipient); return asnerr; // return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( version != 0 && version != 2 ) { SMIME_TRACE2( "Wrong version %d for recipient %d", version, recipient ); return asnerr; //return SMIMEError_WrongVersion + // (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE2( "Version of KeyTransRecipientInfo is %d for recipient %d", version, recipient ); *ktriout = ktri; return 0; } /* returns index of recipient that matches given certificate according to strict SMIME matching; * -1 if not found. */ int asnGetEnvelopeRecipientIndex( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, const P *x509cert ) { int i; ASN_CMS_Certificate *cert; int asnerr; if( envelopedData->recipientInfos.n==0 ) { SMIME_TRACE("No recipients in enveloped data (should not happen)"); return -1; } /* unpack certificate */ ASN_CMS_UnpackCertificate( c->asnc, &cert, x509cert->p, x509cert->l, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking certificate, cannot match any of %d recipients", envelopedData->recipientInfos.n); return -1; } for( i=0; irecipientInfos.n; i++ ) { ASN_CMS_KeyTransRecipientInfo *ktri; SMIME_TRACE1("Matching recipient %d with cert", i); asnerr = getKTRI( c, envelopedData->recipientInfos.elt[i], i, &ktri ); if( asnerr ) { ASN_CMS_FreeCertificate( c->asnc, cert ); return -1; } if( ktri==NULL ) continue; if( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag) ) { ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber = (ASN_CMS_IssuerAndSerialNumber *)ktri->rid.data; SMIME_TRACE("Match recipient based on IssuerAndSerialNumber"); if( match_IssuerAndSerialNumber_with_cert( issuerAndSerialNumber, cert ) ) { SMIME_TRACE( "Matched cert based on IssuerAndSerialNumber" ); break; } } else if ( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_subjectKeyIdentifier_RecipientIdentifierFieldTag) ) { ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier = (ASN_CMS_SubjectKeyIdentifier*)ktri->rid.data; SMIME_TRACE("Match recipient based on SubjectKeyIdentifier"); if( match_SubjectKeyIdentifier_with_cert( subjectKeyIdentifier, cert ) ) { SMIME_TRACE( "Matched cert based on SubjectKeyIdentifier" ); break; } } else { SMIME_TRACE1("Unknown choice type for KeyTransRecipientInfo %02x", ASN_TAG(ktri->rid.CHOICE_field_type)); continue; } } ASN_CMS_FreeCertificate( c->asnc, cert ); if( irecipientInfos.n ) return i; SMIME_TRACE("Not found any match for certificate"); return -1; } /* get symmetrical algorithm and IV for CBC decryption */ SMIMEError asnGetEnvelopeContentEncrAlg( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, PGPCipherAlgorithm *alg, P *IV ) { ASN_CMS_ContentEncryptionAlgorithmIdentifier *encrAlg; ASN_CMS_IV *iv; int asnerr; PGPByte *p; PGPCipherAlgorithm myalg = kPGPCipherAlgorithm_None; IV->p = NULL; IV->l = 0; *alg = kPGPCipherAlgorithm_None; encrAlg = &envelopedData->encryptedContentInfo.contentEncryptionAlgorithm; if( OIDCMP( &encrAlg->algorithm, ASN_CMS_des_ede3_cbc_OID )==0 ) { /* handle SMIME v3 MUST */ myalg = kPGPCipherAlgorithm_3DES; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_id_aes128_CBC_OID )==0 ) { myalg = kPGPCipherAlgorithm_AES128; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_id_aes192_CBC_OID )==0 ) { myalg = kPGPCipherAlgorithm_AES192; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_id_aes256_CBC_OID )==0 ) { myalg = kPGPCipherAlgorithm_AES256; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_rc2_cbc_OID )==0 ) { /* handle SMIME v3 SHOULD */ SMIME_TRACE("rc2-cbc algorithm recognized for content, but we don't support it"); /* parse RC2CBCParameter to get size from version and IV */ return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( myalg==kPGPCipherAlgorithm_None ) { SMIME_TRACE("Unknown content encryption algorithm found"); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } /* handle supported algorithms */ SMIME_TRACE1("%d algorithm recognized for content", myalg); if( encrAlg->parameters==NULL ) { /* all of supported algoriithms are CBC algoritms */ SMIME_TRACE( "AlgorithmIdentifier's parameters field must be present for CBC algorithm" ); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( encrAlg->parameters->len > 256 /* size beyond the era of quantum computing */ ) { SMIME_TRACE1("IV size %d is too big for %d and even for any known to us alg.", encrAlg->parameters->len); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } ASN_CMS_UnpackIV( c->asnc, &iv, encrAlg->parameters->val, encrAlg->parameters->len, &asnerr ); if( asnerr ) { SMIME_TRACE("Failed to unpack des-ede3-cbc IV"); return ASNErrorToSMIMEError( asnerr, (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING) ); } if( iv->len > (PGPUInt)(-1) ) { /* so we can safely cast later */ return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } /* this is octet string */ p = ASN_CMS_Alloc( c->asnc->memMgr, iv->len ); if( !p ) { ASN_CMS_FreeIV( c->asnc, iv ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES| SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } memcpy( p, iv->val, iv->len ); *alg = myalg; IV->p = p; IV->l = (PGPUInt)iv->len; IV->dontFree = FALSE; ASN_CMS_FreeIV( c->asnc, iv ); SMIME_TRACE5( "Got %d algorithm, IV [%d] %02x %02x %02x", myalg, IV->l, p[0], p[1], p[2] ); return 0; } PGPPublicKeyAlgorithm asnGetEnvelopeRecipientKeyEncrAlg( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, int recipient ) { ASN_CMS_KeyTransRecipientInfo *ktri; (void)c; if( recipient >= envelopedData->recipientInfos.n ) { #if PGP_USE_TRACE if( envelopedData->recipientInfos.n==0 ) SMIME_TRACE1("No recipients (should not happen), asked for %d", recipient); else SMIME_TRACE2("Out of range recipient %d, allowed range [0..%d]", recipient, envelopedData->recipientInfos.n ); #endif return SMIMEError_OutOfRangeIndex + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type) != ASN_CMS_ktri_RecipientInfoFieldTag ) { SMIME_TRACE1("Unsupported RecipientInfo choice %02x", ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type)); return kPGPPublicKeyAlgorithm_Invalid; } ktri = (ASN_CMS_KeyTransRecipientInfo *)envelopedData->recipientInfos.elt[recipient]->data; if( OIDCMP( &ktri->keyEncryptionAlgorithm.algorithm, ASN_CMS_rsaEncryption_OID )==0 ) { SMIME_TRACE1("rsaEncryption algorithm found for recipient %d", recipient); return kPGPPublicKeyAlgorithm_RSA; } SMIME_TRACE1("Didn't recognize recipient public key alg %d (no other algorithms possible then RSA?)", recipient); return kPGPPublicKeyAlgorithm_Invalid; } /* Get encrypted key */ SMIMEError asnGetEnvelopeRecipientESK( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, int recipient, P /*out*/ *keyout ) { ASN_CMS_KeyTransRecipientInfo *ktri; long version; PGPByte *p; int asnerr; keyout->p = NULL; keyout->l = 0; if( recipient >= envelopedData->recipientInfos.n ) { #if PGP_USE_TRACE if( envelopedData->recipientInfos.n==0 ) SMIME_TRACE1("No recipients (should not happen), asked for %d", recipient); else SMIME_TRACE2("Out of range recipient %d, allowed range [0..%d]", recipient, envelopedData->recipientInfos.n ); #endif return SMIMEError_OutOfRangeIndex + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type) != ASN_CMS_ktri_RecipientInfoFieldTag ) { SMIME_TRACE1("Unsupported RecipientInfo choice %02x", ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type)); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } ktri = (ASN_CMS_KeyTransRecipientInfo *)envelopedData->recipientInfos.elt[recipient]->data; version = ASN_CMS_GetIntVal( c->asnc, &ktri->version, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking version for recipient %d", recipient); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); } if( version != 0 && version != 2 ) { SMIME_TRACE2( "Wrong version %d for recipient %d", version, recipient ); return SMIMEError_WrongVersion + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( ktri->encryptedKey.len > (PGPUInt)(-1) ) { /* so we can safely cast later to min 2^32 */ return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } p = ASN_CMS_Alloc( c->asnc->memMgr, ktri->encryptedKey.len ); if( !p ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING|SMIME_ERROR_TYPE_RESOURCES); } memcpy( p, ktri->encryptedKey.val, ktri->encryptedKey.len ); SMIME_TRACE5( "Got [%d bit] %02x %02x %02x encrypted key for recipient %d", ktri->encryptedKey.len*8, p[0], p[1], p[2], recipient ); keyout->p = p; keyout->l = (PGPUInt)ktri->encryptedKey.len; keyout->dontFree = FALSE; return 0; } /* Get possible keyid bytes of the recipient key. */ SMIMEError asnGetEnvelopeRecipientKeyIDBytes(SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, int recipient, PGPByte out[8] ) { ASN_CMS_KeyTransRecipientInfo *ktri; int asnerr; memset(out,0,8); if( recipient >= envelopedData->recipientInfos.n ) { SMIME_TRACE2("Out of range recipient %d, allowed range [0..%d]", recipient, envelopedData->recipientInfos.n ); return SMIMEError_OutOfRangeIndex + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } asnerr = getKTRI( c, envelopedData->recipientInfos.elt[recipient], recipient, &ktri ); if( asnerr ) return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); if( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag) ) { ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber = (ASN_CMS_IssuerAndSerialNumber *)ktri->rid.data; if( issuerAndSerialNumber->serialNumber.len > 8 ) { SMIME_TRACE("getting keyid from recipient based on IssuerAndSerialNumber"); memcpy( out, issuerAndSerialNumber->serialNumber.val+issuerAndSerialNumber->serialNumber.len-8, 8 ); } else { SMIME_TRACE1( "IssuerAndSerialNumber has too short SN (%d bytes) to provide keyid suggestion", issuerAndSerialNumber->serialNumber.len ); return SMIMEError_FieldTooShortToHoldKeyID + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } } else if ( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_subjectKeyIdentifier_RecipientIdentifierFieldTag) ) { ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier = (ASN_CMS_SubjectKeyIdentifier*)ktri->rid.data; if( subjectKeyIdentifier->len > 8 ) { SMIME_TRACE("getting keyid from recipient based on SubjectKeyIdentifier"); memcpy( out, subjectKeyIdentifier->val+subjectKeyIdentifier->len-8, 8 ); } else { SMIME_TRACE1( "SubjectKeyIdentifier has too short value (%d bytes) to provide keyid suggestion", subjectKeyIdentifier->len ); return SMIMEError_FieldTooShortToHoldKeyID + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } } else { SMIME_TRACE1("Unknown choice type for KeyTransRecipientInfo %02x", ASN_TAG(ktri->rid.CHOICE_field_type)); pgpAssert(0); } return 0; } SMIMEError asnGetEnvelopedEncrContent( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, P *encrContent ) { ASN_CMS_EncryptedContent *encryptedContent; (void)c; encrContent->p = NULL; encrContent->l=0; /* I changed CMS definition to make EnvelopedData->encryptedContentInfo->encryptedContent mandatory * as required by SMIME. This eliminates one check here and make encryption simplier */ encryptedContent = &envelopedData->encryptedContentInfo.encryptedContent; SMIME_TRACE1("Have encrypted content of %d bytes; point to it without copying", encryptedContent->len); if( encryptedContent->len > (PGPUInt)(-1) ) { /* so we can safely cast to min 2^32 later */ return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } encrContent->p = encryptedContent->val; encrContent->l = (PGPUInt)encryptedContent->len; encrContent->dontFree = TRUE; return 0; } #if SMIME_TEST void test_smime_decrypt( PGPContextRef sdkcontext, P *smime_der, P *cert_der ) { SMIME_CONTEXT c; SMIMEError err; int recipients; int index; err = asnInitSMIMEContext( sdkcontext, &c ); SMIME_TRACE1( "asnInitSMIMEContext returned %08x", err ); err = asnProcessEnvelopedData( &c, smime_der ); SMIME_TRACE1( "asnProcessEnvelopedData returned %08x", err ); if( err ) { asnFreeSMIMEContext( &c ); return; } recipients = asnGetNumberOfEnvelopeRecipients( &c, c.envelopedData ); SMIME_TRACE1( "%d recipients", recipients ); index = asnGetEnvelopeRecipientIndex( &c, c.envelopedData, cert_der ); SMIME_TRACE1( "%d is the index of matched? recipient", index ); if( index != -1 ) { P key; P iv; PGPPublicKeyAlgorithm alg; PGPCipherAlgorithm encrAlg; unsigned i; err = asnGetEnvelopeRecipientESK( &c, c.envelopedData, index, &key ); SMIME_TRACE1( "asnGetEnvelopeRecipientESK returned %08x", err ); pgpSMIMEFreePtr( &key ); alg = asnGetEnvelopeRecipientKeyEncrAlg( &c, c.envelopedData, index ); printf("Recipient %d has alg %d\n", index, alg); if( !asnGetEnvelopeContentEncrAlg( &c, c.envelopedData, &encrAlg, &iv ) ) { printf("Got encrAlg %d\n[%d] ", encrAlg, iv.l); for( i=0; itƹmBAb8^,Z[Z\$goH:@JuJ>/9+@pԝ]Yb;K)]Lti8t }XpVjsh'R !M$)2ꫵ5KO]FvrL2G.boQZ1YOO']㚫̣QuS;`Ϸ i;gJdI)o5Y?16V '``h5Kep=*YH&>JZ^ˤr5.ˢ[%``|1Y5Ѐs<ȫy .b$ lNNӖQPMZx md9SLҦj$ cҖHi>M4ٟUa$b-K@ gU*y35WIr7Qtnm*\?=awЄ#+{I`cJ<=>@tbUshq=)9]A٭jne cߝ3N#B5V`'dtG eY2L5*e.).r@;G6T)Oă 88EY m~*ap;J4Rf=zQ{ L, p`DbeIMa|FH?V 4$Bnd+N9 341ǯ*h9 "D* *}^;8I2 H/ى+O?ޘzKf \rL.R7f/Nʰd }hWI7`品OWQQ>F[QG) j$?Yre4vǥp57<`4[l{PR3n:t L۷'`[CzaYC'̴ ie3[xFy cv F"zs􆚥9Ec~*p ~mUv{5se;ˠ9 =*F]OQծ˵Kc]i GYIN$[LaTڜ,nZ92 I yޅ JMi"[ު8 F!yRISw<[z?EɗN\w >Y2q,yVm#b3'j-y"'}jdw~f(a+©5@FW<'mNB2Պst X2}*/sxv w]܆C_"gr5V Ou4kT>к~E(yyKEV죀ҵPhPJLEbvR‚LsVrZ+?@vDdJ28iGu *FH3p ]}L=LROZyϔ7Wq9UE nl%`PQ)I㵡0Uh1OPy<,X(aИnXtCmf>?ه(wz՞j^@fuэ20ݲì[B= i1f"3]];ۼ 9HWtrl1=k\m7*HP dO*awfCB9};ml!$ds*Hs/H^yA76GZ+ {=Jݯ$̖䟩,*@#q"'F9dTUUQ 񙜒GZH(:R"ޑ%O+?"4w/vc]Hs0M -l+t^޺(p2&YLBK˼cJ퍑b'-'6m"!F M\(  }KiU@,F?^nɵD Xel ʇO5)0ur^qIvnN-&4`ݖms Hԗ*mkU2h &I% ٳJA?UNKI*$m|# =k]VmtIkpCp3M^3Fƙ^,]!dI:u-n9ӟ<2 'FOK7o3Q2L‘6A8<<k25f |=hݳon |1ȁZۯj!휑9qEW% &zgj@Gil@F2r1hQm}yQnҵ?ROe0OL*\)J& 3$#%[0 ҦcKetqpOC.`W$?s(F yDѹ$"1/&R Tdw pﳲo3icګQzb g'i #w(yd&|s+EWOsi {O#RH#"NZ6&blebe- LQT;\ranɕK(.G3Im neC1W>Tа(3gUR QUQWcv=*|A316B)u^ѰA9DLArrIqHe;1tŠbeds4UGǼ]N2zӅ7!Jv1_M:=8?U~UDR@C'GAt-*ŦdZWpЉ9ބ:-,Mؔ"ݝ{9mmϙ?Jde!bT8^4/*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides common routines for lowest-level interface to ASN.1 DER * compiler. We limit DER encoding/decoding routines to this and * similiar files with Verify,Sign,Encrypt,Decrypt suffixes so that changes in * ASN.1 definition or porting to new ASN.1 compiler will be limited to these file. * * There are no SDk objects here, only SDK constants * * The interface between this layer and next level -- CMS layer -- are * PGPSMIMEPtr buffers or opaque pointers to compiler-generated types. * * $Id: pgpSMIMEasn.c,v 1.3 2004/01/09 02:08:33 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" #include "pgpX509Priv.h" #include "pgpTimeDate.h" #include "pgpStrings.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" #if PGP_USE_TRACE #include /* The file is intended to be __FILE__ compile macro. * It appears to be char * even for Unicode */ void pgpSMIMETrace(const char *file, int line, const PGPChar *fmt, ...) { va_list marker; PGPChar s[2000]; PGPChar s2[2048]; const char *p = strrchr( file, '\\' ); if( p ) file = p+1; va_start( marker, fmt ); vsprintf( s, fmt, marker ); va_end( marker ); /* TODO: logging for other platforms */ #if PGP_UNICODE swprintf( s2, L"%s(%d): %ls\n", file, line, s ); #if PGP_WIN32 OutputDebugString( s2 ); #else wprintf( s2 ); #endif #else sprintf( s2, PGPTXT_MACHINE8("%s(%d): %s\n"), file, line, s ); #if PGP_WIN32 OutputDebugString( s2 ); #else printf( s2 ); #endif #endif } #endif /* PGP_USE_TRACE */ /* Converts ASN.1 compiler error into SMIME error */ SMIMEError ASNErrorToSMIMEError( int asnerr, SMIMEError flags ) { if( asnerr < 0 ) asnerr = -asnerr; if( asnerr > SMIMEError_EncodingMax ) return flags + SMIMEError_ErrorOverflow; return flags + asnerr; } /* 3 ASN memory allocation routines */ static void *SMIME_Alloc( ASN_CMS_MemoryMgr *mem, size_t requestSize ) { /* SMIME_TRACE1("\tASN allocation request for %d bytes", requestSize); */ return (PGPNewData ((PGPMemoryMgrRef) mem->customValue, requestSize, 0)); } static int SMIME_Free( ASN_CMS_MemoryMgr *mem, void *allocation ) { (void) mem; /* SMIME_TRACE("\tASN free request"); */ if( allocation ) PGPFreeData (allocation); return 0; } static int SMIME_Realloc ( ASN_CMS_MemoryMgr *mem, void **allocation, size_t requestSize) { /* SMIME_TRACE1("\tASN realloc request for %d bytes", requestSize); */ return PGPReallocData ((PGPMemoryMgrRef) mem->customValue, allocation, requestSize, 0); } static ASN_CMS_MemoryMgr SMIME_MemMgr = { NULL, SMIME_Alloc, SMIME_Realloc, SMIME_Free }; /* Compare parsed OID agains a given static OID * function is suitable for OID ordering */ int oidcmp( const ASN_CMS_OBJECT_ID *oid1, const unsigned char *oid2, size_t oid2_size ) { size_t l; int r; if( oid1->len == oid2_size ) return memcmp( oid1->val, oid2, oid2_size ); l = (oid1->len < oid2_size) ? oid1->len : oid2_size; r = memcmp( oid1->val, oid2, l ); if( r!=0 ) return r; /* equal prefix */ return (oid1->len < oid2_size) ? -1 : 1; } /* compares Name objects, assuming they are depresented as ANY */ int namecmp( ASN_CMS_Name_opaque *name1, ASN_CMS_Name_opaque *name2 ) { if( name1->len != name2->len ) { SMIME_TRACE2("Names have different lengths for DNs: %d vs %d", name1->len, name2->len); return name1->len < name2->len ? -1 : 1; } return memcmp( name1->val, name2->val, name1->len ); } /* compares Certificate's SNs that are represented similiar to ANY even though they are INTEGERs */ int sncmp( ASN_CMS_CertificateSerialNumber *sn1, ASN_CMS_CertificateSerialNumber *sn2 ) { /*SMIME_TRACE5("Comparing serial numbers [%d] %02x %02x and [%d] %02x", sn1->len, sn1->val[0], sn1->val[1], sn2->len, sn2->val[0] );*/ if( sn1->len != sn2->len ) { SMIME_TRACE2("SNs have different lengths: %d vs %d", sn1->len, sn2->len); return sn1->len < sn2->len ? -1 : 1; } return memcmp( sn1->val, sn2->val, sn1->len ); } SMIMEError setoid( SMIME_CONTEXT *smime, const unsigned char *oid, size_t oid_size, ASN_CMS_OBJECT_ID *oid_obj ) { unsigned char *p; memset( oid_obj, 0, sizeof(*oid_obj) ); p = ASN_CMS_Alloc( smime->asnc->memMgr, oid_size ); if( p==NULL ) return SMIMEError_NoMem; memcpy( p, oid, oid_size ); oid_obj->val = p; oid_obj->len = oid_size; return 0; } SMIMEError setnull( SMIME_CONTEXT *smime, ASN_CMS_ANY *any ) { any->val = ASN_CMS_Alloc( smime->asnc->memMgr, 2 ); if( any->val==NULL ) { return SMIMEError_NoMem; } any->len = 2; any->val[0] = 0x05; /* ANY tag */ any->val[1] = 0x00; /* len is 0 */ return 0; } #if SMIME_TEST /* there are routines in SDK CMS (where CMS is it Certificate Management System), but they deal with PKITime * redefined to TC_Time. PKITime is defined in cert.asn. * Those time conversion routines support more formats then CMS * (in true meaning: Cryptographic Message Syntax) allows, so we reimplement time-relevant code here */ SMIMEError ___gettm( ASN_CMS_Time *asntime, struct tm *tmout ) { struct tm tm; PGPByte timestr[80]; memset(tmout, 0, sizeof(*tmout)); /* Dates between Jan 1 1950 and Dec 31 2049 must be stored as UTCTime */ if( ASN_TAG(asntime->CHOICE_field_type) == ASN_CMS_utcTime_TimeFieldTag ) { ASN_CMS_UTCTime *utcTime; int i; SMIME_TRACE("Field type is UTCTime YYMMDDHHMMSSZ"); utcTime = (ASN_CMS_UTCTime *)asntime->data; #if PGP_USE_TRACE { unsigned size = utcTime->len; if( size > sizeof(timestr)-1 ) size = sizeof(timestr)-1; memcpy( timestr, utcTime->val, size ); timestr[size] = '\0'; } #endif /* YYMMDDHHMMSSZ, were Z is verbatium */ memset( &tm, 0, sizeof(tm) ); if( utcTime->len != 13 ) { SMIME_TRACE1("UTCTime is too short: format must be YYMMDDHHMMSSZ, passed %s", timestr); return SMIMEError_CorruptData + SMIME_ERROR_CATEGORY_ERROR; } i = sscanf( utcTime->val, "%02u%02u%02u%02u%02u%02uZ", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec ); if( i != 6 || tm.tm_mon==0 || tm.tm_mday==0 ) { SMIME_TRACE2("Expected 6 fields in time format YYMMDDHHMMSSZ, but found only %d for %s", i, timestr); return SMIMEError_CorruptData + SMIME_ERROR_CATEGORY_ERROR; } /* in tm everything is zero-based, except tm_mday */ tm.tm_mon --; if( tm.tm_year < 50 ) tm.tm_year += 100; if( tm.tm_mon >= 12 || tm.tm_mday > 31 || tm.tm_mday==0 || tm.tm_hour>=24 || tm.tm_min>=60 || tm.tm_sec >=60 ) { SMIME_TRACE1("Some of UTCTime components are out of range for %s", timestr); } SMIME_TRACE2("Succesefully parsed UTCTime %s as %s", timestr, asctime(&tm)); *tmout = tm; return 0; } else if( ASN_TAG(asntime->CHOICE_field_type) == ASN_CMS_generalTime_TimeFieldTag ) { /* ASN_CMS_GeneralizedTime *generalizedTime; */ SMIME_TRACE("Field type is GeneralizedTime, that must be used after Dec 31 2049"); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_NOT_IMPL; } else { SMIME_TRACE1("Unknown Time field type 0x%02x", ASN_TAG(asntime->CHOICE_field_type)); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_LOGICAL_ERROR; } } #endif /* SMIME_TEST */ SMIMEError gettime( ASN_CMS_Time *asntime, time_t *timet ) { #if PGP_USE_TRACE PGPByte timestr[80]; #endif *timet = 0; /* Dates between Jan 1 1950 and Dec 31 2049 must be stored as UTCTime */ if( ASN_TAG(asntime->CHOICE_field_type) == ASN_CMS_utcTime_TimeFieldTag ) { ASN_CMS_UTCTime *utcTime; PGPUInt32 time32; SMIME_TRACE("Field type is UTCTime YYMMDDHHMMSSZ"); utcTime = (ASN_CMS_UTCTime *)asntime->data; #if PGP_USE_TRACE { unsigned size = utcTime->len; if( size > sizeof(timestr)-1 ) size = sizeof(timestr)-1; memcpy( timestr, utcTime->val, size ); timestr[size] = '\0'; } #endif /* YYMMDDHHMMSSZ, were Z is verbatium */ if( utcTime->len != 13 ) { SMIME_TRACE1("UTCTime is too short: format must be YYMMDDHHMMSSZ, passed %s", timestr); return SMIMEError_CorruptData + SMIME_ERROR_CATEGORY_ERROR; } time32 = (PGPUInt32)pgpDecodeUTCTime (utcTime->val, utcTime->len, FALSE/*generalized*/); if( time32!=0 ) { *timet = (time_t)time32; SMIME_TRACE2("Succesefully parsed UTCTime %s as %s", timestr, ctime(timet)); return 0; } else { SMIME_TRACE("Failed to decode UTCTime"); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_ERROR; } } else if( ASN_TAG(asntime->CHOICE_field_type) == ASN_CMS_generalTime_TimeFieldTag ) { /* ASN_CMS_GeneralizedTime *generalizedTime; */ SMIME_TRACE("Field type is GeneralizedTime, that must be used after Dec 31 2049"); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_NOT_IMPL; } else { SMIME_TRACE1("Unknown Time field type 0x%02x", ASN_TAG(asntime->CHOICE_field_type)); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_LOGICAL_ERROR; } } #if SMIME_TEST /* not used */ SMIMEError ___settm( SMIME_CONTEXT *smime, struct tm *tm, ASN_CMS_Time *asntime ) { /* Dates between Jan 1 1950 and Dec 31 2049 must be stored as UTCTime */ if( tm->tm_year < 150 ) { ASN_CMS_UTCTime *utcTime; PGPByte *timestr; int y; SMIME_TRACE("Encoding date as UTCTime YYMMDDHHMMSSZ"); utcTime = ASN_CMS_NewUTCTime( smime->asnc ); if( utcTime == NULL ) return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_TYPE_RESOURCES); timestr = ASN_CMS_Alloc( smime->asnc->memMgr, 16 ); if( timestr==NULL ) { ASN_CMS_FreeUTCTime( smime->asnc, utcTime ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_TYPE_RESOURCES); } y = tm->tm_year; if( y > 100 ) y -= 100; sprintf( timestr, "%02u%02u%02u%02u%02u%02uZ", y, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec ); utcTime->len = strlen( timestr ); utcTime->val = timestr; asntime->CHOICE_field_type = ASN_CMS_utcTime_TimeFieldTag; asntime->data = utcTime; SMIME_TRACE1("Exported UTCTime as %s", timestr); return 0; } else { /* ASN_CMS_GeneralizedTime *generalizedTime; */ /* asntime->CHOICE_field_type = ASN_CMS_generalTime_TimeFieldTag; */ SMIME_TRACE("Encoding date as GeneralizedTime YYYYMMDDHHMMSSZ"); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_NOT_IMPL; } } #endif /* SMIME_TEST */ SMIMEError settime( SMIME_CONTEXT *smime, PGPTime pgptime, ASN_CMS_Time *asntime ) { PGPChar8 buf[PGPX509TIMELEN+1]; int size; PGPBoolean isUTCtime; size = pgpTimeToASNTime( pgptime, buf, &isUTCtime ); #if 0 && PGP_USE_TRACE { struct tm tm; struct tm tm2; time_t timet = (time_t)time(NULL); time_t timet2; SMIME_TRACE2("timet=%08x pgptime=%08x", timet, pgptime); gmtime_r( &timet, &tm ); settm( smime, &tm, asntime ); gettm( asntime, &tm2 ); timet2 = mktime( &tm2 ); SMIME_TRACE1("timet2=%08x", timet2); return 0; } #endif if( isUTCtime ) { ASN_CMS_UTCTime *utcTime; PGPByte *timestr; SMIME_TRACE1("Encoding date as UTCTime YYMMDDHHMMSSZ %s", buf); utcTime = ASN_CMS_NewUTCTime( smime->asnc ); if( utcTime == NULL ) return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_TYPE_RESOURCES); timestr = ASN_CMS_Alloc( smime->asnc->memMgr, size+1 ); if( timestr==NULL ) { ASN_CMS_FreeUTCTime( smime->asnc, utcTime ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_TYPE_RESOURCES); } memcpy( timestr, buf, size ); timestr[size] = '\0'; utcTime->len = size; pgpAssert( utcTime->val==NULL ); utcTime->val = timestr; asntime->CHOICE_field_type = ASN_CMS_utcTime_TimeFieldTag; pgpAssert( asntime->data==NULL ); asntime->data = utcTime; SMIME_TRACE1("Exported UTCTime as %s", timestr); return 0; } else { /* ASN_CMS_GeneralizedTime *generalizedTime; */ /* asntime->CHOICE_field_type = ASN_CMS_generalTime_TimeFieldTag; */ SMIME_TRACE("Encoding date as GeneralizedTime YYYYMMDDHHMMSSZ"); return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_NOT_IMPL; } } /* This function peeks for OID from ContentType without unpacking whole object * It is efficient for potentially large ASN.1 objects, but assumes ASN.1 definition * of ContentType, know ASN.1 DER encoding and the length of supported OIDs */ static SMIMEError getContentTypeOIDByPeeking( SMIME_CONTEXT *smime, PGPByte der[16], ASN_CMS_OBJECT_ID **oid_obj ) { size_t length; size_t tagsize; int asnerr=0; *oid_obj = NULL; tagsize = ASN_CMS_TakeTag( der, 0x30, &length ); if( tagsize == 0 ) { SMIME_TRACE4("Failed to parse DER %02x %02x %02x %02x as SEQUENCE", der[0], der[1], der[2], der[3]); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_ENCODING_DECODING); } ASN_CMS_UnpackOBJECT_ID( smime->asnc, oid_obj, der+tagsize, 11 /* object tag + one byte length + 9 byte OID */, &asnerr ); if( asnerr ) { SMIME_TRACE5("After unpacking OID %02x %02x %02x %02x asnerr=%d", der[tagsize], der[tagsize+1],der[tagsize+2],der[tagsize+3],asnerr); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_ENCODING_DECODING ); } return 0; } SMIMEError asnContentInfoToInputFormat( SMIME_CONTEXT *smime, P *der, PGPInputFormat *format ) { ASN_CMS_OBJECT_ID *contentType_oid; SMIMEError err; *format = kPGPInputFormat_Unknown; if( der->l < 16 ) return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_ENCODING_DECODING); err = getContentTypeOIDByPeeking( smime, der->p, &contentType_oid ); if( err ) { SMIME_TRACE1("Could not recongnize ContentInfo by peeking inside it for OID, smimeerr=%08x", err); return err; } if( OIDCMP(contentType_oid, ASN_CMS_id_signedData_OID )==0 ) { SMIME_TRACE("id-signedData detected"); *format = kPGPInputFormat_SMIMEBodySignedData; } else if( OIDCMP(contentType_oid, ASN_CMS_id_envelopedData_OID )==0 ) { SMIME_TRACE("id-envelopedData detected"); *format = kPGPInputFormat_SMIMEBodyEncryptedData; } else { SMIME_TRACE("Unknown ContentType"); } ASN_CMS_FreeOBJECT_ID( smime->asnc, contentType_oid ); return 0; } #if SMIME_TEST /* Given a DER-encoded Name, extract e-mail from it. Returns ASN.1 compiler error */ static PGPByte const emailoid[] = { 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x01 }; const int emailoid_LEN = sizeof(emailoid); int not_tested___getemail( SMIME_CONTEXT *smime, const P *name_der, P *email ) { ASN_CMS_Name *name; int err; int i; email->p = NULL; email->l = 0; ASN_CMS_UnpackName( smime->asnc, &name, name_der->p, name_der->l, &err ); if( err ) { SMIME_TRACE1("Cannot unpack Name (err=%d)", err); return err; } for( i=0; in; i++ ) { int j; ASN_CMS_RelativeDistinguishedName *rdn = name->elt[i]; for( j=0; jn; j++ ) { ASN_CMS_AttributeTypeAndDistinguishedValue *attr_value = rdn->elt[j]; if( OIDCMP( &attr_value->type, emailoid )==0 ) { ASN_CMS_PrintableString *printstruct; PGPByte *p; SMIME_TRACE5("Found e-mail DER value [%d] %02x %02x %02x %02x", attr_value->value.len, attr_value->value.val[0], attr_value->value.val[1], attr_value->value.val[2], attr_value->value.val[3] ); ASN_CMS_UnpackPrintableString( smime->asnc, &printstruct, attr_value->value.val, attr_value->value.len, &err ); if( !err ) { SMIME_TRACE1("Error %d unpacking e-mail DER string as PrintableString", err); continue; } p = ASN_CMS_Alloc( smime->asnc->memMgr, printstruct->len+1 ); if( !p ) { SMIME_TRACE1("No memory allocating %d bytes for e-mail", printstruct->len+1 ); ASN_CMS_FreePrintableString( smime->asnc, printstruct ); continue; } /* Found e-mail, set it and return */ memcpy( p, printstruct->val, printstruct->len ); p[printstruct->len] = '\0'; SMIME_TRACE1("Found e-mail <%s>", p); email->p = p; email->l = printstruct->len; ASN_CMS_FreePrintableString( smime->asnc, printstruct ); ASN_CMS_FreeName( smime->asnc, name ); return 0; } } } ASN_CMS_FreeName( smime->asnc, name ); SMIME_TRACE("Could not find any RDN e-mail in the Name"); return 0; } #endif /* SMIME_TEST */ #if PGP_USE_TRACE /*debug*/ const PGPChar * asn1comp_err(int err) { const PGPChar *p = PGPTXT_MACHINE("Unknown ASN.1 error"); switch( err ) { case ASN_CMS_ErrPackUnderrun: p = PGPTXT_MACHINE("ErrPackUnderrun"); break; case ASN_CMS_ErrPackOverrun: p = PGPTXT_MACHINE("ErrPackOverrun"); break; case ASN_CMS_ErrPackSEQOFArrayTooLong: /* lth > MAX of that type */ p = PGPTXT_MACHINE("ErrPackSEQOFArrayTooLong"); break; case ASN_CMS_ErrPackNoBlock: /* ASN block ptr is NULL */ p = PGPTXT_MACHINE("ErrPackNoBlock"); break; case ASN_CMS_ErrUnpackNoStructure: /* block pointer is NULL */ p = PGPTXT_MACHINE("ErrUnpackNoStructure"); break; case ASN_CMS_ErrUnpackNoBlockPtr: /* ASN block pointer pointer is NULL */ p = PGPTXT_MACHINE("ErrUnpackNoBlockPtr"); break; case ASN_CMS_ErrUnpackNoBlock: /* ASN block pointer is NULL */ p = PGPTXT_MACHINE("ErrUnpackNoBlock"); break; case ASN_CMS_ErrUnpackOverrun: p = PGPTXT_MACHINE("ErrUnpackOverrun"); break; case ASN_CMS_ErrUnpackUnderrun: p = PGPTXT_MACHINE("ErrUnpackUnderrun"); break; case ASN_CMS_ErrUnpackBooleanLth: /* a boolean block with lth != 1 */ p = PGPTXT_MACHINE("ErrUnpackBooleanLth"); break; case ASN_CMS_ErrUnpackTaggedLth: /* a context tag lth failed to match the length of the contents */ p = PGPTXT_MACHINE("ErrUnpackTaggedLth"); break; case ASN_CMS_ErrUnpackReqMissing: /* a required substructure is missing */ p = PGPTXT_MACHINE("ErrUnpackReqMissing"); break; case ASN_CMS_ErrUnpackNullLth: /* a NULL block with lth != 0 */ p = PGPTXT_MACHINE("ErrUnpackReqMissing"); break; case ASN_CMS_ErrPackSETOFArrayTooLong: /* lth > MAX of that type */ p = PGPTXT_MACHINE("ErrPackSETOFArrayTooLong"); break; case ASN_CMS_ErrPackSETOFUnsortable: /* SET OF with identical elements */ p = PGPTXT_MACHINE("ErrPackSETOFUnsortable"); break; case ASN_CMS_ErrOutOfMemory: /* Out of memory */ p = PGPTXT_MACHINE("ErrOutOfMemory"); break; case ASN_CMS_ErrPackBufferTooShort: /* provided buffer space too short */ p = PGPTXT_MACHINE("ErrPackBufferTooShort"); break; case ASN_CMS_ErrUnpackInvalidEncoding: p = PGPTXT_MACHINE("ErrUnpackInvalidEncoding"); break; case ASN_CMS_ErrBadContext: p = PGPTXT_MACHINE("ErrBadContext"); break; case ASN_CMS_ErrUnpackSetBadType: p = PGPTXT_MACHINE("ErrUnpackSetBadType"); break; case ASN_CMS_ErrUnpackDuplicateField: p = PGPTXT_MACHINE("ErrUnpackDuplicateField"); break; case 0: p = PGPTXT_MACHINE("(no error)"); default: break; } return p; } #endif /* SMIME_TEST */ SMIMEError asnInitSMIMEContext( PGPContextRef sdkcontext, SMIME_CONTEXT *c ) { PGPMemoryMgrRef sdkmem = PGPPeekContextMemoryMgr (sdkcontext); /* Set up convenience pointer */ c->asnc = &c->asn_context_obj; c->asnc->customValue = NULL; /* setup SDK context */ c->sdkc = sdkcontext; /* ----- setup memory namager for ASN.1 generated code ----- */ /* point the pointer to internal object in SMIME context */ c->asnc->memMgr = &c->asn_memMgr_obj; /* Initialize it with function pointers to SDK mem. routines */ c->asn_memMgr_obj = SMIME_MemMgr; /* Store SDK memory manager inside this object */ c->asn_memMgr_obj.customValue = sdkmem; /* clear ASN structures */ c->signedData = NULL; c->envelopedData = NULL; return 0; } /* TODO: move parts to content type - specific files */ SMIMEError asnFreeSMIMEContext( SMIME_CONTEXT *c ) { if( c->signedData ) { ASN_CMS_FreeSignedData( c->asnc, c->signedData ); SMIME_TRACE1( "Freed signed data %p", c->signedData ); } if( c->envelopedData ) { ASN_CMS_FreeEnvelopedData( c->asnc, c->envelopedData ); SMIME_TRACE1( "Freed enveloped data %p", c->envelopedData ); } memset( c, 0, sizeof(*c) ); return 0; } /*__Editor_settings____ Local Variables: tab-width: 4 End: vi: ts=4 sw=4 vim: si _____________________*/ pedData, &encrAlg, &iv ) ) { printf("Got encrAlg %d\n[%d] ", encrAlg, iv.l); for( i=0; iQ=d:@[T;|fFޚQIM %DZCoCmf鑁1SJiȝ#hj51fƛ4դHyH1K\ﮋBLG1&k @=jLj@c%%.٫=u_]ڨ;Y@)Pk.E=CGJFfw3xOځtirN'!Çx+U?K€VҭYc_LV^V˒!z|V gԙj`3]iK-O&Z o K'Vv%RĨxvK?&% sfh`p) zy6(-IIf=3CҐ\ X2=U6%5DO[g+l_<P¸h=2iW_>%0XGF8Jmjhʔ~@<&j]G*&nSDCGݴ{Moh 7:sz#i2@x v.܆ X"1ݸ@w *wb)+8RP2&28]@9M,q;p|#NqN[r@H'8I~`s30THqIc?@B0' N p#jOXb'rPg>`a9[ :''@MX{.YpIw )(ƾEө'ur . RM7Ť ol+GXd ͮy3l|BAeB5;)t7lHw,[ŻK&OݓyA겤tXAX;1 Bm?TxeH9K7-2An~t텖}`R fgb36 ;zF?{Ofvߙ54‰A),/c |cE.g1ً=e;m<[B TLZ+x8t D&nc},%rAZt`\pV,H83Hq +# ,4m^ /yK -x'Yp1$~)ݣTm1PXESs%F 41m- ' Y8?ƤO/Zm $A FyPvR">q^>"w2@qOp$4 f),n\b}w[lSĒrtVW\YCO<[vl,J|-H਷5oh NV۴'pe@D|A=q-ި?*􎘳 I=k#,\ k&UO[D.G[1 MdnI@Ux4J65cn#ڏ9_#E}AGNJj-PY@ LiwroouRO\XHV2$pz3:~[8 ءIQ=+?Y&Xs5J*.b9^&=&9>e͟FlrЛ8m5pTq8&LIÊ0TIę'b+a%G=(SH /ȸh>ϔN3hoY5Fႅ(f56k;Hv fyU[RBTA|t_ZR/&-1$LIl-o?.8Sŀб$gvZ}YbS^$UyFE"Sڝ-& v q9˽ lftw{i(ĖJLĠU wmc_R'j.Owb7enI > #gfԂBd͵VpnZZIe܃e9#%?0 h N1˜jw) ݁Nڽ|6ـ$n$P ,~Z(U _qdK˶Q5)v"죰q|Gص0+;m`ʳ+vݲ- bn^fUR8Ʊ߁ۙ kM@"5jvȓ\_,Bp ]\aX dUV^>hҕ)T>!mo/*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 routines needed for * encryption in SMIME. * * $Id: pgpSMIMEasnEncrypt.c,v 1.2 2003/05/14 00:45:28 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" SMIMEError asnCreateEnvelopedData( SMIME_CONTEXT *smime, int recipients ) { ASN_CMS_EnvelopedData *envelopedData; SMIMEError smimeerr; int recipient; SMIME_TRACE1("Building top level EnvelopedData for %d recipients", recipients); envelopedData = ASN_CMS_NewEnvelopedData(smime->asnc); if( envelopedData==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Version 0. OriginatorInfo is absent, RecipientInfo structures are version 0 (see bellow), UnprotectedAttributes is absent */ ASN_CMS_PutIntVal( smime->asnc, &envelopedData->version, 0 ); envelopedData->recipientInfos.n = recipients; envelopedData->recipientInfos.elt = ASN_CMS_Alloc( smime->asnc->memMgr, recipients * sizeof(ASN_CMS_RecipientInfo*) ); if( envelopedData->recipientInfos.elt==NULL ) { envelopedData->recipientInfos.n = 0; ASN_CMS_FreeEnvelopedData( smime->asnc, envelopedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } memset( envelopedData->recipientInfos.elt, 0, recipients * sizeof(ASN_CMS_RecipientInfo*) ); /* create recipients, allocate memory and set as much fields as we can here */ smimeerr=0; for( recipient=0; recipientasnc ); if( ri==NULL ) { SMIME_TRACE1( "Failed to allocate RecipientInfo for recipient %d", recipient ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } /* RecipientInfo for us always means KeyTransRecipientInfo */ ktri = ASN_CMS_NewKeyTransRecipientInfo( smime->asnc ); if( ktri == NULL ) { SMIME_TRACE1( "Failed to allocate KeyTransRecipientInfo for recipient %d", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } pgpAssert( ri->data==NULL ); ri->data = ktri; ri->CHOICE_field_type = ASN_CMS_ktri_RecipientInfoFieldTag; /* SMIME_TRACE2("Attached ktri %p for recipient %d", ktri, recipient); */ /* Version 0. RecipientIdentifier is IssueAndSerialNumber, not SubjectKeyIdentifier */ ASN_CMS_PutIntVal( smime->asnc, &ktri->version, 0 ); /* Construct IssuerAndSerialNumber */ ktri->rid.data = ASN_CMS_NewIssuerAndSerialNumber( smime->asnc ); if( ktri->rid.data==NULL ) { SMIME_TRACE1( "Failed to allocate IssuerAndSerialNumber for recipient %d", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } ktri->rid.CHOICE_field_type = ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag; /* Construct OPTIONAL parameters field for KeyEncryptionAlgorithmIdentifier */ ktri->keyEncryptionAlgorithm.parameters = ASN_CMS_NewANY( smime->asnc ); if( ktri->keyEncryptionAlgorithm.parameters==NULL ) { SMIME_TRACE1( "Failed to allocate ANY for recipient %d's KeyEncryptionAlgorithm parameters", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } /* ... and initialize it with NULL */ smimeerr = setnull( smime, ktri->keyEncryptionAlgorithm.parameters ); if( smimeerr ) { SMIME_TRACE1( "Failed to set ANY to NULL for recipient %d's KeyEncryptionAlgorithm parameters", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr |= (SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } /* Finally attach RecipientInfo */ envelopedData->recipientInfos.elt[recipient] = ri; } /* for each recipient... */ if( smimeerr ) { ASN_CMS_FreeEnvelopedData( smime->asnc, envelopedData ); return smimeerr; } { ASN_CMS_EncryptedContentInfo *encryptedContentInfo = &envelopedData->encryptedContentInfo; SETOID( smime, ASN_CMS_id_data_OID, &encryptedContentInfo->contentType ); encryptedContentInfo->contentEncryptionAlgorithm.parameters = ASN_CMS_NewANY( smime->asnc ); if( encryptedContentInfo->contentEncryptionAlgorithm.parameters==NULL ) { SMIME_TRACE("Failed to create ANY for parameters of EncryptedContentInfo->ContentEncryptionAlgorithIdentifier"); ASN_CMS_FreeEnvelopedData( smime->asnc, envelopedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } } /* encryptedContentInfo */ if( smime->envelopedData!=NULL ) { SMIME_TRACE1("Had old envelopedData %p in the context, clean it", smime->envelopedData); ASN_CMS_FreeEnvelopedData( smime->asnc, smime->envelopedData ); } smime->envelopedData = envelopedData; SMIME_TRACE1("Added envelopedData %p to the context", smime->envelopedData); return 0; } /* CBC mode is assumed for 'alg' */ SMIMEError asnSetEnvelopeContentEncrAlg( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, const PGPCipherAlgorithm alg, const P *IV ) { ASN_CMS_ContentEncryptionAlgorithmIdentifier *contentEncryptionAlg; SMIMEError smimeerr; contentEncryptionAlg = &envelopedData->encryptedContentInfo.contentEncryptionAlgorithm; SMIME_TRACE5("Setting %d encryption algorithm, IV [%d] %02x %02x %02x", alg, IV->l, IV->p[0], IV->p[1], IV->p[2] ); switch( alg ) { case kPGPCipherAlgorithm_3DES: smimeerr = SETOID( smime, ASN_CMS_des_ede3_cbc_OID, &contentEncryptionAlg->algorithm ); break; case kPGPCipherAlgorithm_AES128: smimeerr = SETOID( smime, ASN_CMS_id_aes128_CBC_OID, &contentEncryptionAlg->algorithm ); break; case kPGPCipherAlgorithm_AES192: smimeerr = SETOID( smime, ASN_CMS_id_aes192_CBC_OID, &contentEncryptionAlg->algorithm ); break; case kPGPCipherAlgorithm_AES256: smimeerr = SETOID( smime, ASN_CMS_id_aes256_CBC_OID, &contentEncryptionAlg->algorithm ); break; default: SMIME_TRACE1("Unsupported algorithm %d passed as an encryption algorithm", alg); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } { ASN_CMS_IV *iv; PGPByte *iv_der; size_t size; int err; if( smimeerr ) { SMIME_TRACE1("Failed to set OID for algorithm %d", alg); return smimeerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } iv = ASN_CMS_NewIV(smime->asnc); if( iv==NULL ) { SMIME_TRACE1("Failed to allocate IV object for algorithm %d", alg); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* attach temporarily input IV data */ iv->val = IV->p; iv->len = IV->l; size = ASN_CMS_SizeofIV( smime->asnc, iv, TRUE/*outerSizeFlag*/ ); iv_der = ASN_CMS_Alloc( smime->asnc->memMgr, size ); if( iv_der == NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for CBCParameter (IV)", size); /* detach data */ iv->val = NULL; iv->len = 0; ASN_CMS_FreeIV(smime->asnc, iv); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } err = 0; ASN_CMS_PackIV( smime->asnc, iv_der, size, iv, &err ); /* detach data */ iv->val = NULL; iv->len = 0; ASN_CMS_FreeIV(smime->asnc, iv); if( err ) { SMIME_TRACE1("Failed to pack IV, ASN err=%d", err); ASN_CMS_Free(smime->asnc->memMgr, iv_der); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Attach IV to the 'parameters' */ pgpAssert( contentEncryptionAlg->parameters!=NULL );/* OPTIONAL in CMS, but mandatory here, so we must had created it earlier */ contentEncryptionAlg->parameters->val = iv_der; contentEncryptionAlg->parameters->len = size; } return 0; } /* move encrypted content to envelopedData */ SMIMEError asnSetEnvelopedEncrContent( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, P *encrContent ) { ASN_CMS_EncryptedContent *encryptedContent; /* see comments for decrypt */ encryptedContent = &envelopedData->encryptedContentInfo.encryptedContent; if( encryptedContent->val!=NULL ) { SMIME_TRACE1("Had EncryptedContent %p, freed", encryptedContent->val); ASN_CMS_Free( smime->asnc->memMgr, encryptedContent->val ); } encryptedContent->val = encrContent->p; encryptedContent->len = encrContent->l; SMIME_TRACE5("Moved encrypted content [%d] %02x %02x %02x %02x", encrContent->l, encrContent->p[0], encrContent->p[1], encrContent->p[2], encrContent->p[3] ); encrContent->dontFree = TRUE; /* transfer ownership */ return 0; } SMIMEError asnSetEnvelopeRecipientKeyEncrAlg( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, int recipient, PGPPublicKeyAlgorithm encrAlg ) { ASN_CMS_KeyTransRecipientInfo *ktri; pgpAssert( recipient < envelopedData->recipientInfos.n ); pgpAssert( ASN_TAG( envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type ) == ASN_CMS_ktri_RecipientInfoFieldTag ); ktri = (ASN_CMS_KeyTransRecipientInfo*)envelopedData->recipientInfos.elt[recipient]->data; SMIME_TRACE2("Setting public key algorithm %d for recipient %d", encrAlg, recipient); if( encrAlg != kPGPPublicKeyAlgorithm_RSA ) { SMIME_TRACE1("Unsupported KeyEncryptionAlgorithm for key transport", encrAlg); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Have RSA algorithm here -- the only supported for key transport (and we support only key transport in RecipientInfo) */ SETOID( smime, ASN_CMS_rsaEncryption_OID, &ktri->keyEncryptionAlgorithm.algorithm ); /* Paramers setup to NULL earlier */ return 0; } /* Set recipient identification as IssuerAndSerialNumber */ SMIMEError asnSetEnvelopeRecipient( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, int recipient, const P *x509cert ) { ASN_CMS_KeyTransRecipientInfo *ktri; ASN_CMS_IssuerAndSerialNumber *id; ASN_CMS_Certificate *cert; int asnerr; pgpAssert( recipient < envelopedData->recipientInfos.n ); pgpAssert( ASN_TAG( envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type ) == ASN_CMS_ktri_RecipientInfoFieldTag ); ktri = (ASN_CMS_KeyTransRecipientInfo*)envelopedData->recipientInfos.elt[recipient]->data; pgpAssert( ASN_TAG(ktri->rid.CHOICE_field_type) == ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag ); id = (ASN_CMS_IssuerAndSerialNumber*)ktri->rid.data; if( id==NULL ) { SMIME_TRACE1("IssuerAndSerialNumber is null for recipient %d (shoudld never happen)", recipient); return SMIMEError_CorruptData + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE5("Identifying recipient %d with certificate [%d] %02x %02x %02x", recipient, x509cert->l, x509cert->p[0], x509cert->p[1], x509cert->p[2] ); /* unpack certificate to get needed fields */ asnerr=0; ASN_CMS_UnpackCertificate( smime->asnc, &cert, x509cert->p, x509cert->l, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking certificate that identifies recipient %d", recipient); return asnerr; } if( id==NULL ) { SMIME_TRACE("Count not create empty NewIssuerAndSerialNumber object"); ASN_CMS_FreeCertificate( smime->asnc, cert ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Now initialize IssuerAndSerialNumber structure by detaching content from the Certificate and * attaching it to id. This is potentially unsafe, but logically speaking this is exactly what we need to do. */ /* attach */ pgpAssert( id->issuer.val==NULL && id->issuer.len==0 ); id->issuer.val = cert->tbsCertificate.issuer.val; id->issuer.len = cert->tbsCertificate.issuer.len; pgpAssert( id->serialNumber.val==NULL && id->serialNumber.len==0 ); id->serialNumber.val = cert->tbsCertificate.serialNumber.val; id->serialNumber.len = cert->tbsCertificate.serialNumber.len; /* detach */ cert->tbsCertificate.issuer.val = NULL; cert->tbsCertificate.issuer.len = 0; cert->tbsCertificate.serialNumber.val = NULL; cert->tbsCertificate.serialNumber.len = 0; ASN_CMS_FreeCertificate( smime->asnc, cert ); #if PGP_USE_TRACE if( id->serialNumber.len <= 4 ) { long sn; sn = ASN_CMS_GetIntVal (smime->asnc, &id->serialNumber, &asnerr); SMIME_TRACE4( "Set %d byte DN and %d byte SN=%d for recipient %d", id->issuer.len, id->serialNumber.len, sn, recipient ); } else SMIME_TRACE3( "Set %d byte DN and %d byte SN for recipient %d", id->issuer.len, id->serialNumber.len, recipient ); #endif return 0; } SMIMEError asnSetEnvelopeRecipientESK( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, int recipient, const P *esk ) { ASN_CMS_KeyTransRecipientInfo *ktri; ASN_CMS_EncryptedKey *encryptedKey; pgpAssert( recipient < envelopedData->recipientInfos.n ); pgpAssert( ASN_TAG( envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type ) == ASN_CMS_ktri_RecipientInfoFieldTag ); ktri = (ASN_CMS_KeyTransRecipientInfo*)envelopedData->recipientInfos.elt[recipient]->data; encryptedKey = &ktri->encryptedKey; encryptedKey->val = ASN_CMS_Alloc( smime->asnc->memMgr, esk->l ); if( encryptedKey->val==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for EncryptedKey", esk->l); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } encryptedKey->len = esk->l; memcpy( encryptedKey->val, esk->p, esk->l ); SMIME_TRACE5("Set EncryptedKey [%d] %02x %02x %02x for recipient %d", esk->l, esk->p[0], esk->p[1], esk->p[2], recipient ); return 0; } /* Exports envelopedData into DER form in a straignforward inefficient way. * * Any better solution will require changes to asn1comp. One possible solution is to * teach compiler to output indefinite size packet so that we could export envelopedData * with our unique tag in place of encryptedContent. This allows us to replace this tag inside DER encoding block * by actual encrypted content without invalidating structure sizes or doing complicated header changes * to account for size adjustment. This solution will spare compiler from doing more advanced memory management * and is more efficient for application */ SMIMEError asnExportEnveloped( SMIME_CONTEXT *smime, const ASN_CMS_EnvelopedData *envelopedData, P *enveloped_der ) { size_t encrDataSize, contentInfoSize; PGPByte *encrData_der, *contentInfo_der; ASN_CMS_ContentInfo *contentInfo; SMIMEError smimeerr; int asnerr; enveloped_der->p = NULL; enveloped_der->l = 0; /* TODO: potentially huge */ encrDataSize = ASN_CMS_SizeofEnvelopedData( smime->asnc, (ASN_CMS_EnvelopedData *)envelopedData, TRUE/*outerSizeFlag*/ ); encrData_der = ASN_CMS_Alloc( smime->asnc->memMgr, encrDataSize ); if( encrData_der==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for exported EnvelopedData", encrDataSize); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } asnerr=0; ASN_CMS_PackEnvelopedData( smime->asnc, encrData_der, encrDataSize, (ASN_CMS_EnvelopedData *)envelopedData, &asnerr ); if( asnerr ) { SMIME_TRACE2("Error %d packing EnvelopedData (expected result to be %d bytes)", asnerr, encrDataSize ); ASN_CMS_Free( smime->asnc->memMgr, encrData_der ); return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Now wrap encrData_der into ContentType */ contentInfo = ASN_CMS_NewContentInfo( smime->asnc ); if( contentInfo==NULL ) { ASN_CMS_Free( smime->asnc->memMgr, encrData_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* attach SignedData to ContentInfo object */ contentInfo->content.val = encrData_der; contentInfo->content.len = encrDataSize; smimeerr = SETOID( smime, ASN_CMS_id_envelopedData_OID, &contentInfo->contentType ); if( smimeerr ) { SMIME_TRACE("Failed to set id-envelopedData OID"); ASN_CMS_FreeContentInfo( smime->asnc, contentInfo ); return smimeerr | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } contentInfoSize = ASN_CMS_SizeofContentInfo( smime->asnc, contentInfo, TRUE/*outerSizeFlag*/ ); contentInfo_der = ASN_CMS_Alloc( smime->asnc->memMgr, contentInfoSize ); if( contentInfo_der==NULL ) { ASN_CMS_FreeContentInfo( smime->asnc, contentInfo ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } ASN_CMS_PackContentInfo( smime->asnc, contentInfo_der, contentInfoSize, contentInfo, &asnerr ); ASN_CMS_FreeContentInfo( smime->asnc, contentInfo ); if( asnerr ) { SMIME_TRACE2("Error %d packing ContentInfo (expected result to be %d bytes)", asnerr, contentInfoSize ); ASN_CMS_Free( smime->asnc->memMgr, contentInfo_der ); return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Packed %d bytes of ContentInfo for EnvelopedData", contentInfoSize); enveloped_der->p = contentInfo_der; enveloped_der->l = contentInfoSize; enveloped_der->dontFree = FALSE; return 0; } #if SMIME_TEST void test_smime_encrypt( PGPContextRef sdkcontext, P *cert_der ) { SMIME_CONTEXT c; SMIMEError err; err = asnInitSMIMEContext( sdkcontext, &c ); SMIME_TRACE1("Returned %08x", err); err = asnCreateEnvelopedData( &c, 2 ); SMIME_TRACE1("Returned %08x", err); { const P iv = { (void*)"\x01\x02\x03\x04\x05\x06\x07\x08", 8, TRUE }; err = asnSetEnvelopeContentEncrAlg( &c, c.envelopedData, kPGPCipherAlgorithm_3DES, &iv ); SMIME_TRACE1("Returned %08x", err); } err = asnSetEnvelopeRecipientKeyEncrAlg( &c, c.envelopedData, 0, kPGPPublicKeyAlgorithm_RSA ); SMIME_TRACE1("Returned %08x", err); err = asnSetEnvelopeRecipient( &c, c.envelopedData, 0, cert_der ); SMIME_TRACE1("Returned %08x", err); { PGPByte buf[1024/8]; P esk = {buf, sizeof(buf), TRUE}; memset( buf, 0xff, sizeof(buf) ); err = asnSetEnvelopeRecipientESK( &c, c.envelopedData, 0, &esk ); SMIME_TRACE1("Returned %08x", err); } err = asnFreeSMIMEContext( &c ); SMIME_TRACE1("Returned %08x", err); } #endif /*__Editor_settings____ Local Variables: tab-width: 4 End: vi: ts=4 sw=4 vim: si _____________________*/ /*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 DER decryption * for SMIME. * * $Id: pgpSMIMEasnDecrypt.c,v 1.6 2004/04/23 06:44:50 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" SMIMEError asnProcessEnvelopedData(SMIME_CONTEXT *c, const P *der) { ASN_CMS_ContentInfo *ci; ASN_CMS_EnvelopedData *envelopedData; int err=0; ASN_CMS_UnpackContentInfo( c->asnc, &ci, der->p, der->l, &err ); SMIME_TRACE1( "ASN_CMS_UnpackContentInfo returned %d", err ); if( err ) return ASNErrorToSMIMEError( err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); /* ContentInfo has ANY DEFINED BY 'content' that parser treats as ANY; * now manually direct the parser */ if( OIDCMP( &ci->contentType, ASN_CMS_id_envelopedData_OID )!=0 ) { SMIME_TRACE( "Given SMIME block is not EnvelopedData type" ); ASN_CMS_FreeContentInfo( c->asnc, ci ); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE("ContentType is EnvelopedData"); ASN_CMS_UnpackEnvelopedData( c->asnc, &envelopedData, ci->content.val, ci->content.len, &err ); /* Don't need content into anymore */ ASN_CMS_FreeContentInfo( c->asnc, ci ); SMIME_TRACE("Freed contentInfo, keep envelopedData"); if( err ) { SMIME_TRACE2( "UnpackEnvelopedData returned %d %s", err, asn1comp_err(err) ); return ASNErrorToSMIMEError( err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); } SMIME_TRACE("Unpacked envelopedData OK"); if( c->envelopedData ) { SMIME_TRACE1("Had old envelopedData %p in the context, clean it", c->envelopedData); ASN_CMS_FreeEnvelopedData( c->asnc, c->envelopedData ); } c->envelopedData = envelopedData; SMIME_TRACE1("Added envelopedData %p to the context", c->envelopedData); return 0; } int asnGetNumberOfEnvelopeRecipients(SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData) { (void)c; return ( envelopedData==NULL ? 0 : envelopedData->recipientInfos.n ); } #if 0 if( recipient > envelopedData->recipientInfos.n ) { if( envelopedData->recipientInfos.n==0 ) SMIME_TRACE1("No recipients in enveloped data (should not happen) and we are asked for recipient %d", recipient); else SMIME_TRACE1("Out of range recipient %d for [0..%d]", recipient, envelopedData->recipientInfos.n-1); return FALSE; } #endif /* compare certificate with given identification */ static PGPBoolean match_IssuerAndSerialNumber_with_cert( ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber, ASN_CMS_Certificate *x509cert ) { if( sncmp( &x509cert->tbsCertificate.serialNumber, &issuerAndSerialNumber->serialNumber )!=0 ) { SMIME_TRACE("cert_match_IssuerAndSerialNumber: SN doesn't match"); return FALSE; } if( namecmp( & x509cert->tbsCertificate.issuer, &issuerAndSerialNumber->issuer )!=0 ) { SMIME_TRACE("cert_match_IssuerAndSerialNumber: issuer's DN doesn't match"); return FALSE; } SMIME_TRACE("cert_match_IssuerAndSerialNumber: found a cert based on IssuerAndSerialNumber"); return TRUE; } /* compare certificate with given identification */ static PGPBoolean match_SubjectKeyIdentifier_with_cert( ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier, ASN_CMS_Certificate *x509cert ) { int i; /* look in certificate extensions for OCTET STRING */ if( x509cert->tbsCertificate.extensions->n == 0 ) { SMIME_TRACE("cert_match_for_subjectKeyIdentifier: no extensions"); return FALSE; } for( i=0; itbsCertificate.extensions->n; i++ ) { if( OIDCMP( &x509cert->tbsCertificate.extensions->elt[i]->extnID, ASN_CMS_id_ce_subjectKeyIdentifier_OID )==0 ) break; } if( i == x509cert->tbsCertificate.extensions->n ) { SMIME_TRACE("cert_match_for_subjectKeyIdentifier: no SubjectKeyIdentifier extension"); return FALSE; } SMIME_TRACE1("cert_match_for_subjectKeyIdentifier: match found at extension #%d", i); if( x509cert->tbsCertificate.extensions->elt[i]->extnValue.len != subjectKeyIdentifier->len ) { SMIME_TRACE2("cert_match_for_subjectKeyIdentifier: length of SubjectKeyIdentifier extension don't match: %d vs %d", x509cert->tbsCertificate.extensions->elt[i]->extnValue.len, subjectKeyIdentifier->len); return FALSE; } return memcmp( x509cert->tbsCertificate.extensions->elt[i]->extnValue.val, subjectKeyIdentifier->val, subjectKeyIdentifier->len )==0; } /* returns asnerr */ static int getKTRI( SMIME_CONTEXT *c, ASN_CMS_RecipientInfo *ri, int recipient, ASN_CMS_KeyTransRecipientInfo **ktriout ) { long version; ASN_CMS_KeyTransRecipientInfo *ktri; int asnerr = 0; (void)recipient; *ktriout = NULL; if( ASN_TAG(ri->CHOICE_field_type) != ASN_CMS_ktri_RecipientInfoFieldTag ) { #if PGP_USE_TRACE { char s[80]; switch( ASN_TAG(ri->CHOICE_field_type) ) { case ASN_CMS_kari_RecipientInfoFieldTag: strcpy( s, "KeyAgreeRecipientInfo" ); break; case ASN_CMS_kekri_RecipientInfoFieldTag: strcpy( s, "KEKRecipientInfo" ); break; default: sprintf( s, "Unknown RecipientInfo choice %d", ASN_TAG(ri->CHOICE_field_type) ); break; } SMIME_TRACE2("RecipientInfo %d is not KeyTransRecipientInfo, it is %s", recipient, s); } #endif return 0; } SMIME_TRACE2("Identified RecipientInfo type as KeyTransRecipientInfo (%02x) for recipient %d", ri->CHOICE_field_type, recipient); ktri = (ASN_CMS_KeyTransRecipientInfo *)ri->data; version = ASN_CMS_GetIntVal( c->asnc, &ktri->version, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking version for recipient %d", recipient); return asnerr; // return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( version != 0 && version != 2 ) { SMIME_TRACE2( "Wrong version %d for recipient %d", version, recipient ); return asnerr; //return SMIMEError_WrongVersion + // (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE2( "Version of KeyTransRecipientInfo is %d for recipient %d", version, recipient ); *ktriout = ktri; return 0; } /* returns index of recipient that matches given certificate according to strict SMIME matching; * -1 if not found. */ int asnGetEnvelopeRecipientIndex( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, const P *x509cert ) { int i; ASN_CMS_Certificate *cert; int asnerr; if( envelopedData->recipientInfos.n==0 ) { SMIME_TRACE("No recipients in enveloped data (should not happen)"); return -1; } /* unpack certificate */ ASN_CMS_UnpackCertificate( c->asnc, &cert, x509cert->p, x509cert->l, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking certificate, cannot match any of %d recipients", envelopedData->recipientInfos.n); return -1; } for( i=0; irecipientInfos.n; i++ ) { ASN_CMS_KeyTransRecipientInfo *ktri; SMIME_TRACE1("Matching recipient %d with cert", i); asnerr = getKTRI( c, envelopedData->recipientInfos.elt[i], i, &ktri ); if( asnerr ) { ASN_CMS_FreeCertificate( c->asnc, cert ); return -1; } if( ktri==NULL ) continue; if( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag) ) { ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber = (ASN_CMS_IssuerAndSerialNumber *)ktri->rid.data; SMIME_TRACE("Match recipient based on IssuerAndSerialNumber"); if( match_IssuerAndSerialNumber_with_cert( issuerAndSerialNumber, cert ) ) { SMIME_TRACE( "Matched cert based on IssuerAndSerialNumber" ); break; } } else if ( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_subjectKeyIdentifier_RecipientIdentifierFieldTag) ) { ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier = (ASN_CMS_SubjectKeyIdentifier*)ktri->rid.data; SMIME_TRACE("Match recipient based on SubjectKeyIdentifier"); if( match_SubjectKeyIdentifier_with_cert( subjectKeyIdentifier, cert ) ) { SMIME_TRACE( "Matched cert based on SubjectKeyIdentifier" ); break; } } else { SMIME_TRACE1("Unknown choice type for KeyTransRecipientInfo %02x", ASN_TAG(ktri->rid.CHOICE_field_type)); continue; } } ASN_CMS_FreeCertificate( c->asnc, cert ); if( irecipientInfos.n ) return i; SMIME_TRACE("Not found any match for certificate"); return -1; } /* get symmetrical algorithm and IV for CBC decryption */ SMIMEError asnGetEnvelopeContentEncrAlg( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, PGPCipherAlgorithm *alg, P *IV ) { ASN_CMS_ContentEncryptionAlgorithmIdentifier *encrAlg; ASN_CMS_IV *iv; int asnerr; PGPByte *p; PGPCipherAlgorithm myalg = kPGPCipherAlgorithm_None; IV->p = NULL; IV->l = 0; *alg = kPGPCipherAlgorithm_None; encrAlg = &envelopedData->encryptedContentInfo.contentEncryptionAlgorithm; if( OIDCMP( &encrAlg->algorithm, ASN_CMS_des_ede3_cbc_OID )==0 ) { /* handle SMIME v3 MUST */ myalg = kPGPCipherAlgorithm_3DES; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_id_aes128_CBC_OID )==0 ) { myalg = kPGPCipherAlgorithm_AES128; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_id_aes192_CBC_OID )==0 ) { myalg = kPGPCipherAlgorithm_AES192; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_id_aes256_CBC_OID )==0 ) { myalg = kPGPCipherAlgorithm_AES256; } else if( OIDCMP( &encrAlg->algorithm, ASN_CMS_rc2_cbc_OID )==0 ) { /* handle SMIME v3 SHOULD */ SMIME_TRACE("rc2-cbc algorithm recognized for content, but we don't support it"); /* parse RC2CBCParameter to get size from version and IV */ return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( myalg==kPGPCipherAlgorithm_None ) { SMIME_TRACE("Unknown content encryption algorithm found"); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } /* handle supported algorithms */ SMIME_TRACE1("%d algorithm recognized for content", myalg); if( encrAlg->parameters==NULL ) { /* all of supported algoriithms are CBC algoritms */ SMIME_TRACE( "AlgorithmIdentifier's parameters field must be present for CBC algorithm" ); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( encrAlg->parameters->len > 256 /* size beyond the era of quantum computing */ ) { SMIME_TRACE1("IV size %d is too big for %d and even for any known to us alg.", encrAlg->parameters->len); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } ASN_CMS_UnpackIV( c->asnc, &iv, encrAlg->parameters->val, encrAlg->parameters->len, &asnerr ); if( asnerr ) { SMIME_TRACE("Failed to unpack des-ede3-cbc IV"); return ASNErrorToSMIMEError( asnerr, (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING) ); } if( iv->len > (PGPUInt)(-1) ) { /* so we can safely cast later */ return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } /* this is octet string */ p = ASN_CMS_Alloc( c->asnc->memMgr, iv->len ); if( !p ) { ASN_CMS_FreeIV( c->asnc, iv ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES| SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } memcpy( p, iv->val, iv->len ); *alg = myalg; IV->p = p; IV->l = (PGPUInt)iv->len; IV->dontFree = FALSE; ASN_CMS_FreeIV( c->asnc, iv ); SMIME_TRACE5( "Got %d algorithm, IV [%d] %02x %02x %02x", myalg, IV->l, p[0], p[1], p[2] ); return 0; } PGPPublicKeyAlgorithm asnGetEnvelopeRecipientKeyEncrAlg( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, int recipient ) { ASN_CMS_KeyTransRecipientInfo *ktri; (void)c; if( recipient >= envelopedData->recipientInfos.n ) { #if PGP_USE_TRACE if( envelopedData->recipientInfos.n==0 ) SMIME_TRACE1("No recipients (should not happen), asked for %d", recipient); else SMIME_TRACE2("Out of range recipient %d, allowed range [0..%d]", recipient, envelopedData->recipientInfos.n ); #endif return SMIMEError_OutOfRangeIndex + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type) != ASN_CMS_ktri_RecipientInfoFieldTag ) { SMIME_TRACE1("Unsupported RecipientInfo choice %02x", ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type)); return kPGPPublicKeyAlgorithm_Invalid; } ktri = (ASN_CMS_KeyTransRecipientInfo *)envelopedData->recipientInfos.elt[recipient]->data; if( OIDCMP( &ktri->keyEncryptionAlgorithm.algorithm, ASN_CMS_rsaEncryption_OID )==0 ) { SMIME_TRACE1("rsaEncryption algorithm found for recipient %d", recipient); return kPGPPublicKeyAlgorithm_RSA; } SMIME_TRACE1("Didn't recognize recipient public key alg %d (no other algorithms possible then RSA?)", recipient); return kPGPPublicKeyAlgorithm_Invalid; } /* Get encrypted key */ SMIMEError asnGetEnvelopeRecipientESK( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, int recipient, P /*out*/ *keyout ) { ASN_CMS_KeyTransRecipientInfo *ktri; long version; PGPByte *p; int asnerr; keyout->p = NULL; keyout->l = 0; if( recipient >= envelopedData->recipientInfos.n ) { #if PGP_USE_TRACE if( envelopedData->recipientInfos.n==0 ) SMIME_TRACE1("No recipients (should not happen), asked for %d", recipient); else SMIME_TRACE2("Out of range recipient %d, allowed range [0..%d]", recipient, envelopedData->recipientInfos.n ); #endif return SMIMEError_OutOfRangeIndex + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type) != ASN_CMS_ktri_RecipientInfoFieldTag ) { SMIME_TRACE1("Unsupported RecipientInfo choice %02x", ASN_TAG(envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type)); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } ktri = (ASN_CMS_KeyTransRecipientInfo *)envelopedData->recipientInfos.elt[recipient]->data; version = ASN_CMS_GetIntVal( c->asnc, &ktri->version, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking version for recipient %d", recipient); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); } if( version != 0 && version != 2 ) { SMIME_TRACE2( "Wrong version %d for recipient %d", version, recipient ); return SMIMEError_WrongVersion + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } if( ktri->encryptedKey.len > (PGPUInt)(-1) ) { /* so we can safely cast later to min 2^32 */ return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } p = ASN_CMS_Alloc( c->asnc->memMgr, ktri->encryptedKey.len ); if( !p ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING|SMIME_ERROR_TYPE_RESOURCES); } memcpy( p, ktri->encryptedKey.val, ktri->encryptedKey.len ); SMIME_TRACE5( "Got [%d bit] %02x %02x %02x encrypted key for recipient %d", ktri->encryptedKey.len*8, p[0], p[1], p[2], recipient ); keyout->p = p; keyout->l = (PGPUInt)ktri->encryptedKey.len; keyout->dontFree = FALSE; return 0; } /* Get possible keyid bytes of the recipient key. */ SMIMEError asnGetEnvelopeRecipientKeyIDBytes(SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, int recipient, PGPByte out[8] ) { ASN_CMS_KeyTransRecipientInfo *ktri; int asnerr; memset(out,0,8); if( recipient >= envelopedData->recipientInfos.n ) { SMIME_TRACE2("Out of range recipient %d, allowed range [0..%d]", recipient, envelopedData->recipientInfos.n ); return SMIMEError_OutOfRangeIndex + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } asnerr = getKTRI( c, envelopedData->recipientInfos.elt[recipient], recipient, &ktri ); if( asnerr ) return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING ); if( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag) ) { ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber = (ASN_CMS_IssuerAndSerialNumber *)ktri->rid.data; if( issuerAndSerialNumber->serialNumber.len > 8 ) { SMIME_TRACE("getting keyid from recipient based on IssuerAndSerialNumber"); memcpy( out, issuerAndSerialNumber->serialNumber.val+issuerAndSerialNumber->serialNumber.len-8, 8 ); } else { SMIME_TRACE1( "IssuerAndSerialNumber has too short SN (%d bytes) to provide keyid suggestion", issuerAndSerialNumber->serialNumber.len ); return SMIMEError_FieldTooShortToHoldKeyID + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } } else if ( ASN_TAG(ktri->rid.CHOICE_field_type)==(ASN_CMS_subjectKeyIdentifier_RecipientIdentifierFieldTag) ) { ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier = (ASN_CMS_SubjectKeyIdentifier*)ktri->rid.data; if( subjectKeyIdentifier->len > 8 ) { SMIME_TRACE("getting keyid from recipient based on SubjectKeyIdentifier"); memcpy( out, subjectKeyIdentifier->val+subjectKeyIdentifier->len-8, 8 ); } else { SMIME_TRACE1( "SubjectKeyIdentifier has too short value (%d bytes) to provide keyid suggestion", subjectKeyIdentifier->len ); return SMIMEError_FieldTooShortToHoldKeyID + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } } else { SMIME_TRACE1("Unknown choice type for KeyTransRecipientInfo %02x", ASN_TAG(ktri->rid.CHOICE_field_type)); pgpAssert(0); } return 0; } SMIMEError asnGetEnvelopedEncrContent( SMIME_CONTEXT *c, ASN_CMS_EnvelopedData *envelopedData, P *encrContent ) { ASN_CMS_EncryptedContent *encryptedContent; (void)c; encrContent->p = NULL; encrContent->l=0; /* I changed CMS definition to make EnvelopedData->encryptedContentInfo->encryptedContent mandatory * as required by SMIME. This eliminates one check here and make encryption simplier */ encryptedContent = &envelopedData->encryptedContentInfo.encryptedContent; SMIME_TRACE1("Have encrypted content of %d bytes; point to it without copying", encryptedContent->len); if( encryptedContent->len > (PGPUInt)(-1) ) { /* so we can safely cast to min 2^32 later */ return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_DECODING); } encrContent->p = encryptedContent->val; encrContent->l = (PGPUInt)encryptedContent->len; encrContent->dontFree = TRUE; return 0; } #if SMIME_TEST void test_smime_decrypt( PGPContextRef sdkcontext, P *smime_der, P *cert_der ) { SMIME_CONTEXT c; SMIMEError err; int recipients; int index; err = asnInitSMIMEContext( sdkcontext, &c ); SMIME_TRACE1( "asnInitSMIMEContext returned %08x", err ); err = asnProcessEnvelopedData( &c, smime_der ); SMIME_TRACE1( "asnProcessEnvelopedData returned %08x", err ); if( err ) { asnFreeSMIMEContext( &c ); return; } recipients = asnGetNumberOfEnvelopeRecipients( &c, c.envelopedData ); SMIME_TRACE1( "%d recipients", recipients ); index = asnGetEnvelopeRecipientIndex( &c, c.envelopedData, cert_der ); SMIME_TRACE1( "%d is the index of matched? recipient", index ); if( index != -1 ) { P key; P iv; PGPPublicKeyAlgorithm alg; PGPCipherAlgorithm encrAlg; unsigned i; err = asnGetEnvelopeRecipientESK( &c, c.envelopedData, index, &key ); SMIME_TRACE1( "asnGetEnvelopeRecipientESK returned %08x", err ); pgpSMIMEFreePtr( &key ); alg = asnGetEnvelopeRecipientKeyEncrAlg( &c, c.envelopedData, index ); printf("Recipient %d has alg %d\n", index, alg); if( !asnGetEnvelopeContentEncrAlg( &c, c.envelopedData, &encrAlg, &iv ) ) { printf("Got encrAlg %d\n[%d] ", encrAlg, iv.l); for( i=0; inXNY&Ĝ_n|3;CB g!/z:᝽ uvbTt-FMewTRq'*ᗮ\:wZ9 4\H*P8 7׀oXEOt tGp7nsbfMpo^x,g!JZ6q$$sK'qOu.*cT v lAȝQ!3C c5!hwI_ml^$XZ!Xys:Zv;icZdETpk[]0ˬOM`rlȃ@=78[.V*d;ӤfN'C Dj|jt_u9:U7MkYpL3qj,!Vȿ+ 8II#^ }.Pp"j!H<x۹n֦n`;E1hME:UbmI#M*R3LA%*dL9=z5_]AK{^kg8ݸ wulMrnQ>GedkDԵRͲѼl*\3\sݪ*G9Ɵ ]ޣ 1qyT%^wNq"^X8ϔ/r%T1 5i=wp` }@M,n? rC`lf,O)KKd49R7ow{׌N{ [rdybF!]jD鏊氛Xl15՗@|H=dMH\% PA erGP R􍲭qa"Bk֫!$d*Wv6 37LY'Evk&t򈔠OR,>Judž:-YnA6m`dp[#Ey;^HC#"RԒ7=߬@${6 @ql2zª)R93AZ&SwnXnuVA* "q3 S@ı.M'Ԕ i86{̮;ąf}Bq )J{ݯi}H9Vn,vR@9iLO@&dMUmB r3"\O^~p1P6ř Fk &;S~-j? 7ڱP>SuwU_ 93 EQ5*|rv\QtEҬ$u3S^zQLk &Xr8 jMXsIÑǍ]q TP+n;֭|B҂0,g N9R[-vzm5:ZrAv,w%qF]Eiv׸B$HϦh+JҔd/w#gzŞ:Zj1LY]M”?G.? o$I=LUf֒R<ɓO*~vEp-\ժ ́sS_+y%~vB13R7TNj=(kgэ'i[;v"!0d*^olя +Y7PoXb6q1L-7c͍H#r}cWJL̔.NEDXJ ig1BK2mvk3f\.͝@kK{gSzs[;NяQF3Fm1\%A79$d~3CL^JjR~JCd{‚Yt m|Gֵt F Ag$'O[)츶:҄`J" Ή,L34$kSPmyx^ݨԳE&rhGͲ,oA?|#4ͷuY7-  tnimܶXc|u RTR@(2I#KV~ ǩm ŷ,op$+c72I,`b* =Bd[#2T($+ kU;KŸ&cވ4mjm C`DSgtT?] Y" "AH`UBkJ ̮>4)gIoEFCkB .;qf1W l</*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 routines needed for * signature generation in SMIME. * * $Id: pgpSMIMEasnSign.c,v 1.4 2003/10/14 02:18:39 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" #include "pgpASN_SMIME.h" #include "pgpASN_SMIME_asn.h" #include "pgpASN_SMIME_oid.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" static SMIMEError getoidDER( SMIME_CONTEXT *c, const unsigned char *oid, size_t len, P *derout ) { ASN_CMS_OBJECT_ID *objectID; PGPByte *p; size_t size; int err; derout->p = NULL; derout->l = 0; objectID = ASN_CMS_NewOBJECT_ID( c->asnc ); if( oid==NULL ) return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES); objectID->val = (void*)oid; objectID->len = len; size = ASN_CMS_SizeofOBJECT_ID( c->asnc, objectID, TRUE/*outerSizeFlag*/ ); p = ASN_CMS_Alloc( c->asnc->memMgr, size ); if( p==NULL ) { ASN_CMS_FreeOBJECT_ID( c->asnc, objectID ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES); } err=0; /* urgly surprise: must do this for compiler */ ASN_CMS_PackOBJECT_ID( c->asnc, p, size, objectID, &err ); objectID->val = NULL; /* this object doesn't own oid */ objectID->len = 0; ASN_CMS_FreeOBJECT_ID( c->asnc, objectID ); if( err ) { SMIME_TRACE1("Error %d packing %d bytes oid", len); ASN_CMS_Free( c->asnc->memMgr, p ); return err + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES); } derout->p = p; derout->l = size; derout->dontFree = FALSE; SMIME_TRACE5( "Exported object ID: [%d] %02x %02x %02x %02x", size, p[0],p[1],p[2],p[3] ); return 0; } SMIMEError asnCreateSigned(SMIME_CONTEXT *smime, int signers, int certificates) { ASN_CMS_SignedData *signedData; SMIME_TRACE1("Building top level SignedData for %d signers", signers); signedData = ASN_CMS_NewSignedData(smime->asnc); if( signedData==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } ASN_CMS_PutIntVal( smime->asnc, &signedData->version, 1 ); signedData->signerInfos.n = signers; signedData->signerInfos.elt = ASN_CMS_Alloc( smime->asnc->memMgr, signers * sizeof(ASN_CMS_SignerInfo*) ); if( signedData->signerInfos.elt==NULL ) { signedData->signerInfos.n = 0; ASN_CMS_FreeSignedData( smime->asnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( signedData->signerInfos.elt, 0, signers * sizeof(ASN_CMS_SignerInfo*) ); { ASN_CMS_EncapsulatedContentInfo *encapContentInfo = &signedData->encapContentInfo; SETOID( smime, ASN_CMS_id_data_OID, &encapContentInfo->eContentType ); encapContentInfo->eContent = NULL; /* multipart/signed */ SMIME_TRACE("Done setting empty encapContentInfo for multipart/signed or encapsulated"); } /* encapContentInfo */ { ASN_CMS_CertificateSet *certs = ASN_CMS_NewCertificateSet(smime->asnc); if( !certs ) { ASN_CMS_FreeSignedData( smime->asnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } certs->n = certificates; certs->elt = ASN_CMS_Alloc( smime->asnc->memMgr, sizeof(ASN_CMS_CertificateChoices*)*certificates ); if( certs->elt==NULL ) { ASN_CMS_FreeCertificateSet( smime->asnc, certs ); ASN_CMS_FreeSignedData( smime->asnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( certs->elt, 0, sizeof(ASN_CMS_CertificateChoices*)*certificates ); signedData->certificates = certs; } /* certificates pointers */ /* it is safe to free signerData now */ /* ----- Set up content ----- */ { int i; for( i=0; iasnc ); int err; if( signerInfo==NULL ) break; ASN_CMS_PutIntVal( smime->asnc, &signerInfo->version, 1 ); signedData->signerInfos.elt[i] = signerInfo; /* construct signer attributes structures with mandatory attributes at * fixed positions */ { ASN_CMS_SignedAttributes *signedAttrs = ASN_CMS_NewSignedAttributes(smime->asnc); ASN_CMS_Attribute *attr; #define attributes 4 /* for [0] id-messageDigest, [1] is content-type, [2] is id-SigningTime, [3] is smimeCapabilities */ const P oids[attributes] = { { ASN_CMS_id_messageDigest_OID, ASN_CMS_id_messageDigest_OID_LEN, TRUE }, /* content is OCTET STRING */ { ASN_CMS_id_contentType_OID, ASN_CMS_id_contentType_OID_LEN, TRUE }, /* content is OID */ { ASN_CMS_id_signingTime_OID, ASN_CMS_id_signingTime_OID_LEN, TRUE }, /* content is SigningTime */ { ASN_CMS_smimeCapabilities_OID, ASN_CMS_smimeCapabilities_OID_LEN, TRUE } /* content is SMIMECapabilities */ /* TODO: smimeCapabilites should be here */ }; int i_attr; /* construct a content of SignerAttributes */ signedAttrs->n = attributes; signedAttrs->elt = ASN_CMS_Alloc(smime->asnc->memMgr, sizeof(ASN_CMS_Attribute*) * attributes); if( signedAttrs->elt==NULL ) { ASN_CMS_FreeSignedAttributes( smime->asnc, signedAttrs ); break; } memset( signedAttrs->elt, 0, sizeof(ASN_CMS_Attribute*) * attributes ); for( i_attr=0; i_attrasnc); if( attr==NULL ) break; /* construct attrValues which is a set of 1 AttributeValue (which is ANY) */ err = setoid( smime, oids[i_attr].p, oids[i_attr].l, &attr->attrType ); if( err ) break; attr->attrValues.n = 1; attr->attrValues.elt = ASN_CMS_Alloc( smime->asnc->memMgr, sizeof(ASN_CMS_AttributeValue*)*1 ); if( attr->attrValues.elt==NULL ) { ASN_CMS_FreeAttribute( smime->asnc, attr ); break; } attr->attrValues.elt[0] = ASN_CMS_NewAttributeValue(smime->asnc); /* this is ANY in ASN.1 */ if( attr->attrValues.elt[0]==NULL ) { ASN_CMS_FreeAttribute( smime->asnc, attr ); break; } signedAttrs->elt[i_attr] = attr; } if( i_attrasnc, signedAttrs ); break; } /* Now set attribute [1] to the constant value */ { P oid; err = getoidDER( smime, ASN_CMS_id_data_OID, ASN_CMS_id_data_OID_LEN, &oid ); if( err ) { SMIME_TRACE1("Error %d creating DER OID", err); ASN_CMS_FreeSignedAttributes( smime->asnc, signedAttrs ); break; } signedAttrs->elt[1]->attrValues.elt[0]->val = oid.p; signedAttrs->elt[1]->attrValues.elt[0]->len = oid.l; /* transfered the memory from oid to attribute [1] */ } signerInfo->signedAttrs = signedAttrs; /* finally attach signed attributes set */ #undef attributes } /* signedAttrs */ } if( iasnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Done setting %d SignerInfos", signers); } /* signerInfos */ { int i; for( i=0; icertificates->elt[i] = ASN_CMS_NewCertificateChoices( smime->asnc ))==NULL ) break; } if( iasnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Done setting %d CertificateChoices", certificates); } /* certificates */ if( smime->signedData ) { SMIME_TRACE1("Had old signedData %p in the context, clean it", smime->signedData); ASN_CMS_FreeSignedData( smime->asnc, smime->signedData ); } smime->signedData = signedData; SMIME_TRACE1("Added signedData %p to the context", smime->signedData); return 0; } SMIMEError asnSetSignedContent( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, const P* eContent ) { ASN_CMS_OCTET_STRING *octetStr; octetStr = ASN_CMS_NewOCTET_STRING( smime->asnc ); if( octetStr==NULL ) return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); octetStr->val = ASN_CMS_Alloc( smime->asnc->memMgr, eContent->l ); if( octetStr->val==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for the eContent", eContent->l); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } octetStr->len = eContent->l; memcpy( octetStr->val, eContent->p, eContent->l ); if( signedData->encapContentInfo.eContent!=NULL) { SMIME_TRACE1("Had eContent size [%d], freed it", signedData->encapContentInfo.eContent->len); ASN_CMS_FreeOCTET_STRING( smime->asnc, signedData->encapContentInfo.eContent ); } signedData->encapContentInfo.eContent = octetStr; SMIME_TRACE4( "Set eContent to [%d] %02x %02x %02x", octetStr->len, octetStr->val[0], octetStr->val[1], octetStr->val[2] ); return 0; } /* Sets digestAlgorithms field in SignedData * hashAlg is kPGPHashAlgorithm_Invalid-terminated string of hash algoritms, the length is up to signers. * We use the fact that hash algorithm value is less then 256 */ SMIMEError asnSetHashAlgorithms( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, const PGPHashAlgorithm hashAlgs[] ) { PGPHashAlgorithm hashHits[256]; PGPHashAlgorithm maxHash=0; int uniqueHashAlgs=0; int hashIndex=0; int i; ASN_CMS_DigestAlgorithmIdentifiers myDigestAlgorithms; const int signers = signedData->signerInfos.n; SMIMEError err=0; memset(&myDigestAlgorithms, 0, sizeof(myDigestAlgorithms)); if( signers <= 0 ) { SMIME_TRACE("No signers. Number of signerts must be set first"); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( hashHits, 0, sizeof(hashHits) ); for( i=0; i < signers && hashAlgs[i] != kPGPHashAlgorithm_Invalid; i++ ) { pgpAssert( hashAlgs[i] < 256 ); if( hashAlgs[i] > maxHash ) maxHash = hashAlgs[i]; hashHits[ hashAlgs[i] ] ++; } for( i=0; i<=(int)maxHash; i++ ) if( hashHits[i] ) uniqueHashAlgs++; SMIME_TRACE2( "%d unique hash algorithms specified, largest is %d", uniqueHashAlgs, maxHash ); myDigestAlgorithms.n = uniqueHashAlgs; myDigestAlgorithms.elt = ASN_CMS_Alloc( smime->asnc->memMgr, uniqueHashAlgs * sizeof(ASN_CMS_DigestAlgorithmIdentifier*) ); if( myDigestAlgorithms.elt==NULL ) { myDigestAlgorithms.n = 0; return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( myDigestAlgorithms.elt, 0, uniqueHashAlgs * sizeof(ASN_CMS_DigestAlgorithmIdentifier*) ); /* Now add uniqueHashAlgs AlgorithmIdentifier SEQUENCE { OID }. AlgorithmIdentifier has optional parameters field which * is empty for any hash algorithm we support */ for( i=0; i<=(int)maxHash; i++ ) { if( hashHits[i] ) { ASN_CMS_DigestAlgorithmIdentifier *algorithm = ASN_CMS_NewDigestAlgorithmIdentifier( smime->asnc ); if( algorithm==NULL ) { err = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); break; } switch( i ) { case kPGPHashAlgorithm_SHA: SMIME_TRACE("processing SHA-1 algorithm for SignedData"); err = SETOID( smime, ASN_CMS_sha_1_OID, &algorithm->algorithm ); break; #if 0 case kPGPHashAlgorithm_SHA256; case kPGPHashAlgorithm_SHA384; case kPGPHashAlgorithm_SHA512; /* future algorithms */ break; case kPGPHashAlgorithm_MD5: SMIME_TRACE("processing MD5 algorithm for SignedData"); err = SETOID( smime, ASN_CMS_md5_OID, &algorithm->algorithm ); break; #endif default: SMIME_TRACE1("Asked to use unsupported hash algorithm %d", i); err = SMIMEError_UnsupportedHash | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( err ) { SMIME_TRACE1("Error %d while creating hash algorithm object", err); ASN_CMS_FreeDigestAlgorithmIdentifier( smime->asnc, algorithm ); break; } /* Set DER NULL object */ algorithm->parameters = ASN_CMS_NewANY(smime->asnc); if( algorithm->parameters==NULL ) { SMIME_TRACE("No memory for ANY object"); ASN_CMS_FreeDigestAlgorithmIdentifier( smime->asnc, algorithm ); err = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); break; } /* now ANY attached to algorithm's parameters */ err = setnull( smime, algorithm->parameters); if( err ) { SMIME_TRACE("No memory for NULL object"); ASN_CMS_FreeDigestAlgorithmIdentifier( smime->asnc, algorithm ); err |= (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); break; } SMIME_TRACE1("Attaching hash algorithm object at index %d", hashIndex); myDigestAlgorithms.elt[hashIndex++] = algorithm; } } if( err ) { ASN_CMS_DropInPlaceDigestAlgorithmIdentifiers( smime->asnc, &myDigestAlgorithms ); return err; } if( signedData->digestAlgorithms.n > 0 ) { SMIME_TRACE1("Had %d hash algorithms advertized. Clean them first", signedData->digestAlgorithms.n); pgpAssert( signedData->digestAlgorithms.elt ); ASN_CMS_DropInPlaceDigestAlgorithmIdentifiers( smime->asnc, &signedData->digestAlgorithms ); } signedData->digestAlgorithms = myDigestAlgorithms; /* transfer pointers */ SMIME_TRACE1("Done setting %d message digest algorithms", uniqueHashAlgs); #if PGP_DEBUG { PGPHashAlgorithm hashAlgs[100]; int n; asnGetHashAlgs( smime, signedData, hashAlgs, &n ); SMIME_TRACE1("Found %d hash algorithm right after I set them", n); } #endif return 0; } /* will leak memory if called twice for same signer and signedData */ SMIMEError asnSetSignerHashAlg( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, PGPHashAlgorithm hashAlg ) { SMIMEError err=0; ASN_CMS_DigestAlgorithmIdentifier myDigestAlgorithm; ASN_CMS_DigestAlgorithmIdentifier *digestAlgorithm; memset(&myDigestAlgorithm, 0, sizeof(myDigestAlgorithm)); pgpAssert( signer < signedData->signerInfos.n ); digestAlgorithm = &signedData->signerInfos.elt[signer]->digestAlgorithm; pgpAssert(digestAlgorithm); /* create DER ANY object for parameters */ myDigestAlgorithm.parameters = ASN_CMS_NewANY(smime->asnc); if( myDigestAlgorithm.parameters==NULL ) { SMIME_TRACE("No memory for ANY object"); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* now setup a content */ switch( hashAlg ) { case kPGPHashAlgorithm_SHA: err = SETOID( smime, ASN_CMS_sha_1_OID, &myDigestAlgorithm.algorithm ); break; #if 0 case kPGPHashAlgorithm_SHA256; case kPGPHashAlgorithm_SHA384; case kPGPHashAlgorithm_SHA512; /* future algorithms */ break; case kPGPHashAlgorithm_MD5: SETOID( smime, ASN_CMS_md5_OID, &myDigestAlgorithm.algorithm ); break; #endif default: SMIME_TRACE2("Asked to use unsupported hash algorithm %d for signer %d", hashAlg, signer); err = SMIMEError_UnsupportedHash | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( err ) { SMIME_TRACE1("Error during DigestAlgorithmIdentifier construction for signer %d", signer ); ASN_CMS_DropInPlaceDigestAlgorithmIdentifier( smime->asnc, &myDigestAlgorithm ); return err + (SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err = setnull( smime, myDigestAlgorithm.parameters); if( err ) { SMIME_TRACE("No memory for NULL object"); ASN_CMS_DropInPlaceDigestAlgorithmIdentifier( smime->asnc, &myDigestAlgorithm ); return err + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } #if PGP_USE_TRACE if( digestAlgorithm->parameters != NULL ) SMIME_TRACE1("Had DigestAlgorithmIdentifier for signer %d. Clean it", signer); #endif ASN_CMS_DropInPlaceDigestAlgorithmIdentifier( smime->asnc, digestAlgorithm ); *digestAlgorithm = myDigestAlgorithm; SMIME_TRACE2("Set hash algorithm %d for signer %d", hashAlg, signer); return 0; } /* signer hash is part of signed attributes at the position [0] */ SMIMEError asnSetSignerMsgHash( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const P *hash ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_Attribute *msgDigestAttr; ASN_CMS_OCTET_STRING *octetStr; P hash_der; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE5("Setting message digest [%d] %02x %02x %02x for signer %d", hash->l, hash->p[0], hash->p[1], hash->p[2], signer ); pgpAssert(signerInfo->signedAttrs->n > 0); /* id-messageDigest must be at [0] */ msgDigestAttr = signerInfo->signedAttrs->elt[0]; pgpAssert( OIDCMP( &msgDigestAttr->attrType, ASN_CMS_id_messageDigest_OID )==0 ); pgpAssert( msgDigestAttr->attrValues.n==1 && msgDigestAttr->attrValues.elt[0]!=NULL ); /* Set content. attrValues is a set of one element: DER OCTET STRING */ octetStr = ASN_CMS_NewOCTET_STRING( smime->asnc ); if( octetStr==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err = ASN_CMS_PutOctVal( smime->asnc, octetStr, hash->p, hash->l ); if( err ) { ASN_CMS_FreeOCTET_STRING( smime->asnc, octetStr ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } hash_der.l = ASN_CMS_SizeofOCTET_STRING( smime->asnc, octetStr, TRUE/*outerSizeFlag*/ ); hash_der.p = ASN_CMS_Alloc( smime->asnc->memMgr, hash_der.l ); hash_der.dontFree = FALSE; if( hash_der.p==NULL ) { ASN_CMS_FreeOCTET_STRING( smime->asnc, octetStr ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err=0; /* must do this for compiler */ ASN_CMS_PackOCTET_STRING( smime->asnc, hash_der.p, hash_der.l, octetStr, &err ); ASN_CMS_FreeOCTET_STRING( smime->asnc, octetStr ); if( err ) { pgpSMIMEFreePtr( &hash_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* initialize ANY with DER of hash */ pgpAssert( msgDigestAttr->attrValues.n==1 ); if( msgDigestAttr->attrValues.elt[0]->val != NULL ) { SMIME_TRACE1("Had message hash for signer %d, clean it", signer); ASN_CMS_Free( smime->asnc->memMgr, msgDigestAttr->attrValues.elt[0]->val ); } msgDigestAttr->attrValues.elt[0]->val = hash_der.p; msgDigestAttr->attrValues.elt[0]->len = hash_der.l; return 0; } SMIMEError asnSetSigner( SMIME_CONTEXT *smime, int certificate, ASN_CMS_SignedData *signedData, const P *x509cert ) { ASN_CMS_CertificateChoices *certificateChoices; ASN_CMS_Certificate *cert; int err; pgpAssert( signedData->certificates && certificate < signedData->certificates->n ); certificateChoices = signedData->certificates->elt[certificate]; pgpAssert(certificateChoices); SMIME_TRACE2("Setting certificate %d, one of [0..%d]", certificate, signedData->certificates->n-1); /* we use only X.509 cert */ certificateChoices->CHOICE_field_type = ASN_CMS_certificate_CertificateChoicesFieldTag; ASN_CMS_UnpackCertificate( smime->asnc, &cert, x509cert->p, x509cert->l, &err ); if( err ) { SMIME_TRACE1("Error unpacking X509 certificate %d", certificate); return ASNErrorToSMIMEError( err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING ); } /* attach certificate to the signedData */ certificateChoices->data = cert; return 0; } /* Set signing time as 'time'. This functions can be exported if more control over signing time is required */ static SMIMEError setSignerSigningTime( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, PGPTime time ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_Attribute *signingTimeAttr; ASN_CMS_SigningTime *signingTime; P signingTime_der; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; /* id-signingTime must be at [2] */ signingTimeAttr = signerInfo->signedAttrs->elt[2]; pgpAssert( OIDCMP( &signingTimeAttr->attrType, ASN_CMS_id_signingTime_OID )==0 ); pgpAssert( signingTimeAttr->attrValues.n==1 && signingTimeAttr->attrValues.elt[0]!=NULL ); /* Set the content. attrValues is a set of one element: DER SigningTime */ signingTime = ASN_CMS_NewSigningTime( smime->asnc ); if( signingTime==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err = settime( smime, time, signingTime ); if( err ) { SMIME_TRACE1("Failed to initialize SigningTime with current time, err=%d", err); ASN_CMS_FreeSigningTime( smime->asnc, signingTime ); return err + (SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } signingTime_der.l = ASN_CMS_SizeofSigningTime( smime->asnc, signingTime, TRUE/*outerSizeFlag*/ ); signingTime_der.p = ASN_CMS_Alloc( smime->asnc->memMgr, signingTime_der.l ); signingTime_der.dontFree = FALSE; if( signingTime_der.p==NULL ) { ASN_CMS_FreeSigningTime( smime->asnc, signingTime ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err=0; /* must do this for ASN.1 compiler */ ASN_CMS_PackSigningTime( smime->asnc, signingTime_der.p, signingTime_der.l, signingTime, &err ); ASN_CMS_FreeSigningTime( smime->asnc, signingTime ); if( err ) { pgpSMIMEFreePtr( &signingTime_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* initialize ANY with DER of SigningTime */ SMIME_TRACE1("Attaching signing time for signer %d", signer); pgpAssert( signingTimeAttr->attrValues.n==1 ); if( signingTimeAttr->attrValues.elt[0]->val!=NULL ) { SMIME_TRACE1("Had signing time attribute for signer %d, clean it", signer); ASN_CMS_Free( smime->asnc->memMgr, signingTimeAttr->attrValues.elt[0]->val ); } signingTimeAttr->attrValues.elt[0]->val = signingTime_der.p; signingTimeAttr->attrValues.elt[0]->len = signingTime_der.l; SMIME_TRACE5("Set up date as DER [%d] %02x %02x %02x %02x", signingTime_der.l, signingTime_der.p[0], signingTime_der.p[1], signingTime_der.p[2], signingTime_der.p[3] ); return 0; } /* Set same signing time for all signers */ SMIMEError asnSetSigningTime( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData ) { const int signers = signedData->signerInfos.n; const PGPTime time = PGPGetTime(); int signer; SMIMEError smimeerr = kPGPError_NoErr; /* to make the compiler happy */ if( signers == 0 ) { SMIME_TRACE("No signers, cannot set signing time"); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } for( signer=0; signer < signers; signer++ ) { smimeerr = setSignerSigningTime( smime, signer, signedData, time ); if( smimeerr ) break; } return smimeerr; } SMIMEError asnSetSignerSignature( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const P *sig ) { ASN_CMS_SignerInfo *signerInfo; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE5( "Setting signature [%d] %02x %02x %02x %02x", sig->l, sig->p[0], sig->p[1], sig->p[2], sig->p[3] ); err = ASN_CMS_PutOctVal( smime->asnc, &signerInfo->signature, sig->p, sig->l ); if( err ) { return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } return 0; } SMIMEError asnSetSignerSignatureAlg( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, PGPPublicKeyAlgorithm sigAlg ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_SignatureAlgorithmIdentifier mySignatureAlgorithm; SMIMEError err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; memset( &mySignatureAlgorithm, 0, sizeof(mySignatureAlgorithm) ); if( sigAlg==kPGPPublicKeyAlgorithm_RSA ) { err = SETOID( smime, ASN_CMS_rsaEncryption_OID, &mySignatureAlgorithm.algorithm ); SMIME_TRACE("Setting SignatureAlgorithmIdentifier to rsaEncryption"); } else if( sigAlg==kPGPPublicKeyAlgorithm_DSA ) { err = SETOID( smime, ASN_CMS_id_dsa_with_sha1_OID, &mySignatureAlgorithm.algorithm ); SMIME_TRACE("Setting SignatureAlgorithmIdentifier to id-dsa-with-sha1"); } else { SMIME_TRACE2("Unsupported public key algorithm %d for signing for signer %d", sigAlg, signer); pgpAssert(0); return SMIMEError_UnsupportedPubAlg + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( err ) { SMIME_TRACE1("Error setting OID for the SignatureAlgorithmIdentifier for signer %d", signer); return err; } /* Set DER NULL object */ mySignatureAlgorithm.parameters = ASN_CMS_NewANY(smime->asnc); if( mySignatureAlgorithm.parameters==NULL ) { SMIME_TRACE("No memory for ANY object"); ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier( smime->asnc, &mySignatureAlgorithm ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* now ANY attached to SignatureAlgorithm's parameters; set parameters to NULL */ err = setnull( smime, mySignatureAlgorithm.parameters ); if( err ) { SMIME_TRACE1("Error setting parameters to NULL for the SignatureAlgorithmIdentifier for signer %d", signer); ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier( smime->asnc, &mySignatureAlgorithm ); return err; } #if PGP_USE_TRACE if( signerInfo->signatureAlgorithm.parameters != NULL ) SMIME_TRACE1("Had SignatureAlgorithm for signer %d, clean it", signer); #endif ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier( smime->asnc, &signerInfo->signatureAlgorithm ); signerInfo->signatureAlgorithm = mySignatureAlgorithm; /* transfer pointers */ return 0; } /* Set signer certificate */ SMIMEError asnSetSignerCert( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const P *x509cert ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber; ASN_CMS_IssuerAndSerialNumber myIssuerAndSerialNumber; ASN_CMS_Certificate *certificate; size_t size; PGPByte *p; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE( "Setting signer certificate" ); /* First parse certificate */ ASN_CMS_UnpackCertificate( smime->asnc, &certificate, x509cert->p, x509cert->l, &err ); if( err ) { SMIME_TRACE1("Failed to unpack certificate [%d]", x509cert->l); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING ); } /* Now make IssuerAndSerialNumber by pointing to fields from Certificate. This must be done carefully as IssuerAndSerialNUmber * will not own these fields (Certificate is the owner) */ memset( &myIssuerAndSerialNumber, 0, sizeof(myIssuerAndSerialNumber) ); myIssuerAndSerialNumber.issuer = certificate->tbsCertificate.issuer; myIssuerAndSerialNumber.serialNumber = certificate->tbsCertificate.serialNumber; size = ASN_CMS_SizeofIssuerAndSerialNumber( smime->asnc, &myIssuerAndSerialNumber, TRUE/*outerSizeFlag*/ ); p = ASN_CMS_Alloc( smime->asnc->memMgr, size ); if( p==NULL ) { ASN_CMS_FreeCertificate( smime->asnc, certificate ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* store */ ASN_CMS_PackIssuerAndSerialNumber( smime->asnc, p, size, &myIssuerAndSerialNumber, &err ); ASN_CMS_FreeCertificate( smime->asnc, certificate ); /* also done with myIssuerAndSerialNumber, forget it */ if( err ) { SMIME_TRACE1("Error packing issuer and serial number, expected length %d bytes", size); ASN_CMS_Free( smime->asnc->memMgr, p ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING ); } /* restore */ ASN_CMS_UnpackIssuerAndSerialNumber( smime->asnc, &issuerAndSerialNumber, p, size, &err ); ASN_CMS_Free( smime->asnc->memMgr, p ); if( err ) { return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* attach IssuerAndSerialNumber to SignerIdentifier */ if( signerInfo->sid.data ) { if( ASN_TAG(signerInfo->sid.CHOICE_field_type) == ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag ) { SMIME_TRACE1("Had id data of type IssuerAndSerialNumber for signer %d, clean it", signer); ASN_CMS_FreeIssuerAndSerialNumber( smime->asnc, signerInfo->sid.data ); } else { SMIME_TRACE1("Had id data of type IssuerAndSerialNumber for signer %d, must not happen, leaking memory here", signer); pgpAssert(0); } } signerInfo->sid.CHOICE_field_type = ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag; signerInfo->sid.data = issuerAndSerialNumber; SMIME_TRACE("Set mandatory SignerIdentifier attribute for SignerInfo"); return 0; } /* Set capabilities for the signer (similiar to PGP key preferences) * Currently set encryption algorithms * * SMIMECapabilities is signed attribute [3] * * Most symbols here should have CMS_SMIME prefix instead of ASN_CMS, but compiler doesn't allow this * for the module that has IMPORT * */ SMIMEError asnSetSignerCaps( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const PGPCipherAlgorithm *algs, int nalgs ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_Attribute *SMIMECapabilitiesAttr; ASN_CMS_SMIMECapabilities *capabilities; P capabilities_der; int i; SMIMEError smimeerr; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE( "Setting signer capabilities" ); /* smimeCapabilities must be at [3] */ SMIMECapabilitiesAttr = signerInfo->signedAttrs->elt[3]; pgpAssert( OIDCMP( &SMIMECapabilitiesAttr->attrType, ASN_CMS_smimeCapabilities_OID )==0 ); pgpAssert( SMIMECapabilitiesAttr->attrValues.n==1 && SMIMECapabilitiesAttr->attrValues.elt[0]!=NULL ); /* Set the content. attrValues is a set of one element: DER SMIMECapabilities */ capabilities = ASN_CMS_NewSMIMECapabilities( smime->asnc ); if( capabilities==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* initialize a SET of nalgs SMIMECapability attributes */ capabilities->n = nalgs; capabilities->elt = ASN_CMS_Alloc( smime->asnc->memMgr, nalgs * sizeof(ASN_CMS_SMIMECapability*) ); if( capabilities->elt==NULL ) { capabilities->n = 0; ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } for( i=0; ielt[i] = ASN_CMS_NewSMIMECapability( smime->asnc ); if( capabilities->elt[i]==NULL ) break; } if( iasnc, capabilities ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* set capability [0] to algs[0], ... */ for( i=0; ielt[i]->capabilityID ); break; case kPGPCipherAlgorithm_AES128: smimeerr = SETOID( smime, ASN_CMS_id_aes128_CBC_OID, &capabilities->elt[i]->capabilityID ); break; case kPGPCipherAlgorithm_AES192: smimeerr = SETOID( smime, ASN_CMS_id_aes192_CBC_OID, &capabilities->elt[i]->capabilityID ); break; case kPGPCipherAlgorithm_AES256: smimeerr = SETOID( smime, ASN_CMS_id_aes256_CBC_OID, &capabilities->elt[i]->capabilityID ); break; default: smimeerr = SMIMEError_UnsupportedEncrAlg; break; } if( smimeerr ) { SMIME_TRACE2("Failed to set capability #%d for cipher %d", i, algs[i]); ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); return smimeerr | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } } /* export the set into capabilities_der */ capabilities_der.l = ASN_CMS_SizeofSMIMECapabilities( smime->asnc, capabilities, TRUE/*outerSizeFlag*/ ); capabilities_der.p = ASN_CMS_Alloc( smime->asnc->memMgr, capabilities_der.l ); capabilities_der.dontFree = FALSE; if( capabilities_der.p==NULL ) { ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err=0; /* must do this for ASN.1 compiler */ ASN_CMS_PackSMIMECapabilities( smime->asnc, capabilities_der.p, capabilities_der.l, capabilities, &err ); ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); if( err ) { pgpSMIMEFreePtr( &capabilities_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( SMIMECapabilitiesAttr->attrValues.elt[0]->val!=NULL ) { SMIME_TRACE1("Had SMIMECapabilities attribute for signer %d, clean it", signer); ASN_CMS_Free( smime->asnc->memMgr, SMIMECapabilitiesAttr->attrValues.elt[0]->val ); } SMIMECapabilitiesAttr->attrValues.elt[0]->val = capabilities_der.p; SMIMECapabilitiesAttr->attrValues.elt[0]->len = capabilities_der.l; SMIME_TRACE5("Set up SMIMECapabilitiesAttr as DER [%d] %02x %02x %02x %02x", capabilities_der.l, capabilities_der.p[0], capabilities_der.p[1], capabilities_der.p[2], capabilities_der.p[3] ); return 0; } /* Set same capabilities for all signers */ SMIMEError asnSetCaps( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, const PGPCipherAlgorithm *algs, int nalgs ) { const int signers = signedData->signerInfos.n; int signer; SMIMEError smimeerr = kPGPError_NoErr; /* to make the compiler happy */ if( signers == 0 ) { SMIME_TRACE("No signers, cannot set capabilities"); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } for( signer=0; signer < signers; signer++ ) { smimeerr = asnSetSignerCaps( smime, signer, signedData, algs, nalgs ); if( smimeerr ) break; } return smimeerr; } SMIMEError asnExportSigned( SMIME_CONTEXT *c, const ASN_CMS_SignedData *signedData, P *signed_der ) { size_t signedDataSize; PGPByte *signedData_der; ASN_CMS_ContentInfo *contentInfo; size_t contentInfoSize; PGPByte *contentInfo_der; SMIMEError smimeerr; int asnerr; signed_der->p = NULL; signed_der->l = 0; signedDataSize = ASN_CMS_SizeofSignedData( c->asnc, (ASN_CMS_SignedData *)signedData, TRUE/*outerSizeFlag*/ ); signedData_der = ASN_CMS_Alloc( c->asnc->memMgr, signedDataSize ); if( signedData_der==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for exported SignedData", signedDataSize); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } asnerr=0; ASN_CMS_PackSignedData( c->asnc, signedData_der, signedDataSize, (ASN_CMS_SignedData *)signedData, &asnerr ); if( asnerr ) { SMIME_TRACE2("Error %d packing SignedData (expected result to be %d bytes)", asnerr, signedDataSize ); ASN_CMS_Free( c->asnc->memMgr, signedData_der ); return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* Now wrap signedData_der into ContentType */ contentInfo = ASN_CMS_NewContentInfo( c->asnc ); if( contentInfo==NULL ) { ASN_CMS_Free( c->asnc->memMgr, signedData_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* attach SignedData to ContentInfo object */ contentInfo->content.val = signedData_der; contentInfo->content.len = signedDataSize; smimeerr = SETOID( c, ASN_CMS_id_signedData_OID, &contentInfo->contentType ); if( smimeerr ) { SMIME_TRACE("Failed to set id-signedData OID"); ASN_CMS_FreeContentInfo( c->asnc, contentInfo ); return smimeerr | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } contentInfoSize = ASN_CMS_SizeofContentInfo( c->asnc, contentInfo, TRUE/*outerSizeFlag*/ ); contentInfo_der = ASN_CMS_Alloc( c->asnc->memMgr, contentInfoSize ); if( contentInfo_der==NULL ) { ASN_CMS_FreeContentInfo( c->asnc, contentInfo ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } ASN_CMS_PackContentInfo( c->asnc, contentInfo_der, contentInfoSize, contentInfo, &asnerr ); ASN_CMS_FreeContentInfo( c->asnc, contentInfo ); if( asnerr ) { SMIME_TRACE2("Error %d packing ContentInfo (expected result to be %d bytes)", asnerr, contentInfoSize ); ASN_CMS_Free( c->asnc->memMgr, contentInfo_der ); return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Packed %d bytes of ContentInfo for SignedData", contentInfoSize); signed_der->p = contentInfo_der; signed_der->l = contentInfoSize; signed_der->dontFree = FALSE; return 0; } #if 0 void test_smime_sign( PGPContextRef sdkcontext, P *cert_der ) { SMIME_CONTEXT c; SMIMEError err; PGPHashAlgorithm hashAlgs[] = { kPGPHashAlgorithm_SHA, kPGPHashAlgorithm_SHA, kPGPHashAlgorithm_Invalid }; const P hash = { (void*)"\x01\x02\x03\x04\x05\x05\x07\x08\x09\x0a\x01\x02\x03\x04\x05\x05\x07\x08\x09\x0a", 20, TRUE }; const P sig = { (void*)"\x0a\x0b\x0c\x0d\x0e\x0f", 6, TRUE }; int signer = 0; err = asnInitSMIMEContext( sdkcontext, &c ); SMIME_TRACE1( "asnInitSMIMEContext returned %08x", err ); err = asnCreateMultipartSigned( &c, 100 /* signers */, 10 /* certificates */ ); SMIME_TRACE1( "asnCreateMultipartSigned returned %08x", err ); if( err ) { asnFreeSMIMEContext( &c ); return; } err = asnSetHashAlgorithms( &c, c.signedData, hashAlgs ); SMIME_TRACE1( "returned %08x", err ); err = asnSetSignerHashAlg( &c, signer, c.signedData, kPGPHashAlgorithm_SHA ); SMIME_TRACE1( "returned %08x", err ); err = asnSetSignerMsgHash( &c, signer, c.signedData, &hash ); SMIME_TRACE1( "returned %08x", err ); err = asnSetSigner( &c, 0, c.signedData, cert_der ); SMIME_TRACE1( "returned %08x", err ); err = asnSetSignerSignature( &c, signer, c.signedData, &sig ); SMIME_TRACE1( "returned %08x", err ); err = asnFreeSMIMEContext( &c ); SMIME_TRACE1( "asnInitSMIMEContext returned %08x", err ); } #endif /*__Editor_settings____ Local Variables: tab-width: 4 End: vi: ts=4 sw=4 vim: si _____________________*/ ۙ*}hIA2zP[fi7BECϗΎxVqy၍N1g~);sSgMtĤA(R{JsiHoC}K8f 33F="h 2ʻqPiSZM[=R)$Ic9UJ-&pO82TSY@ 9+;?4>@Fødq|(ĸ2ۼ/.I`ݜZ+V4ۉ1RTK$hI]+b?Z -i]U|-V;{u |6Aiio;CrرW lmjʖU}`70 Α{Cv)- B A 30gʨMK[VѰꍖS<UoG]+Q=%Ku--C2!q ~\; \V'̯ylj/ZzB+CYs} wwNGF*HlQ+AGp UFSdufu0q ŌQΪ}3 mS E/oeK5w$&|SWZY@wCu9HA aSq;C`\喓r՝]׍cҵB,wnJ;m>ȹwPmXw]߁-KFiL[o%zA W;ʀf5F \,[75:;FLF5a{ݸ60Xk`wlZu*؅52;'Qu.yIBڶ߲: 'ޖ[w6.`pۂp~)M<@JBRJmnOaX*eHCqu;g7/wj( I)P8T*#:+@ r23~bk۴!QR5eW>X4K֒a]ZdsG ~ #h#'$Z ?B,A1&D|~w61ԮZP³f-8"ogDF 4KZtKC_{}EY-]rW!qkV֥u(70*бsQhS/!3DFI B:T8>XHwHFh3ML` z@]q6_ oHҚ2XRKFbV*3"15gOIi$M844uCFenӐ[r GIviBJ G7^vJELU+,G&&Ӕ3kg-;/?;߯;[4wKĞ0yӇYhv$i?SiD *\?]v 1LZ'wm 8WHFApg.&U4vʈЬZobɖN>s$eQPf'A|G-32f !$ _A{;:ȟ% ;8J( ;1I8쫥lh2j[è eJU3=+׉nk.I ؠ|]R%H?h粺{(É`U n*#5ہ-/^g'*Լ0 `&}ӶsȚK q1`^71w9L[{+/x6UM`⸄$#Cy_W4hB:h^]5~ "HOҜݱo,Z?JLqQCimf>tgxg8&q*KRrH{+*tm<; Ԧ׷KeU#y"F)s . J JcKj7-_mڅ@bKGOڝ7ď''(-5vϘ֭V ,P/ex%ΒAck ^gLƤĐ2~M{B.%1OrgÇ_uJgO*Z v2~n3qA SiH3^zmF#eO CrV6X|Jm+!p d[mr#5|3X]k "cֆ&C:y4 II+,o|[H ֔=Yb|Kv6,;5vMwTJnrb9uݧwowNj T(1B62^!X]6M)LE>w;V.OV s<H=wKlXy!I FPS\ŀ 5MLjM̴z]Jh|'n6௉ $Y3NmT!N9ʖқ ;Y;&pKPzq?h81WNCMj]`zNI8Mz҆V!~i?vnʂ$b } HF7;PMzDWXiPGjl%-\[d|#΍@ 0AB|n]{n<= $(LJɨ[)lD̐Up[oV݌V g p)*([j봐yK[eZ*J\Q̳> q@*1U/dccUXrH/74\ 19,G/ڷl@|_6J-tmek]/;33Fݖ#k8bH?L,@*IRH9FY .[!}U~ŽW&`ۼ]zŐ/aHqUD(,0+kp69JF`ߩc NiM]e4Gwza>5jP %6b}h_Z meyB.;sw&\J1A*S[5k/*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 routines needed for * encryption in SMIME. * * $Id: pgpSMIMEasnEncrypt.c,v 1.2 2003/05/14 00:45:28 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" SMIMEError asnCreateEnvelopedData( SMIME_CONTEXT *smime, int recipients ) { ASN_CMS_EnvelopedData *envelopedData; SMIMEError smimeerr; int recipient; SMIME_TRACE1("Building top level EnvelopedData for %d recipients", recipients); envelopedData = ASN_CMS_NewEnvelopedData(smime->asnc); if( envelopedData==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Version 0. OriginatorInfo is absent, RecipientInfo structures are version 0 (see bellow), UnprotectedAttributes is absent */ ASN_CMS_PutIntVal( smime->asnc, &envelopedData->version, 0 ); envelopedData->recipientInfos.n = recipients; envelopedData->recipientInfos.elt = ASN_CMS_Alloc( smime->asnc->memMgr, recipients * sizeof(ASN_CMS_RecipientInfo*) ); if( envelopedData->recipientInfos.elt==NULL ) { envelopedData->recipientInfos.n = 0; ASN_CMS_FreeEnvelopedData( smime->asnc, envelopedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } memset( envelopedData->recipientInfos.elt, 0, recipients * sizeof(ASN_CMS_RecipientInfo*) ); /* create recipients, allocate memory and set as much fields as we can here */ smimeerr=0; for( recipient=0; recipientasnc ); if( ri==NULL ) { SMIME_TRACE1( "Failed to allocate RecipientInfo for recipient %d", recipient ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } /* RecipientInfo for us always means KeyTransRecipientInfo */ ktri = ASN_CMS_NewKeyTransRecipientInfo( smime->asnc ); if( ktri == NULL ) { SMIME_TRACE1( "Failed to allocate KeyTransRecipientInfo for recipient %d", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } pgpAssert( ri->data==NULL ); ri->data = ktri; ri->CHOICE_field_type = ASN_CMS_ktri_RecipientInfoFieldTag; /* SMIME_TRACE2("Attached ktri %p for recipient %d", ktri, recipient); */ /* Version 0. RecipientIdentifier is IssueAndSerialNumber, not SubjectKeyIdentifier */ ASN_CMS_PutIntVal( smime->asnc, &ktri->version, 0 ); /* Construct IssuerAndSerialNumber */ ktri->rid.data = ASN_CMS_NewIssuerAndSerialNumber( smime->asnc ); if( ktri->rid.data==NULL ) { SMIME_TRACE1( "Failed to allocate IssuerAndSerialNumber for recipient %d", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } ktri->rid.CHOICE_field_type = ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag; /* Construct OPTIONAL parameters field for KeyEncryptionAlgorithmIdentifier */ ktri->keyEncryptionAlgorithm.parameters = ASN_CMS_NewANY( smime->asnc ); if( ktri->keyEncryptionAlgorithm.parameters==NULL ) { SMIME_TRACE1( "Failed to allocate ANY for recipient %d's KeyEncryptionAlgorithm parameters", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } /* ... and initialize it with NULL */ smimeerr = setnull( smime, ktri->keyEncryptionAlgorithm.parameters ); if( smimeerr ) { SMIME_TRACE1( "Failed to set ANY to NULL for recipient %d's KeyEncryptionAlgorithm parameters", recipient ); ASN_CMS_FreeRecipientInfo( smime->asnc, ri ); smimeerr |= (SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); break; } /* Finally attach RecipientInfo */ envelopedData->recipientInfos.elt[recipient] = ri; } /* for each recipient... */ if( smimeerr ) { ASN_CMS_FreeEnvelopedData( smime->asnc, envelopedData ); return smimeerr; } { ASN_CMS_EncryptedContentInfo *encryptedContentInfo = &envelopedData->encryptedContentInfo; SETOID( smime, ASN_CMS_id_data_OID, &encryptedContentInfo->contentType ); encryptedContentInfo->contentEncryptionAlgorithm.parameters = ASN_CMS_NewANY( smime->asnc ); if( encryptedContentInfo->contentEncryptionAlgorithm.parameters==NULL ) { SMIME_TRACE("Failed to create ANY for parameters of EncryptedContentInfo->ContentEncryptionAlgorithIdentifier"); ASN_CMS_FreeEnvelopedData( smime->asnc, envelopedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } } /* encryptedContentInfo */ if( smime->envelopedData!=NULL ) { SMIME_TRACE1("Had old envelopedData %p in the context, clean it", smime->envelopedData); ASN_CMS_FreeEnvelopedData( smime->asnc, smime->envelopedData ); } smime->envelopedData = envelopedData; SMIME_TRACE1("Added envelopedData %p to the context", smime->envelopedData); return 0; } /* CBC mode is assumed for 'alg' */ SMIMEError asnSetEnvelopeContentEncrAlg( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, const PGPCipherAlgorithm alg, const P *IV ) { ASN_CMS_ContentEncryptionAlgorithmIdentifier *contentEncryptionAlg; SMIMEError smimeerr; contentEncryptionAlg = &envelopedData->encryptedContentInfo.contentEncryptionAlgorithm; SMIME_TRACE5("Setting %d encryption algorithm, IV [%d] %02x %02x %02x", alg, IV->l, IV->p[0], IV->p[1], IV->p[2] ); switch( alg ) { case kPGPCipherAlgorithm_3DES: smimeerr = SETOID( smime, ASN_CMS_des_ede3_cbc_OID, &contentEncryptionAlg->algorithm ); break; case kPGPCipherAlgorithm_AES128: smimeerr = SETOID( smime, ASN_CMS_id_aes128_CBC_OID, &contentEncryptionAlg->algorithm ); break; case kPGPCipherAlgorithm_AES192: smimeerr = SETOID( smime, ASN_CMS_id_aes192_CBC_OID, &contentEncryptionAlg->algorithm ); break; case kPGPCipherAlgorithm_AES256: smimeerr = SETOID( smime, ASN_CMS_id_aes256_CBC_OID, &contentEncryptionAlg->algorithm ); break; default: SMIME_TRACE1("Unsupported algorithm %d passed as an encryption algorithm", alg); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } { ASN_CMS_IV *iv; PGPByte *iv_der; size_t size; int err; if( smimeerr ) { SMIME_TRACE1("Failed to set OID for algorithm %d", alg); return smimeerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } iv = ASN_CMS_NewIV(smime->asnc); if( iv==NULL ) { SMIME_TRACE1("Failed to allocate IV object for algorithm %d", alg); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* attach temporarily input IV data */ iv->val = IV->p; iv->len = IV->l; size = ASN_CMS_SizeofIV( smime->asnc, iv, TRUE/*outerSizeFlag*/ ); iv_der = ASN_CMS_Alloc( smime->asnc->memMgr, size ); if( iv_der == NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for CBCParameter (IV)", size); /* detach data */ iv->val = NULL; iv->len = 0; ASN_CMS_FreeIV(smime->asnc, iv); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } err = 0; ASN_CMS_PackIV( smime->asnc, iv_der, size, iv, &err ); /* detach data */ iv->val = NULL; iv->len = 0; ASN_CMS_FreeIV(smime->asnc, iv); if( err ) { SMIME_TRACE1("Failed to pack IV, ASN err=%d", err); ASN_CMS_Free(smime->asnc->memMgr, iv_der); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Attach IV to the 'parameters' */ pgpAssert( contentEncryptionAlg->parameters!=NULL );/* OPTIONAL in CMS, but mandatory here, so we must had created it earlier */ contentEncryptionAlg->parameters->val = iv_der; contentEncryptionAlg->parameters->len = size; } return 0; } /* move encrypted content to envelopedData */ SMIMEError asnSetEnvelopedEncrContent( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, P *encrContent ) { ASN_CMS_EncryptedContent *encryptedContent; /* see comments for decrypt */ encryptedContent = &envelopedData->encryptedContentInfo.encryptedContent; if( encryptedContent->val!=NULL ) { SMIME_TRACE1("Had EncryptedContent %p, freed", encryptedContent->val); ASN_CMS_Free( smime->asnc->memMgr, encryptedContent->val ); } encryptedContent->val = encrContent->p; encryptedContent->len = encrContent->l; SMIME_TRACE5("Moved encrypted content [%d] %02x %02x %02x %02x", encrContent->l, encrContent->p[0], encrContent->p[1], encrContent->p[2], encrContent->p[3] ); encrContent->dontFree = TRUE; /* transfer ownership */ return 0; } SMIMEError asnSetEnvelopeRecipientKeyEncrAlg( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, int recipient, PGPPublicKeyAlgorithm encrAlg ) { ASN_CMS_KeyTransRecipientInfo *ktri; pgpAssert( recipient < envelopedData->recipientInfos.n ); pgpAssert( ASN_TAG( envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type ) == ASN_CMS_ktri_RecipientInfoFieldTag ); ktri = (ASN_CMS_KeyTransRecipientInfo*)envelopedData->recipientInfos.elt[recipient]->data; SMIME_TRACE2("Setting public key algorithm %d for recipient %d", encrAlg, recipient); if( encrAlg != kPGPPublicKeyAlgorithm_RSA ) { SMIME_TRACE1("Unsupported KeyEncryptionAlgorithm for key transport", encrAlg); return SMIMEError_UnsupportedEncrAlg + (SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Have RSA algorithm here -- the only supported for key transport (and we support only key transport in RecipientInfo) */ SETOID( smime, ASN_CMS_rsaEncryption_OID, &ktri->keyEncryptionAlgorithm.algorithm ); /* Paramers setup to NULL earlier */ return 0; } /* Set recipient identification as IssuerAndSerialNumber */ SMIMEError asnSetEnvelopeRecipient( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, int recipient, const P *x509cert ) { ASN_CMS_KeyTransRecipientInfo *ktri; ASN_CMS_IssuerAndSerialNumber *id; ASN_CMS_Certificate *cert; int asnerr; pgpAssert( recipient < envelopedData->recipientInfos.n ); pgpAssert( ASN_TAG( envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type ) == ASN_CMS_ktri_RecipientInfoFieldTag ); ktri = (ASN_CMS_KeyTransRecipientInfo*)envelopedData->recipientInfos.elt[recipient]->data; pgpAssert( ASN_TAG(ktri->rid.CHOICE_field_type) == ASN_CMS_issuerAndSerialNumber_RecipientIdentifierFieldTag ); id = (ASN_CMS_IssuerAndSerialNumber*)ktri->rid.data; if( id==NULL ) { SMIME_TRACE1("IssuerAndSerialNumber is null for recipient %d (shoudld never happen)", recipient); return SMIMEError_CorruptData + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE5("Identifying recipient %d with certificate [%d] %02x %02x %02x", recipient, x509cert->l, x509cert->p[0], x509cert->p[1], x509cert->p[2] ); /* unpack certificate to get needed fields */ asnerr=0; ASN_CMS_UnpackCertificate( smime->asnc, &cert, x509cert->p, x509cert->l, &asnerr ); if( asnerr ) { SMIME_TRACE1("Error unpacking certificate that identifies recipient %d", recipient); return asnerr; } if( id==NULL ) { SMIME_TRACE("Count not create empty NewIssuerAndSerialNumber object"); ASN_CMS_FreeCertificate( smime->asnc, cert ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Now initialize IssuerAndSerialNumber structure by detaching content from the Certificate and * attaching it to id. This is potentially unsafe, but logically speaking this is exactly what we need to do. */ /* attach */ pgpAssert( id->issuer.val==NULL && id->issuer.len==0 ); id->issuer.val = cert->tbsCertificate.issuer.val; id->issuer.len = cert->tbsCertificate.issuer.len; pgpAssert( id->serialNumber.val==NULL && id->serialNumber.len==0 ); id->serialNumber.val = cert->tbsCertificate.serialNumber.val; id->serialNumber.len = cert->tbsCertificate.serialNumber.len; /* detach */ cert->tbsCertificate.issuer.val = NULL; cert->tbsCertificate.issuer.len = 0; cert->tbsCertificate.serialNumber.val = NULL; cert->tbsCertificate.serialNumber.len = 0; ASN_CMS_FreeCertificate( smime->asnc, cert ); #if PGP_USE_TRACE if( id->serialNumber.len <= 4 ) { long sn; sn = ASN_CMS_GetIntVal (smime->asnc, &id->serialNumber, &asnerr); SMIME_TRACE4( "Set %d byte DN and %d byte SN=%d for recipient %d", id->issuer.len, id->serialNumber.len, sn, recipient ); } else SMIME_TRACE3( "Set %d byte DN and %d byte SN for recipient %d", id->issuer.len, id->serialNumber.len, recipient ); #endif return 0; } SMIMEError asnSetEnvelopeRecipientESK( SMIME_CONTEXT *smime, ASN_CMS_EnvelopedData *envelopedData, int recipient, const P *esk ) { ASN_CMS_KeyTransRecipientInfo *ktri; ASN_CMS_EncryptedKey *encryptedKey; pgpAssert( recipient < envelopedData->recipientInfos.n ); pgpAssert( ASN_TAG( envelopedData->recipientInfos.elt[recipient]->CHOICE_field_type ) == ASN_CMS_ktri_RecipientInfoFieldTag ); ktri = (ASN_CMS_KeyTransRecipientInfo*)envelopedData->recipientInfos.elt[recipient]->data; encryptedKey = &ktri->encryptedKey; encryptedKey->val = ASN_CMS_Alloc( smime->asnc->memMgr, esk->l ); if( encryptedKey->val==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for EncryptedKey", esk->l); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } encryptedKey->len = esk->l; memcpy( encryptedKey->val, esk->p, esk->l ); SMIME_TRACE5("Set EncryptedKey [%d] %02x %02x %02x for recipient %d", esk->l, esk->p[0], esk->p[1], esk->p[2], recipient ); return 0; } /* Exports envelopedData into DER form in a straignforward inefficient way. * * Any better solution will require changes to asn1comp. One possible solution is to * teach compiler to output indefinite size packet so that we could export envelopedData * with our unique tag in place of encryptedContent. This allows us to replace this tag inside DER encoding block * by actual encrypted content without invalidating structure sizes or doing complicated header changes * to account for size adjustment. This solution will spare compiler from doing more advanced memory management * and is more efficient for application */ SMIMEError asnExportEnveloped( SMIME_CONTEXT *smime, const ASN_CMS_EnvelopedData *envelopedData, P *enveloped_der ) { size_t encrDataSize, contentInfoSize; PGPByte *encrData_der, *contentInfo_der; ASN_CMS_ContentInfo *contentInfo; SMIMEError smimeerr; int asnerr; enveloped_der->p = NULL; enveloped_der->l = 0; /* TODO: potentially huge */ encrDataSize = ASN_CMS_SizeofEnvelopedData( smime->asnc, (ASN_CMS_EnvelopedData *)envelopedData, TRUE/*outerSizeFlag*/ ); encrData_der = ASN_CMS_Alloc( smime->asnc->memMgr, encrDataSize ); if( encrData_der==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for exported EnvelopedData", encrDataSize); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } asnerr=0; ASN_CMS_PackEnvelopedData( smime->asnc, encrData_der, encrDataSize, (ASN_CMS_EnvelopedData *)envelopedData, &asnerr ); if( asnerr ) { SMIME_TRACE2("Error %d packing EnvelopedData (expected result to be %d bytes)", asnerr, encrDataSize ); ASN_CMS_Free( smime->asnc->memMgr, encrData_der ); return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* Now wrap encrData_der into ContentType */ contentInfo = ASN_CMS_NewContentInfo( smime->asnc ); if( contentInfo==NULL ) { ASN_CMS_Free( smime->asnc->memMgr, encrData_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } /* attach SignedData to ContentInfo object */ contentInfo->content.val = encrData_der; contentInfo->content.len = encrDataSize; smimeerr = SETOID( smime, ASN_CMS_id_envelopedData_OID, &contentInfo->contentType ); if( smimeerr ) { SMIME_TRACE("Failed to set id-envelopedData OID"); ASN_CMS_FreeContentInfo( smime->asnc, contentInfo ); return smimeerr | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } contentInfoSize = ASN_CMS_SizeofContentInfo( smime->asnc, contentInfo, TRUE/*outerSizeFlag*/ ); contentInfo_der = ASN_CMS_Alloc( smime->asnc->memMgr, contentInfoSize ); if( contentInfo_der==NULL ) { ASN_CMS_FreeContentInfo( smime->asnc, contentInfo ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } ASN_CMS_PackContentInfo( smime->asnc, contentInfo_der, contentInfoSize, contentInfo, &asnerr ); ASN_CMS_FreeContentInfo( smime->asnc, contentInfo ); if( asnerr ) { SMIME_TRACE2("Error %d packing ContentInfo (expected result to be %d bytes)", asnerr, contentInfoSize ); ASN_CMS_Free( smime->asnc->memMgr, contentInfo_der ); return asnerr + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_ENCRYPTION|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Packed %d bytes of ContentInfo for EnvelopedData", contentInfoSize); enveloped_der->p = contentInfo_der; enveloped_der->l = contentInfoSize; enveloped_der->dontFree = FALSE; return 0; } #if SMIME_TEST void test_smime_encrypt( PGPContextRef sdkcontext, P *cert_der ) { SMIME_CONTEXT c; SMIMEError err; err = asnInitSMIMEContext( sdkcontext, &c ); SMIME_TRACE1("Returned %08x", err); err = asnCreateEnvelopedData( &c, 2 ); SMIME_TRACE1("Returned %08x", err); { const P iv = { (void*)"\x01\x02\x03\x04\x05\x06\x07\x08", 8, TRUE }; err = asnSetEnvelopeContentEncrAlg( &c, c.envelopedData, kPGPCipherAlgorithm_3DES, &iv ); SMIME_TRACE1("Returned %08x", err); } err = asnSetEnvelopeRecipientKeyEncrAlg( &c, c.envelopedData, 0, kPGPPublicKeyAlgorithm_RSA ); SMIME_TRACE1("Returned %08x", err); err = asnSetEnvelopeRecipient( &c, c.envelopedData, 0, cert_der ); SMIME_TRACE1("Returned %08x", err); { PGPByte buf[1024/8]; P esk = {buf, sizeof(buf), TRUE}; memset( buf, 0xff, sizeof(buf) ); err = asnSetEnvelopeRecipientESK( &c, c.envelopedData, 0, &esk ); SMIME_TRACE1("Returned %08x", err); } err = asnFreeSMIMEContext( &c ); SMIME_TRACE1("Returned %08x", err); } #endif /*__Editor_settings____ Local Variables: tab-width: 4 End: vi: ts=4 sw=4 vim: si _____________________*/ /*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 DER signature verification * for SMIME. * * $Id: pgpSMIMEasnVerify.c,v 1.6 2004/05/14 03:38:47 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" #include "pgpASN_SMIME.h" #include "pgpASN_SMIME_asn.h" #include "pgpASN_SMIME_oid.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" SMIMEError asnGetSignedContent( const ASN_CMS_SignedData *signedData, P *eContent ) { eContent->p = NULL; eContent->l = 0; if( signedData==NULL ) { return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } if( signedData->encapContentInfo.eContent==NULL ) { SMIME_TRACE("EncapsulatedContentInfo.eContent in NOT present, have clear-signed message"); return 0; } eContent->l = (PGPUInt)signedData->encapContentInfo.eContent->len; if( eContent->l != signedData->encapContentInfo.eContent->len ) { eContent->l = 0; return SMIMEError_SizeTooLarge | SMIME_ERROR_CATEGORY_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } eContent->p = signedData->encapContentInfo.eContent->val; eContent->dontFree = TRUE; SMIME_TRACE4( "EncapsulatedContentInfo.eContent in present [%d] %02x %02x %02x ..., signedData are enveloped", eContent->l, eContent->p[0], eContent->p[1], eContent->p[2] ); return 0; } /* number or signers, or error */ int asnGetNumberOfSigners( const ASN_CMS_SignedData *signedData ) { if( signedData==NULL ) return 0; return signedData->signerInfos.n; } SMIMEError asnGetSignerHashAlg( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, PGPHashAlgorithm *hashAlg ) { const ASN_CMS_SignerInfo *signerInfo; (void)c; pgpAssert( signedData && signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; *hashAlg = kPGPHashAlgorithm_Invalid; /* determine the hash type */ if( OIDCMP( &signerInfo->digestAlgorithm.algorithm, ASN_CMS_sha_1_OID )==0 ) { SMIME_TRACE( "SHA-1 hash alg. detected for the signer" ); *hashAlg = kPGPHashAlgorithm_SHA; } else if( OIDCMP( &signerInfo->digestAlgorithm.algorithm, ASN_CMS_md5_OID )==0 ) { SMIME_TRACE( "MD5 hash alg. detected for the signer" ); *hashAlg = kPGPHashAlgorithm_MD5; } else { SMIME_TRACE("Unknown signing algorith used for the signature"); return SMIMEError_UnsupportedHash + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } return 0; } /* Get advertised hash algorithms employed by signers as reported in SignedData. No checks is done for * individual signers */ SMIMEError asnGetHashAlgs( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, PGPHashAlgorithm hashAlgs[/*size signers*/], int *n ) { const int signers = signedData->signerInfos.n; int myn=0; int i; (void)smime; *n = 0; if( signedData->digestAlgorithms.n==0 ) { SMIME_TRACE1("DigestAlgorithms set is empty for %d signers (no advertised algs)", signers); return SMIMEError_InconsistentData + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } if( signedData->digestAlgorithms.n > signers ) { /* Could be more tolerant */ SMIME_TRACE2("%d hash algorithms advertised for %d signers", signedData->digestAlgorithms.n, signers); return SMIMEError_InconsistentData + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } for( i=0; idigestAlgorithms.n; i++ ) { ASN_CMS_DigestAlgorithmIdentifier *digestAlgID = signedData->digestAlgorithms.elt[i]; pgpAssert(ialgorithm, ASN_CMS_sha_1_OID )==0 ) { SMIME_TRACE1("SignedData advertised SHA-1 in the position %d", i); hashAlgs[myn++] = kPGPHashAlgorithm_SHA; } else if ( OIDCMP( &digestAlgID->algorithm, ASN_CMS_sha_1_OID )==0 ) { SMIME_TRACE1("SignedData advertised md5 in the position %d", i); hashAlgs[myn++] = kPGPHashAlgorithm_MD5; } else { SMIME_TRACE1("Unknown signing algorith advertised in the position %d", i); return SMIMEError_UnsupportedHash + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } } SMIME_TRACE1("%d hash algorithms advertised", myn); *n = myn; return 0; } /* Returns a data hash for this signer. This value is different for each signer as determined * by only a hash type. The set of signedAttributes is optional, but if it present then messageDigest must be there. * The absence of the field takes away ability to destinquish * between forged signature and content modified by transfer agents. PGP always generates this attribute * as many e-mail clients. * * In case of multipart/signed the hash is calculated over headers and a body as shown by '|', * lines end with * * ------=_NextPart_123 *|Content-Type: text/plain; *| charset="iso-8859-1" *|Content-Transfer-Encoding: 7bit *| *|This is a body of a signed message * * ------=_NextPart_123 * Content-Type: application/x-pkcs7-signature; * name="smime.p7s" * Content-Transfer-Encoding: base64 * Content-Disposition: attachment; * filename="smime.p7s" * * MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIII6TCCAngw * ... * */ SMIMEError asnGetSignerMsgHash( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, P /*out*/ *hashOut ) { int n_signedAttrs; const ASN_CMS_SignerInfo *signerInfo; int i; ASN_CMS_OCTET_STRING *octetstr = NULL; int err; hashOut->p = NULL; hashOut->l = 0; pgpAssert( signedData && signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; if( signerInfo->signedAttrs == NULL ) { SMIME_TRACE("Could not find useful but unfortunately optional messageDigest in a an empty set SignedAttributes"); return SMIMEError_NotFound | 0 /*no error*/ | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } n_signedAttrs = signerInfo->signedAttrs->n; SMIME_TRACE1("Looking for id-messagegeDigest among %d SignedAttributes", n_signedAttrs); /* look for id-messagegeDigest */ for( i=0; isignedAttrs->elt[i]->attrType, ASN_CMS_id_messageDigest_OID )==0 ) break; } if( i==n_signedAttrs ) { /* if the set is non-empty, the message hash must be present */ SMIME_TRACE1("Could not find mandatory messageDigest in a set of %d signedAttributes", n_signedAttrs); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } if( signerInfo->signedAttrs->elt[i]->attrValues.n != 1 ) { SMIME_TRACE1("Found messageDigest as attribute #%d, but the attrValues set has %d elements", signerInfo->signedAttrs->elt[i]->attrValues.n ); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } /* This ANY is DER encoded OCTET STRING */ SMIME_TRACE5( "Found messageDigest as attribute #%d, DER [%d] %02x %02x %02x", i, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->len, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->val[0], signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->val[1], signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->val[2] ); ASN_CMS_UnpackOCTET_STRING( c->asnc, &octetstr, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->val, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->len, &err ); if( err != 0 || octetstr==NULL ) { SMIME_TRACE ( "Failed to parse DER hash as octet string" ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } SMIME_TRACE5("Parsed hash as octet string [%d] %02x %02x %02x %02x", octetstr->len, octetstr->val[0], octetstr->val[1], octetstr->val[2], octetstr->val[3] ); if( octetstr->len > c->contentHashInternal.l ) { hashOut->l = (PGPUInt)octetstr->len; ASN_CMS_FreeOCTET_STRING( c->asnc, octetstr ); return SMIMEError_BufferTooShort | SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING; } hashOut->l = (PGPUInt)octetstr->len; hashOut->p = c->contentHashInternal.p; hashOut->dontFree = c->contentHashInternal.dontFree; memcpy( hashOut->p, octetstr->val, octetstr->len ); ASN_CMS_FreeOCTET_STRING( c->asnc, octetstr ); return 0; } PGPPublicKeyAlgorithm asnGetSignerSignatureAlg( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData ) { ASN_CMS_SignerInfo *signerInfo; (void)c; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; if( OIDCMP( &signerInfo->signatureAlgorithm.algorithm, ASN_CMS_rsaEncryption_OID )==0 ) { SMIME_TRACE("rsaEncryption SignatureAlgorityhmIdentifier detected"); return kPGPPublicKeyAlgorithm_RSA; } else if( OIDCMP( &signerInfo->signatureAlgorithm.algorithm, ASN_CMS_id_dsa_with_sha1_OID )==0 ) { SMIME_TRACE("id-dsa-with-sha1 SignatureAlgorityhmIdentifier detected"); return kPGPPublicKeyAlgorithm_DSA; } else { #if PGP_USE_TRACE if( signerInfo->signatureAlgorithm.algorithm.len >= 4 ) { SMIME_TRACE5( "Unknown SignatureAlgorityhmIdentifier found [%d] %02x %02x %02x %02x", signerInfo->signatureAlgorithm.algorithm.len, signerInfo->signatureAlgorithm.algorithm.val[0], signerInfo->signatureAlgorithm.algorithm.val[1], signerInfo->signatureAlgorithm.algorithm.val[2], signerInfo->signatureAlgorithm.algorithm.val[3] ); } else SMIME_TRACE1( "Unknown SignatureAlgorityhmIdentifier found, size %d", signerInfo->signatureAlgorithm.algorithm.len ); #endif return kPGPPublicKeyAlgorithm_Invalid; } } SMIMEError asnGetSignerSignature( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, P /*out*/ *sig ) { PGPByte *p; PGPUInt n; ASN_CMS_SignerInfo *signerInfo; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; sig->p = NULL; sig->l = 0; n = (PGPUInt)signerInfo->signature.len; SMIME_TRACE5( "Have signature [%d] %02x %02x %02x %02x", n, signerInfo->signature.val[0], signerInfo->signature.val[1], signerInfo->signature.val[2], signerInfo->signature.val[3] ); if( n != signerInfo->signature.len ) { return SMIMEError_SizeTooLarge + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } p = ASN_CMS_Alloc( c->asnc->memMgr, n ); if( !p ) { return SMIMEError_NoMemoryAtVeryfying + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } memcpy( p, signerInfo->signature.val, n ); sig->p = p; sig->l = n; sig->dontFree = FALSE; return 0; } /* Calculate the hash of data that signer signed using specified hash, i.e. signed attributes or * eContent */ SMIMEError asnGetSignedAttrs( SMIME_CONTEXT *c, int signer, const ASN_CMS_SignedData *signedData, P /*out*/ *attrs ) { const ASN_CMS_SignerInfo *signerInfo; PGPByte *p; PGPUInt n; size_t nAsSize; int err; pgpAssert( attrs ); attrs->p = NULL; attrs->l = 0; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; if( signerInfo->signedAttrs==NULL || signerInfo->signedAttrs->n == 0 ) { SMIME_TRACE( "TODO: signed eContent not implemented yet" ); return SMIMEError_NotFound | SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING; } n = signerInfo->signedAttrs->n; SMIME_TRACE1( "asnGetSignedAttrs: %d signed attributes", n ); /* Export signed attributes so we can hash them */ nAsSize = ASN_CMS_SizeofSignedAttributes( c->asnc, signerInfo->signedAttrs, TRUE ); n = (PGPUInt)nAsSize; SMIME_TRACE1( "asnGetSignedAttrs: DER of signed attributes occupies %d bytes", n ); if( n != nAsSize ) { return SMIMEError_SizeTooLarge | SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING; } p = ASN_CMS_Alloc( c->asnc->memMgr, n ); if( p==NULL ) { SMIME_TRACE1("Out of memory while trying to reserve %d bytes for DER signed attributes", n); return SMIMEError_NoMemoryAtVeryfying | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } ASN_CMS_PackSignedAttributes( c->asnc, p, n, signerInfo->signedAttrs, &err ); if( err!=0 ) { SMIME_TRACE1("Error %d while packing signed attributes", err); ASN_CMS_Free( c->asnc->memMgr, p ); return SMIMEError_CorruptDataAtVeryfying | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE5( "Packed signed attributes: [%d] %02x %02x %02x %02x", n, p[0], p[1], p[2], p[3] ); attrs->p = p; attrs->l = n; attrs->dontFree = FALSE; return 0; } /* allocates memory and exports X509 certificate. Returns NULL for other types of certificates */ static SMIMEError export_x509cert( SMIME_CONTEXT *c, ASN_CMS_CertificateChoices *cert, P *out ) { ASN_CMS_Certificate *x509cert; size_t x509certsizeAsSize; PGPUInt x509certsize; PGPByte *p; int err = 0; out->p = NULL; out->l = 0; /* determine certificate type, 3 types are possible */ if( ASN_TAG(cert->CHOICE_field_type) != ASN_CMS_certificate_CertificateChoicesFieldTag ) { SMIME_TRACE("Certificate must be X509 certificate"); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_NOT_IMPL | SMIME_ERROR_ENCODING_DECODING; } x509cert = (ASN_CMS_Certificate*)cert->data; x509certsizeAsSize = ASN_CMS_SizeofCertificate( c->asnc, x509cert, TRUE ); x509certsize = (PGPUInt)x509certsizeAsSize; if( x509certsize != x509certsizeAsSize ) { return SMIMEError_SizeTooLarge | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } p = ASN_CMS_Alloc( c->asnc->memMgr, x509certsize ); if( p==NULL ) { SMIME_TRACE1("Out of memory while trying to reserve %d bytes for X509 certificate", x509certsize); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } ASN_CMS_PackCertificate( c->asnc, p, x509certsize, x509cert, &err ); if( err!=0 ) { SMIME_TRACE1("Error %d while packing certificate", err); ASN_CMS_Free( c->asnc->memMgr, p ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE5( "Exported X509 cert [%d] %02x %02x %02x %02x", x509certsize, p[0], p[1], p[2], p[3] ); out->p = p; out->l = x509certsize; out->dontFree = FALSE; return 0; } /* certificates in SignerInfo is optional */ int asnGetNumberOfCerts( SMIME_CONTEXT *c, ASN_CMS_SignedData *signedData ) { (void)c; if( signedData->certificates==NULL ) return 0; return signedData->certificates->n; } /* compare certificate with given identification */ static PGPBoolean cert_match_with_IssuerAndSerialNumber( ASN_CMS_CertificateChoices *cert, ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber ) { ASN_CMS_Certificate *x509cert; /* determine certificate type, 3 types are possible */ switch( ASN_TAG(cert->CHOICE_field_type) ) { case ASN_CMS_certificate_CertificateChoicesFieldTag: break; case ASN_CMS_extendedCertificate_CertificateChoicesFieldTag: SMIME_TRACE("cert_match_IssuerAndSerialNumber: Obsolete ExtendedCertificate certificate type"); return FALSE; case ASN_CMS_attrCert_CertificateChoicesFieldTag: SMIME_TRACE("cert_match_IssuerAndSerialNumber: Unusual certificate type AttributeCertificate, ignoring"); return FALSE; default: SMIME_TRACE1("cert_match_IssuerAndSerialNumber: Unknown certificate type %d", ASN_TAG(cert->CHOICE_field_type)); return FALSE; } /* currently support only normal Certificate */ pgpAssert( ASN_TAG(cert->CHOICE_field_type)==ASN_CMS_certificate_CertificateChoicesFieldTag ); x509cert = (ASN_CMS_Certificate*)cert->data; if( sncmp( & x509cert->tbsCertificate.serialNumber, &issuerAndSerialNumber->serialNumber )!=0 ) { SMIME_TRACE("cert_match_IssuerAndSerialNumber: SN doesn't match"); return FALSE; } if( namecmp( & x509cert->tbsCertificate.issuer, &issuerAndSerialNumber->issuer )!=0 ) { SMIME_TRACE("cert_match_IssuerAndSerialNumber: issuer's DN doesn't match"); return FALSE; } SMIME_TRACE("cert_match_IssuerAndSerialNumber: found a cert based on IssuerAndSerialNumber"); return TRUE; } /* compare certificate with given identification */ static PGPBoolean cert_match_with_SubjectKeyIdentifier( ASN_CMS_CertificateChoices *cert, ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier ) { ASN_CMS_Certificate *x509cert; int i; /* determine certificate type, 3 types are possible */ switch( ASN_TAG(cert->CHOICE_field_type) ) { case ASN_CMS_certificate_CertificateChoicesFieldTag: break; case ASN_CMS_extendedCertificate_CertificateChoicesFieldTag: SMIME_TRACE("cert_match_for_subjectKeyIdentifier: Obsolete ExtendedCertificate certificate type"); return FALSE; case ASN_CMS_attrCert_CertificateChoicesFieldTag: SMIME_TRACE("cert_match_for_subjectKeyIdentifier: Unusual certificate type AttributeCertificate, ignoring"); return FALSE; default: SMIME_TRACE1("cert_match_for_subjectKeyIdentifier: Unknown certificate type %d", ASN_TAG(cert->CHOICE_field_type)); return FALSE; } /* currently support only normal Certificate */ pgpAssert( ASN_TAG(cert->CHOICE_field_type)==ASN_CMS_certificate_CertificateChoicesFieldTag ); x509cert = (ASN_CMS_Certificate*)cert->data; /* look in certificate extensions for OCTET STRING */ if( x509cert->tbsCertificate.extensions->n == 0 ) { SMIME_TRACE("cert_match_for_subjectKeyIdentifier: no extensions"); return FALSE; } for( i=0; itbsCertificate.extensions->n; i++ ) { if( OIDCMP( &x509cert->tbsCertificate.extensions->elt[i]->extnID, ASN_CMS_id_ce_subjectKeyIdentifier_OID )==0 ) break; } if( i == x509cert->tbsCertificate.extensions->n ) { SMIME_TRACE("cert_match_for_subjectKeyIdentifier: no SubjectKeyIdentifier extension"); return FALSE; } SMIME_TRACE1("cert_match_for_subjectKeyIdentifier: match found at extension #%d", i); if( x509cert->tbsCertificate.extensions->elt[i]->extnValue.len != subjectKeyIdentifier->len ) { SMIME_TRACE2("cert_match_for_subjectKeyIdentifier: length of SubjectKeyIdentifier extension don't match: %d vs %d", x509cert->tbsCertificate.extensions->elt[i]->extnValue.len, subjectKeyIdentifier->len); return FALSE; } return memcmp( x509cert->tbsCertificate.extensions->elt[i]->extnValue.val, subjectKeyIdentifier->val, subjectKeyIdentifier->len )==0; } /* signer is sequencial number of the signer * returns signer index or -1 of the signer is not in the certificate set */ int asnGetSignerCertIndex( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_SignerIdentifier *sid; (void)c; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; sid = &signerInfo->sid; /* sid can be IssuerAndSerialNUmber or SubjectKeyIdentifier */ if( ASN_TAG(sid->CHOICE_field_type) != (ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag) && ASN_TAG(sid->CHOICE_field_type) != (ASN_CMS_subjectKeyIdentifier_SignerIdentifierFieldTag) ) { SMIME_TRACE3( "SignerIdentifier represented by unknown type %02x, allowed types are %02x %02x", ASN_TAG(sid->CHOICE_field_type), ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag, ASN_CMS_subjectKeyIdentifier_SignerIdentifierFieldTag ); return -1; // return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } if( signedData->certificates==NULL || signedData->certificates->n == 0 ) { SMIME_TRACE("No certificates specified in SignerInfo" ); return -1; //return SMIMEError_BadParam + SMIME_ERROR_CATEGORY_NOT_IMPL /*don't know where to get them...*/ | // SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } if( ASN_TAG(sid->CHOICE_field_type) == ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag ) { ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber = (ASN_CMS_IssuerAndSerialNumber*)sid->data; int i; for( i=0; icertificates->n; i++ ) { if( cert_match_with_IssuerAndSerialNumber( signedData->certificates->elt[i], issuerAndSerialNumber ) ) break; } if( i < signedData->certificates->n ) { SMIME_TRACE2("Found signer certificate index %d in a range [0..%d]; used IssuerAndSerialNumber", i, signedData->certificates->n-1); return i; } } else { ASN_CMS_SubjectKeyIdentifier *subjectKeyIdentifier = (ASN_CMS_SubjectKeyIdentifier*)sid->data; int i; for( i=0; icertificates->n; i++ ) { if( cert_match_with_SubjectKeyIdentifier( signedData->certificates->elt[i], subjectKeyIdentifier ) ) break; } if( i < signedData->certificates->n ) { SMIME_TRACE2("Found signer certificate index %d in a range [0..%d]; used SubjectKeyIdentifier", i, signedData->certificates->n); return i; } } return -1; } /* certificate is an index in the SignerInfo certificate set * Caller must call FreeP(x509cert) */ SMIMEError asnGetCert( SMIME_CONTEXT *c, int certificate, ASN_CMS_SignedData *signedData, P *x509cert ) { P cert = {NULL, 0, TRUE}; SMIMEError ret = SMIMEError_Unknown | SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING; pgpAssert( signedData ); x509cert->p = NULL; x509cert->l = 0; if( signedData->certificates==NULL || signedData->certificates->n == 0 ) { SMIME_TRACE1("No certificates specified in SignedData, but certificate %d asked", certificate ); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_NOT_IMPL /*don't know where to get them...*/ | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } if( certificate >= signedData->certificates->n ) { SMIME_TRACE2("Certificate %d is out of range [0..%d]", certificate, signedData->certificates->n-1 ); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_NOT_IMPL /*don't know where to get them...*/ | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } ret = export_x509cert( c, signedData->certificates->elt[certificate], &cert ); if( ret == 0 ) { *x509cert = cert; return 0; } return ret; } /* check consistency of content-type signed attribute */ static SMIMEError checkContentTypeMatch( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, PGPBoolean *ok ) { ASN_CMS_SignerInfo *signerInfo; int n_signedAttrs; ASN_CMS_OBJECT_ID *oidContentType; int i; int err; *ok = FALSE; pgpAssert( signedData && signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; /* check that contentType in signed attributes matches one in the SignerInfo */ if( signerInfo->signedAttrs==NULL ) { SMIME_TRACE("Unfortunately, optional signed attributes are not present"); *ok = TRUE; return 0; } /* Now content-type must be present */ n_signedAttrs = signerInfo->signedAttrs->n; SMIME_TRACE1("Looking for id-contentType among %d SignedAttributes", n_signedAttrs); /* look for id-messagegeDigest */ for( i=0; isignedAttrs->elt[i]->attrType, ASN_CMS_id_contentType_OID )==0 ) break; } if( i==n_signedAttrs ) { /* if the set is non-empty, the content-type must be present */ SMIME_TRACE1("Could not find mandatory id-contentType in a set of %d signedAttributes", n_signedAttrs); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } SMIME_TRACE2("Found id-contentType as attribute #%d for signer %d", i, signer); if( signerInfo->signedAttrs->elt[i]->attrValues.n != 1 ) { SMIME_TRACE1("Found contentType as attribute #%d, but the attrValues set has %d elements", signerInfo->signedAttrs->elt[i]->attrValues.n ); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } ASN_CMS_UnpackOBJECT_ID( c->asnc, &oidContentType, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->val, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->len, &err ); if( err != 0 || oidContentType==NULL ) { SMIME_TRACE ( "Failed to parse DER OID" ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } if( oidcmp( &signedData->encapContentInfo.eContentType, oidContentType->val, oidContentType->len )!=0 ) { SMIME_TRACE1("Mismatch for signer %d between content-type stored in SignedAttributes and SignedData", signer); ASN_CMS_FreeOBJECT_ID( c->asnc, oidContentType ); return 0; /* no unpacking errors */ } /* this is not required, but we know that we only have id-data, so check it */ if( OIDCMP( oidContentType, ASN_CMS_id_data_OID )!=0 ) { SMIME_TRACE1("Signed attribute and SignedData have other content type then id-data for signer %d", signer); ASN_CMS_FreeOBJECT_ID( c->asnc, oidContentType ); return 0; /* no unpacking errors */ } ASN_CMS_FreeOBJECT_ID( c->asnc, oidContentType ); SMIME_TRACE1("Signer %d has signed content-type attribute matching one in SignedData", signer); *ok = TRUE; return 0; } /* get signer's signing time (optional signed attribute) */ SMIMEError asnGetSignerSigningTime( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, PGPTime *utctime ) { ASN_CMS_SignerInfo *signerInfo; int n_signedAttrs; ASN_CMS_SigningTime *signingTime; int i; time_t unixtime; int err; SMIMEError asnerr; *utctime = 0; pgpAssert( signedData && signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; /* check that contentType in signed attributes matches one in the SignerInfo */ if( signerInfo->signedAttrs==NULL ) { SMIME_TRACE("Optional signed attributes are not present"); return 0; } n_signedAttrs = signerInfo->signedAttrs->n; SMIME_TRACE1("Looking for id-signingTime among %d SignedAttributes", n_signedAttrs); for( i=0; isignedAttrs->elt[i]->attrType, ASN_CMS_id_signingTime_OID )==0 ) break; } if( i==n_signedAttrs ) { SMIME_TRACE1("Could not find optional id-signingTime in a set of %d signedAttributes", n_signedAttrs); return 0; } SMIME_TRACE2("Found id-signingTime as atrribute #%d for signer %d", i, signer); if( signerInfo->signedAttrs->elt[i]->attrValues.n != 1 ) { SMIME_TRACE1("Found id-signingTime as attribute #%d, but the attrValues set has %d elements", signerInfo->signedAttrs->elt[i]->attrValues.n ); return SMIMEError_BadParam | SMIME_ERROR_CATEGORY_LOGICAL_ERROR | SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING; } ASN_CMS_UnpackSigningTime( c->asnc, &signingTime, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->val, signerInfo->signedAttrs->elt[i]->attrValues.elt[0]->len, &err ); if( err != 0 || signingTime==NULL ) { SMIME_TRACE ( "Failed to parse DER SigningTime" ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } asnerr = gettime( signingTime, &unixtime ); ASN_CMS_FreeSigningTime( c->asnc, signingTime ); if( asnerr ) { SMIME_TRACE1("Failed to parse signingTime, err=%d", asnerr); return asnerr + (SMIME_ERROR_DATA_TYPE_SIGNING | SMIME_ERROR_ENCODING_DECODING); } #if PGP_USE_TRACE { PGPByte s[128]; PGPByte *p; time_t stdtime = PGPGetStdTimeFromPGPTime( (PGPTime)unixtime ); sprintf( s, "Converted signingTime to local time: %s", ctime( &stdtime ) ); do { p = strchr( s, '\n' ); if( p ) *p = ' '; } while(p); SMIME_TRACE(s); } #endif *utctime = (PGPTime)unixtime; return 0; } SMIMEError asnCheckSignerAttrs( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, PGPBoolean *ok ) { PGPBoolean ok1; SMIMEError err; *ok = FALSE; err = checkContentTypeMatch( c, signer, signedData, &ok1 ); if( err ) return err; if( !ok1 ) return 0; // err = checkSigningTime( c, signer, signedData, &ok1 ); // if( err ) // return err; // if( !ok1 ) // return 0; // later *ok = TRUE; return 0; } /* extract sender's preferences from signed attributes */ static SMIMEError getSignerCapabilities( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedAttributes *signedAttrs, PGPCipherAlgorithm algs[256], int *nalgs ) { SMIMEError smimeerr=0; int n_signedAttrs; int i; int asnerr=0; P capabilities_der; ASN_CMS_SMIMECapabilities *capabilities; int mynalgs=0; (void)signer; /* here for logging purpose only */ *nalgs = 0; if( signedAttrs==NULL ) { pgpAssert( 0 ); return SMIMEError_BadParam; } n_signedAttrs = signedAttrs->n; SMIME_TRACE1("Looking for smimeCapabilities among %d SignedAttributes", n_signedAttrs); for( i=0; ielt[i]->attrType, ASN_CMS_smimeCapabilities_OID )==0 ) break; } if( i==n_signedAttrs ) { SMIME_TRACE1("Could not find optional smimeCapabilities in a set of %d signedAttributes", n_signedAttrs); return 0; } SMIME_TRACE2("Found smimeCapabilities as signed attribute #%d for signer %d", i, signer); if( signedAttrs->elt[i]->attrValues.n != 1 ) { /* violates SMIME v3 */ SMIME_TRACE1("smimeCapabilities object is stored as set of %d attributes", signedAttrs->elt[i]->attrValues.n); return SMIMEError_InconsistentData + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } capabilities_der.p = signedAttrs->elt[i]->attrValues.elt[0]->val; capabilities_der.l = (PGPUInt)signedAttrs->elt[i]->attrValues.elt[0]->len; /* let the signature fail for > 2^32 */ capabilities_der.dontFree = TRUE; ASN_CMS_UnpackSMIMECapabilities( c->asnc, &capabilities, capabilities_der.p, capabilities_der.l, &asnerr ); SMIME_TRACE1( "ASN_CMS_UnpackSMIMECapabilities returned %d", asnerr ); if( asnerr ) return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); SMIME_TRACE1( "%d SMIMECapabilities present in signed attrs", capabilities->n ); /* go over capabilities, currently we are interested only in encr algs */ for( i=0; in; i++ ) { ASN_CMS_SMIMECapability *capability; capability = capabilities->elt[i]; if( OIDCMP( &capability->capabilityID, ASN_CMS_des_ede3_cbc_OID )==0 ) { algs[mynalgs++] = kPGPCipherAlgorithm_3DES; } else if( OIDCMP( &capability->capabilityID, ASN_CMS_id_aes128_CBC_OID )==0 ) { algs[mynalgs++] = kPGPCipherAlgorithm_AES128; } else if( OIDCMP( &capability->capabilityID, ASN_CMS_id_aes192_CBC_OID )==0 ) { algs[mynalgs++] = kPGPCipherAlgorithm_AES192; } else if( OIDCMP( &capability->capabilityID, ASN_CMS_id_aes256_CBC_OID )==0 ) { algs[mynalgs++] = kPGPCipherAlgorithm_AES256; } #if PGP_USE_TRACE else { SMIME_TRACE1( "Unrecognized SMIME capability at position %d", i ); } #endif if( mynalgs >= 255 ) { SMIME_TRACE1( "Too many encryption algoritms among %d SMIME capabilities", capabilities->n ); smimeerr = SMIMEError_InconsistentData + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); break; } /* TODO: check that capability->parameters is NULL */ } ASN_CMS_FreeSMIMECapabilities( c->asnc, capabilities ); if( smimeerr ) return smimeerr; *nalgs = mynalgs; return 0; } /* extract sender's preferences from signed data */ SMIMEError asnGetSignerCaps( SMIME_CONTEXT *c, int signer, ASN_CMS_SignedData *signedData, PGPCipherAlgorithm algs[256], int *nalgs ) { ASN_CMS_SignerInfo *signerInfo; *nalgs = 0; pgpAssert( signedData && signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; if( signerInfo->signedAttrs==NULL ) { SMIME_TRACE("Optional signed attributes are not present"); return 0; } return getSignerCapabilities( c, signer, signerInfo->signedAttrs, algs, nalgs ); } /* extract sender's preferences from signed data */ SMIMEError asnGetCapsFromSignedAttrs( SMIME_CONTEXT *c, const P *signedAttrs_der, PGPCipherAlgorithm algs[256], int *nalgs ) { ASN_CMS_SignedAttributes *signedAttrs; int asnerr=0; SMIMEError smimeerr; *nalgs = 0; ASN_CMS_UnpackSignedAttributes( c->asnc, &signedAttrs, signedAttrs_der->p, signedAttrs_der->l, &asnerr); if( asnerr!=0 ) { SMIME_TRACE5( "Failed to unpack signed attributes [%d] %02x %02x %02x ..., asnerr=%d\n", signedAttrs_der->l, signedAttrs_der->p[0], signedAttrs_der->p[1], signedAttrs_der->p[2], asnerr ); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } smimeerr = getSignerCapabilities( c, -1, signedAttrs, algs, nalgs ); ASN_CMS_FreeSignedAttributes( c->asnc, signedAttrs ); return smimeerr; } SMIMEError asnProcessSigned(SMIME_CONTEXT *smime, const P *der) { ASN_CMS_ContentInfo *ci; ASN_CMS_SignedData *signedData; int version; int asnerr=0; if( der->l < 128 ) { SMIME_TRACE1("Input size for SMIME body is too small (%d)", der->l); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } ASN_CMS_UnpackContentInfo( smime->asnc, &ci, der->p, der->l, &asnerr ); SMIME_TRACE1( "ASN_CMS_UnpackContentInfo returned %d", asnerr ); if( asnerr ) return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); /* ContentInfo has ANY DEFINED BY 'content' that parser treats as ANY; * now manually direct the parser */ if( OIDCMP( &ci->contentType, ASN_CMS_id_signedData_OID )!=0 ) { SMIME_TRACE( "Given SMIME block is not id-signedData type" ); ASN_CMS_FreeContentInfo( smime->asnc, ci ); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING); } SMIME_TRACE("ContentType is id-signedData"); ASN_CMS_UnpackSignedData( smime->asnc, &signedData, ci->content.val, ci->content.len, &asnerr ); /* Don't need content info anymore */ ASN_CMS_FreeContentInfo( smime->asnc, ci ); SMIME_TRACE("Freed contentInfo, keep signedData"); if( asnerr ) { SMIME_TRACE2( "UnpackSignedData returned %d %s", asnerr, asn1comp_err(asnerr) ); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } version = ASN_CMS_GetIntVal( smime->asnc, &signedData->version, &asnerr ); if( asnerr ) { SMIME_TRACE1("Cannot get version number for SignedData, asnerr=%d", asnerr); ASN_CMS_FreeSignedData( smime->asnc, signedData ); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } if( OIDCMP( &signedData->encapContentInfo.eContentType, ASN_CMS_id_data_OID )!=0 ) { SMIME_TRACE("EncapsulatedContentInfo.eContentType in SignedData is not id-data. Don't know how to work with this content"); ASN_CMS_FreeSignedData( smime->asnc, signedData ); return ASNErrorToSMIMEError( asnerr, SMIME_ERROR_CATEGORY_NOT_IMPL|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_DECODING ); } SMIME_TRACE1("Unpacked signedData OK of version %d, eContentType in EncapsulatedContentInfo is id-data", version); if( smime->signedData ) { SMIME_TRACE1("Had old signedData %p in the context, clean it", smime->signedData); ASN_CMS_FreeSignedData( smime->asnc, smime->signedData ); } smime->signedData = signedData; SMIME_TRACE1("Added signedData %p to the context", smime->signedData); return 0; } #if 0 /*debug*/ int process_smime( PGPContextRef sdkcontext, const P *der ) { ASN_CMS_ContentInfo *ci; ASN_CMS_SignedData *signedData; ASN_CMS_EnvelopedData *envelopedData; int err=0; SMIME_CONTEXT c; asnInitSMIMEContext( sdkcontext, &c ); // /* allocate skeleton */ // ci = ASN_CMS_NewContentInfo( c ); // if( ci == NULL ) // return -1; ASN_CMS_UnpackContentInfo( c.asnc, &ci, der->p, der->l, &err ); SMIME_TRACE1( "\nUnpackContentInfo returned %d", err ); if( err != 0 ) { return err; } SMIME_TRACE1("content of ContentInfo is %d bytes", ci->content.len); /* ContentInfo has ANY DEFINED BY 'content' that parser treats as ANY; * now manually direct the parser */ if( OIDCMP( &ci->contentType, ASN_CMS_id_signedData_OID )==0 ) { int signers; int i; PGPHashAlgorithm hashType; SMIME_TRACE("ContentType is signedData"); ASN_CMS_UnpackSignedData( c.asnc, &signedData, ci->content.val, ci->content.len, &err ); SMIME_TRACE2( "\nUnpackSignedData returned %d %s", err, asn1comp_err(err) ); signers = asnGetNumberOfSigners(signedData); SMIME_TRACE1("%d signers", signers); printf("Total %d certs\n", n_certs); n_certs = asnGetNumberOfCerts( &c, signedData ); for( i=0; imemMgr, cert.p ); err = asnGetSignerSignature( &c, i, signedData, &sig ); printf("asnGetSignerSignature returned size=%d bits\n", sig.l*8); if( !err && sig.l ) { for( j=0; jmemMgr, sig.p ); err = asnGetSignedAttrs( &c, i, signedData, &attrs ); if( !err ) { for( j=0; jcontentType, ASN_CMS_id_envelopedData_OID )==0 ) { printf("ContentType is envelopedData\n"); ASN_CMS_UnpackEnvelopedData( c.asnc, &envelopedData, ci->content.val, ci->content.len, &err ); printf( "\nUnpackEnvelopedData returned %d %s\n", err, asn1comp_err(err) ); ASN_CMS_FreeEnvelopedData( c.asnc, envelopedData); } else { printf("Unknown ContentType\n"); } ASN_CMS_FreeContentInfo( c.asnc, ci ); return 0; } #endif /*__Editor_settings____ Local Variables: tab-width: 4 End: vi: ts=4 sw=4 vim: si _____________________*/ ӵmA r\!n4 H1D CdG-{/kvİJ&4K.8ʬg/*Auvmmzw;`_OJ`A@/^/DE&\X.S%E|$*e5m@ &yʷƝuHdy$tvn! |SUc'U$fǨ>qms=Y;a6%BTr*0TwK(xXȬ?fŀ9gn2W3R/aq2YS()Í_m"5PAbg$~uKIr>^sG‚DVX0ff*8U{CvTi뗃X3ZڭfCk\1)ǽ^o2oQ-$ \ S|6#+TOްZmK ݫFc.jTKnULjfŃ{a"rOjdu N1ʭ D @7HR\dFA&bOn&ewgv -b[]T*hd?2OۥK`!T.-9*WBQ G2cުet(Dm(I g] F"i{ڈv|T-e o(.i/%yjgeR* %c҆8Ir) Tڌ^7%)D9̢Z4۬(Ka $ z^lÁpf.{Gpi&3>^#u5zktlܳ'ZR0G{c2F3fﱎ$LH 'Kr<Ÿ!u숷l[(;0OJ+ٶ 3,w0jIpZ/*____________________________________________________________________________ * Copyright (C) 2003 PGP Corporation * All rights reserved. * * This file provides lowest-level interface to ASN.1 routines needed for * signature generation in SMIME. * * $Id: pgpSMIMEasnSign.c,v 1.4 2003/10/14 02:18:39 ajivsov Exp $ ____________________________________________________________________________*/ #include "pgpASN_CMS.h" #include "pgpASN_CMS_asn.h" #include "pgpASN_CMS_oid.h" #include "pgpASN_CMS_util.h" #include "pgpASN_SMIME.h" #include "pgpASN_SMIME_asn.h" #include "pgpASN_SMIME_oid.h" /* ----- SDK includes ----- */ #include "pgpUtilities.h" #include "pgpPublicKey.h" #include "pgpMem.h" #include "pgpKeys.h" #include "pgpEncode.h" #include "string.h" #include "pgpErrors.h" #include "pgpStrings.h" #include "pgpHashPriv.h" /* ----- end of SDK includes ----- */ #include "pgpSMIME.h" #include "pgpSMIMEPriv.h" static SMIMEError getoidDER( SMIME_CONTEXT *c, const unsigned char *oid, size_t len, P *derout ) { ASN_CMS_OBJECT_ID *objectID; PGPByte *p; size_t size; int err; derout->p = NULL; derout->l = 0; objectID = ASN_CMS_NewOBJECT_ID( c->asnc ); if( oid==NULL ) return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES); objectID->val = (void*)oid; objectID->len = len; size = ASN_CMS_SizeofOBJECT_ID( c->asnc, objectID, TRUE/*outerSizeFlag*/ ); p = ASN_CMS_Alloc( c->asnc->memMgr, size ); if( p==NULL ) { ASN_CMS_FreeOBJECT_ID( c->asnc, objectID ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES); } err=0; /* urgly surprise: must do this for compiler */ ASN_CMS_PackOBJECT_ID( c->asnc, p, size, objectID, &err ); objectID->val = NULL; /* this object doesn't own oid */ objectID->len = 0; ASN_CMS_FreeOBJECT_ID( c->asnc, objectID ); if( err ) { SMIME_TRACE1("Error %d packing %d bytes oid", len); ASN_CMS_Free( c->asnc->memMgr, p ); return err + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES); } derout->p = p; derout->l = size; derout->dontFree = FALSE; SMIME_TRACE5( "Exported object ID: [%d] %02x %02x %02x %02x", size, p[0],p[1],p[2],p[3] ); return 0; } SMIMEError asnCreateSigned(SMIME_CONTEXT *smime, int signers, int certificates) { ASN_CMS_SignedData *signedData; SMIME_TRACE1("Building top level SignedData for %d signers", signers); signedData = ASN_CMS_NewSignedData(smime->asnc); if( signedData==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } ASN_CMS_PutIntVal( smime->asnc, &signedData->version, 1 ); signedData->signerInfos.n = signers; signedData->signerInfos.elt = ASN_CMS_Alloc( smime->asnc->memMgr, signers * sizeof(ASN_CMS_SignerInfo*) ); if( signedData->signerInfos.elt==NULL ) { signedData->signerInfos.n = 0; ASN_CMS_FreeSignedData( smime->asnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( signedData->signerInfos.elt, 0, signers * sizeof(ASN_CMS_SignerInfo*) ); { ASN_CMS_EncapsulatedContentInfo *encapContentInfo = &signedData->encapContentInfo; SETOID( smime, ASN_CMS_id_data_OID, &encapContentInfo->eContentType ); encapContentInfo->eContent = NULL; /* multipart/signed */ SMIME_TRACE("Done setting empty encapContentInfo for multipart/signed or encapsulated"); } /* encapContentInfo */ { ASN_CMS_CertificateSet *certs = ASN_CMS_NewCertificateSet(smime->asnc); if( !certs ) { ASN_CMS_FreeSignedData( smime->asnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } certs->n = certificates; certs->elt = ASN_CMS_Alloc( smime->asnc->memMgr, sizeof(ASN_CMS_CertificateChoices*)*certificates ); if( certs->elt==NULL ) { ASN_CMS_FreeCertificateSet( smime->asnc, certs ); ASN_CMS_FreeSignedData( smime->asnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( certs->elt, 0, sizeof(ASN_CMS_CertificateChoices*)*certificates ); signedData->certificates = certs; } /* certificates pointers */ /* it is safe to free signerData now */ /* ----- Set up content ----- */ { int i; for( i=0; iasnc ); int err; if( signerInfo==NULL ) break; ASN_CMS_PutIntVal( smime->asnc, &signerInfo->version, 1 ); signedData->signerInfos.elt[i] = signerInfo; /* construct signer attributes structures with mandatory attributes at * fixed positions */ { ASN_CMS_SignedAttributes *signedAttrs = ASN_CMS_NewSignedAttributes(smime->asnc); ASN_CMS_Attribute *attr; #define attributes 4 /* for [0] id-messageDigest, [1] is content-type, [2] is id-SigningTime, [3] is smimeCapabilities */ const P oids[attributes] = { { ASN_CMS_id_messageDigest_OID, ASN_CMS_id_messageDigest_OID_LEN, TRUE }, /* content is OCTET STRING */ { ASN_CMS_id_contentType_OID, ASN_CMS_id_contentType_OID_LEN, TRUE }, /* content is OID */ { ASN_CMS_id_signingTime_OID, ASN_CMS_id_signingTime_OID_LEN, TRUE }, /* content is SigningTime */ { ASN_CMS_smimeCapabilities_OID, ASN_CMS_smimeCapabilities_OID_LEN, TRUE } /* content is SMIMECapabilities */ /* TODO: smimeCapabilites should be here */ }; int i_attr; /* construct a content of SignerAttributes */ signedAttrs->n = attributes; signedAttrs->elt = ASN_CMS_Alloc(smime->asnc->memMgr, sizeof(ASN_CMS_Attribute*) * attributes); if( signedAttrs->elt==NULL ) { ASN_CMS_FreeSignedAttributes( smime->asnc, signedAttrs ); break; } memset( signedAttrs->elt, 0, sizeof(ASN_CMS_Attribute*) * attributes ); for( i_attr=0; i_attrasnc); if( attr==NULL ) break; /* construct attrValues which is a set of 1 AttributeValue (which is ANY) */ err = setoid( smime, oids[i_attr].p, oids[i_attr].l, &attr->attrType ); if( err ) break; attr->attrValues.n = 1; attr->attrValues.elt = ASN_CMS_Alloc( smime->asnc->memMgr, sizeof(ASN_CMS_AttributeValue*)*1 ); if( attr->attrValues.elt==NULL ) { ASN_CMS_FreeAttribute( smime->asnc, attr ); break; } attr->attrValues.elt[0] = ASN_CMS_NewAttributeValue(smime->asnc); /* this is ANY in ASN.1 */ if( attr->attrValues.elt[0]==NULL ) { ASN_CMS_FreeAttribute( smime->asnc, attr ); break; } signedAttrs->elt[i_attr] = attr; } if( i_attrasnc, signedAttrs ); break; } /* Now set attribute [1] to the constant value */ { P oid; err = getoidDER( smime, ASN_CMS_id_data_OID, ASN_CMS_id_data_OID_LEN, &oid ); if( err ) { SMIME_TRACE1("Error %d creating DER OID", err); ASN_CMS_FreeSignedAttributes( smime->asnc, signedAttrs ); break; } signedAttrs->elt[1]->attrValues.elt[0]->val = oid.p; signedAttrs->elt[1]->attrValues.elt[0]->len = oid.l; /* transfered the memory from oid to attribute [1] */ } signerInfo->signedAttrs = signedAttrs; /* finally attach signed attributes set */ #undef attributes } /* signedAttrs */ } if( iasnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Done setting %d SignerInfos", signers); } /* signerInfos */ { int i; for( i=0; icertificates->elt[i] = ASN_CMS_NewCertificateChoices( smime->asnc ))==NULL ) break; } if( iasnc, signedData ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } SMIME_TRACE1("Done setting %d CertificateChoices", certificates); } /* certificates */ if( smime->signedData ) { SMIME_TRACE1("Had old signedData %p in the context, clean it", smime->signedData); ASN_CMS_FreeSignedData( smime->asnc, smime->signedData ); } smime->signedData = signedData; SMIME_TRACE1("Added signedData %p to the context", smime->signedData); return 0; } SMIMEError asnSetSignedContent( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, const P* eContent ) { ASN_CMS_OCTET_STRING *octetStr; octetStr = ASN_CMS_NewOCTET_STRING( smime->asnc ); if( octetStr==NULL ) return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); octetStr->val = ASN_CMS_Alloc( smime->asnc->memMgr, eContent->l ); if( octetStr->val==NULL ) { SMIME_TRACE1("Failed to allocate %d bytes for the eContent", eContent->l); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } octetStr->len = eContent->l; memcpy( octetStr->val, eContent->p, eContent->l ); if( signedData->encapContentInfo.eContent!=NULL) { SMIME_TRACE1("Had eContent size [%d], freed it", signedData->encapContentInfo.eContent->len); ASN_CMS_FreeOCTET_STRING( smime->asnc, signedData->encapContentInfo.eContent ); } signedData->encapContentInfo.eContent = octetStr; SMIME_TRACE4( "Set eContent to [%d] %02x %02x %02x", octetStr->len, octetStr->val[0], octetStr->val[1], octetStr->val[2] ); return 0; } /* Sets digestAlgorithms field in SignedData * hashAlg is kPGPHashAlgorithm_Invalid-terminated string of hash algoritms, the length is up to signers. * We use the fact that hash algorithm value is less then 256 */ SMIMEError asnSetHashAlgorithms( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, const PGPHashAlgorithm hashAlgs[] ) { PGPHashAlgorithm hashHits[256]; PGPHashAlgorithm maxHash=0; int uniqueHashAlgs=0; int hashIndex=0; int i; ASN_CMS_DigestAlgorithmIdentifiers myDigestAlgorithms; const int signers = signedData->signerInfos.n; SMIMEError err=0; memset(&myDigestAlgorithms, 0, sizeof(myDigestAlgorithms)); if( signers <= 0 ) { SMIME_TRACE("No signers. Number of signerts must be set first"); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( hashHits, 0, sizeof(hashHits) ); for( i=0; i < signers && hashAlgs[i] != kPGPHashAlgorithm_Invalid; i++ ) { pgpAssert( hashAlgs[i] < 256 ); if( hashAlgs[i] > maxHash ) maxHash = hashAlgs[i]; hashHits[ hashAlgs[i] ] ++; } for( i=0; i<=(int)maxHash; i++ ) if( hashHits[i] ) uniqueHashAlgs++; SMIME_TRACE2( "%d unique hash algorithms specified, largest is %d", uniqueHashAlgs, maxHash ); myDigestAlgorithms.n = uniqueHashAlgs; myDigestAlgorithms.elt = ASN_CMS_Alloc( smime->asnc->memMgr, uniqueHashAlgs * sizeof(ASN_CMS_DigestAlgorithmIdentifier*) ); if( myDigestAlgorithms.elt==NULL ) { myDigestAlgorithms.n = 0; return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } memset( myDigestAlgorithms.elt, 0, uniqueHashAlgs * sizeof(ASN_CMS_DigestAlgorithmIdentifier*) ); /* Now add uniqueHashAlgs AlgorithmIdentifier SEQUENCE { OID }. AlgorithmIdentifier has optional parameters field which * is empty for any hash algorithm we support */ for( i=0; i<=(int)maxHash; i++ ) { if( hashHits[i] ) { ASN_CMS_DigestAlgorithmIdentifier *algorithm = ASN_CMS_NewDigestAlgorithmIdentifier( smime->asnc ); if( algorithm==NULL ) { err = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); break; } switch( i ) { case kPGPHashAlgorithm_SHA: SMIME_TRACE("processing SHA-1 algorithm for SignedData"); err = SETOID( smime, ASN_CMS_sha_1_OID, &algorithm->algorithm ); break; #if 0 case kPGPHashAlgorithm_SHA256; case kPGPHashAlgorithm_SHA384; case kPGPHashAlgorithm_SHA512; /* future algorithms */ break; case kPGPHashAlgorithm_MD5: SMIME_TRACE("processing MD5 algorithm for SignedData"); err = SETOID( smime, ASN_CMS_md5_OID, &algorithm->algorithm ); break; #endif default: SMIME_TRACE1("Asked to use unsupported hash algorithm %d", i); err = SMIMEError_UnsupportedHash | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( err ) { SMIME_TRACE1("Error %d while creating hash algorithm object", err); ASN_CMS_FreeDigestAlgorithmIdentifier( smime->asnc, algorithm ); break; } /* Set DER NULL object */ algorithm->parameters = ASN_CMS_NewANY(smime->asnc); if( algorithm->parameters==NULL ) { SMIME_TRACE("No memory for ANY object"); ASN_CMS_FreeDigestAlgorithmIdentifier( smime->asnc, algorithm ); err = SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); break; } /* now ANY attached to algorithm's parameters */ err = setnull( smime, algorithm->parameters); if( err ) { SMIME_TRACE("No memory for NULL object"); ASN_CMS_FreeDigestAlgorithmIdentifier( smime->asnc, algorithm ); err |= (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); break; } SMIME_TRACE1("Attaching hash algorithm object at index %d", hashIndex); myDigestAlgorithms.elt[hashIndex++] = algorithm; } } if( err ) { ASN_CMS_DropInPlaceDigestAlgorithmIdentifiers( smime->asnc, &myDigestAlgorithms ); return err; } if( signedData->digestAlgorithms.n > 0 ) { SMIME_TRACE1("Had %d hash algorithms advertized. Clean them first", signedData->digestAlgorithms.n); pgpAssert( signedData->digestAlgorithms.elt ); ASN_CMS_DropInPlaceDigestAlgorithmIdentifiers( smime->asnc, &signedData->digestAlgorithms ); } signedData->digestAlgorithms = myDigestAlgorithms; /* transfer pointers */ SMIME_TRACE1("Done setting %d message digest algorithms", uniqueHashAlgs); #if PGP_DEBUG { PGPHashAlgorithm hashAlgs[100]; int n; asnGetHashAlgs( smime, signedData, hashAlgs, &n ); SMIME_TRACE1("Found %d hash algorithm right after I set them", n); } #endif return 0; } /* will leak memory if called twice for same signer and signedData */ SMIMEError asnSetSignerHashAlg( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, PGPHashAlgorithm hashAlg ) { SMIMEError err=0; ASN_CMS_DigestAlgorithmIdentifier myDigestAlgorithm; ASN_CMS_DigestAlgorithmIdentifier *digestAlgorithm; memset(&myDigestAlgorithm, 0, sizeof(myDigestAlgorithm)); pgpAssert( signer < signedData->signerInfos.n ); digestAlgorithm = &signedData->signerInfos.elt[signer]->digestAlgorithm; pgpAssert(digestAlgorithm); /* create DER ANY object for parameters */ myDigestAlgorithm.parameters = ASN_CMS_NewANY(smime->asnc); if( myDigestAlgorithm.parameters==NULL ) { SMIME_TRACE("No memory for ANY object"); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* now setup a content */ switch( hashAlg ) { case kPGPHashAlgorithm_SHA: err = SETOID( smime, ASN_CMS_sha_1_OID, &myDigestAlgorithm.algorithm ); break; #if 0 case kPGPHashAlgorithm_SHA256; case kPGPHashAlgorithm_SHA384; case kPGPHashAlgorithm_SHA512; /* future algorithms */ break; case kPGPHashAlgorithm_MD5: SETOID( smime, ASN_CMS_md5_OID, &myDigestAlgorithm.algorithm ); break; #endif default: SMIME_TRACE2("Asked to use unsupported hash algorithm %d for signer %d", hashAlg, signer); err = SMIMEError_UnsupportedHash | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( err ) { SMIME_TRACE1("Error during DigestAlgorithmIdentifier construction for signer %d", signer ); ASN_CMS_DropInPlaceDigestAlgorithmIdentifier( smime->asnc, &myDigestAlgorithm ); return err + (SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err = setnull( smime, myDigestAlgorithm.parameters); if( err ) { SMIME_TRACE("No memory for NULL object"); ASN_CMS_DropInPlaceDigestAlgorithmIdentifier( smime->asnc, &myDigestAlgorithm ); return err + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } #if PGP_USE_TRACE if( digestAlgorithm->parameters != NULL ) SMIME_TRACE1("Had DigestAlgorithmIdentifier for signer %d. Clean it", signer); #endif ASN_CMS_DropInPlaceDigestAlgorithmIdentifier( smime->asnc, digestAlgorithm ); *digestAlgorithm = myDigestAlgorithm; SMIME_TRACE2("Set hash algorithm %d for signer %d", hashAlg, signer); return 0; } /* signer hash is part of signed attributes at the position [0] */ SMIMEError asnSetSignerMsgHash( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const P *hash ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_Attribute *msgDigestAttr; ASN_CMS_OCTET_STRING *octetStr; P hash_der; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE5("Setting message digest [%d] %02x %02x %02x for signer %d", hash->l, hash->p[0], hash->p[1], hash->p[2], signer ); pgpAssert(signerInfo->signedAttrs->n > 0); /* id-messageDigest must be at [0] */ msgDigestAttr = signerInfo->signedAttrs->elt[0]; pgpAssert( OIDCMP( &msgDigestAttr->attrType, ASN_CMS_id_messageDigest_OID )==0 ); pgpAssert( msgDigestAttr->attrValues.n==1 && msgDigestAttr->attrValues.elt[0]!=NULL ); /* Set content. attrValues is a set of one element: DER OCTET STRING */ octetStr = ASN_CMS_NewOCTET_STRING( smime->asnc ); if( octetStr==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err = ASN_CMS_PutOctVal( smime->asnc, octetStr, hash->p, hash->l ); if( err ) { ASN_CMS_FreeOCTET_STRING( smime->asnc, octetStr ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } hash_der.l = ASN_CMS_SizeofOCTET_STRING( smime->asnc, octetStr, TRUE/*outerSizeFlag*/ ); hash_der.p = ASN_CMS_Alloc( smime->asnc->memMgr, hash_der.l ); hash_der.dontFree = FALSE; if( hash_der.p==NULL ) { ASN_CMS_FreeOCTET_STRING( smime->asnc, octetStr ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err=0; /* must do this for compiler */ ASN_CMS_PackOCTET_STRING( smime->asnc, hash_der.p, hash_der.l, octetStr, &err ); ASN_CMS_FreeOCTET_STRING( smime->asnc, octetStr ); if( err ) { pgpSMIMEFreePtr( &hash_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* initialize ANY with DER of hash */ pgpAssert( msgDigestAttr->attrValues.n==1 ); if( msgDigestAttr->attrValues.elt[0]->val != NULL ) { SMIME_TRACE1("Had message hash for signer %d, clean it", signer); ASN_CMS_Free( smime->asnc->memMgr, msgDigestAttr->attrValues.elt[0]->val ); } msgDigestAttr->attrValues.elt[0]->val = hash_der.p; msgDigestAttr->attrValues.elt[0]->len = hash_der.l; return 0; } SMIMEError asnSetSigner( SMIME_CONTEXT *smime, int certificate, ASN_CMS_SignedData *signedData, const P *x509cert ) { ASN_CMS_CertificateChoices *certificateChoices; ASN_CMS_Certificate *cert; int err; pgpAssert( signedData->certificates && certificate < signedData->certificates->n ); certificateChoices = signedData->certificates->elt[certificate]; pgpAssert(certificateChoices); SMIME_TRACE2("Setting certificate %d, one of [0..%d]", certificate, signedData->certificates->n-1); /* we use only X.509 cert */ certificateChoices->CHOICE_field_type = ASN_CMS_certificate_CertificateChoicesFieldTag; ASN_CMS_UnpackCertificate( smime->asnc, &cert, x509cert->p, x509cert->l, &err ); if( err ) { SMIME_TRACE1("Error unpacking X509 certificate %d", certificate); return ASNErrorToSMIMEError( err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING ); } /* attach certificate to the signedData */ certificateChoices->data = cert; return 0; } /* Set signing time as 'time'. This functions can be exported if more control over signing time is required */ static SMIMEError setSignerSigningTime( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, PGPTime time ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_Attribute *signingTimeAttr; ASN_CMS_SigningTime *signingTime; P signingTime_der; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; /* id-signingTime must be at [2] */ signingTimeAttr = signerInfo->signedAttrs->elt[2]; pgpAssert( OIDCMP( &signingTimeAttr->attrType, ASN_CMS_id_signingTime_OID )==0 ); pgpAssert( signingTimeAttr->attrValues.n==1 && signingTimeAttr->attrValues.elt[0]!=NULL ); /* Set the content. attrValues is a set of one element: DER SigningTime */ signingTime = ASN_CMS_NewSigningTime( smime->asnc ); if( signingTime==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err = settime( smime, time, signingTime ); if( err ) { SMIME_TRACE1("Failed to initialize SigningTime with current time, err=%d", err); ASN_CMS_FreeSigningTime( smime->asnc, signingTime ); return err + (SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } signingTime_der.l = ASN_CMS_SizeofSigningTime( smime->asnc, signingTime, TRUE/*outerSizeFlag*/ ); signingTime_der.p = ASN_CMS_Alloc( smime->asnc->memMgr, signingTime_der.l ); signingTime_der.dontFree = FALSE; if( signingTime_der.p==NULL ) { ASN_CMS_FreeSigningTime( smime->asnc, signingTime ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err=0; /* must do this for ASN.1 compiler */ ASN_CMS_PackSigningTime( smime->asnc, signingTime_der.p, signingTime_der.l, signingTime, &err ); ASN_CMS_FreeSigningTime( smime->asnc, signingTime ); if( err ) { pgpSMIMEFreePtr( &signingTime_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* initialize ANY with DER of SigningTime */ SMIME_TRACE1("Attaching signing time for signer %d", signer); pgpAssert( signingTimeAttr->attrValues.n==1 ); if( signingTimeAttr->attrValues.elt[0]->val!=NULL ) { SMIME_TRACE1("Had signing time attribute for signer %d, clean it", signer); ASN_CMS_Free( smime->asnc->memMgr, signingTimeAttr->attrValues.elt[0]->val ); } signingTimeAttr->attrValues.elt[0]->val = signingTime_der.p; signingTimeAttr->attrValues.elt[0]->len = signingTime_der.l; SMIME_TRACE5("Set up date as DER [%d] %02x %02x %02x %02x", signingTime_der.l, signingTime_der.p[0], signingTime_der.p[1], signingTime_der.p[2], signingTime_der.p[3] ); return 0; } /* Set same signing time for all signers */ SMIMEError asnSetSigningTime( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData ) { const int signers = signedData->signerInfos.n; const PGPTime time = PGPGetTime(); int signer; SMIMEError smimeerr = kPGPError_NoErr; /* to make the compiler happy */ if( signers == 0 ) { SMIME_TRACE("No signers, cannot set signing time"); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } for( signer=0; signer < signers; signer++ ) { smimeerr = setSignerSigningTime( smime, signer, signedData, time ); if( smimeerr ) break; } return smimeerr; } SMIMEError asnSetSignerSignature( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const P *sig ) { ASN_CMS_SignerInfo *signerInfo; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE5( "Setting signature [%d] %02x %02x %02x %02x", sig->l, sig->p[0], sig->p[1], sig->p[2], sig->p[3] ); err = ASN_CMS_PutOctVal( smime->asnc, &signerInfo->signature, sig->p, sig->l ); if( err ) { return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } return 0; } SMIMEError asnSetSignerSignatureAlg( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, PGPPublicKeyAlgorithm sigAlg ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_SignatureAlgorithmIdentifier mySignatureAlgorithm; SMIMEError err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; memset( &mySignatureAlgorithm, 0, sizeof(mySignatureAlgorithm) ); if( sigAlg==kPGPPublicKeyAlgorithm_RSA ) { err = SETOID( smime, ASN_CMS_rsaEncryption_OID, &mySignatureAlgorithm.algorithm ); SMIME_TRACE("Setting SignatureAlgorithmIdentifier to rsaEncryption"); } else if( sigAlg==kPGPPublicKeyAlgorithm_DSA ) { err = SETOID( smime, ASN_CMS_id_dsa_with_sha1_OID, &mySignatureAlgorithm.algorithm ); SMIME_TRACE("Setting SignatureAlgorithmIdentifier to id-dsa-with-sha1"); } else { SMIME_TRACE2("Unsupported public key algorithm %d for signing for signer %d", sigAlg, signer); pgpAssert(0); return SMIMEError_UnsupportedPubAlg + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( err ) { SMIME_TRACE1("Error setting OID for the SignatureAlgorithmIdentifier for signer %d", signer); return err; } /* Set DER NULL object */ mySignatureAlgorithm.parameters = ASN_CMS_NewANY(smime->asnc); if( mySignatureAlgorithm.parameters==NULL ) { SMIME_TRACE("No memory for ANY object"); ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier( smime->asnc, &mySignatureAlgorithm ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* now ANY attached to SignatureAlgorithm's parameters; set parameters to NULL */ err = setnull( smime, mySignatureAlgorithm.parameters ); if( err ) { SMIME_TRACE1("Error setting parameters to NULL for the SignatureAlgorithmIdentifier for signer %d", signer); ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier( smime->asnc, &mySignatureAlgorithm ); return err; } #if PGP_USE_TRACE if( signerInfo->signatureAlgorithm.parameters != NULL ) SMIME_TRACE1("Had SignatureAlgorithm for signer %d, clean it", signer); #endif ASN_CMS_DropInPlaceSignatureAlgorithmIdentifier( smime->asnc, &signerInfo->signatureAlgorithm ); signerInfo->signatureAlgorithm = mySignatureAlgorithm; /* transfer pointers */ return 0; } /* Set signer certificate */ SMIMEError asnSetSignerCert( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const P *x509cert ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_IssuerAndSerialNumber *issuerAndSerialNumber; ASN_CMS_IssuerAndSerialNumber myIssuerAndSerialNumber; ASN_CMS_Certificate *certificate; size_t size; PGPByte *p; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE( "Setting signer certificate" ); /* First parse certificate */ ASN_CMS_UnpackCertificate( smime->asnc, &certificate, x509cert->p, x509cert->l, &err ); if( err ) { SMIME_TRACE1("Failed to unpack certificate [%d]", x509cert->l); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING ); } /* Now make IssuerAndSerialNumber by pointing to fields from Certificate. This must be done carefully as IssuerAndSerialNUmber * will not own these fields (Certificate is the owner) */ memset( &myIssuerAndSerialNumber, 0, sizeof(myIssuerAndSerialNumber) ); myIssuerAndSerialNumber.issuer = certificate->tbsCertificate.issuer; myIssuerAndSerialNumber.serialNumber = certificate->tbsCertificate.serialNumber; size = ASN_CMS_SizeofIssuerAndSerialNumber( smime->asnc, &myIssuerAndSerialNumber, TRUE/*outerSizeFlag*/ ); p = ASN_CMS_Alloc( smime->asnc->memMgr, size ); if( p==NULL ) { ASN_CMS_FreeCertificate( smime->asnc, certificate ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* store */ ASN_CMS_PackIssuerAndSerialNumber( smime->asnc, p, size, &myIssuerAndSerialNumber, &err ); ASN_CMS_FreeCertificate( smime->asnc, certificate ); /* also done with myIssuerAndSerialNumber, forget it */ if( err ) { SMIME_TRACE1("Error packing issuer and serial number, expected length %d bytes", size); ASN_CMS_Free( smime->asnc->memMgr, p ); return ASNErrorToSMIMEError(err, SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING ); } /* restore */ ASN_CMS_UnpackIssuerAndSerialNumber( smime->asnc, &issuerAndSerialNumber, p, size, &err ); ASN_CMS_Free( smime->asnc->memMgr, p ); if( err ) { return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* attach IssuerAndSerialNumber to SignerIdentifier */ if( signerInfo->sid.data ) { if( ASN_TAG(signerInfo->sid.CHOICE_field_type) == ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag ) { SMIME_TRACE1("Had id data of type IssuerAndSerialNumber for signer %d, clean it", signer); ASN_CMS_FreeIssuerAndSerialNumber( smime->asnc, signerInfo->sid.data ); } else { SMIME_TRACE1("Had id data of type IssuerAndSerialNumber for signer %d, must not happen, leaking memory here", signer); pgpAssert(0); } } signerInfo->sid.CHOICE_field_type = ASN_CMS_issuerAndSerialNumber_SignerIdentifierFieldTag; signerInfo->sid.data = issuerAndSerialNumber; SMIME_TRACE("Set mandatory SignerIdentifier attribute for SignerInfo"); return 0; } /* Set capabilities for the signer (similiar to PGP key preferences) * Currently set encryption algorithms * * SMIMECapabilities is signed attribute [3] * * Most symbols here should have CMS_SMIME prefix instead of ASN_CMS, but compiler doesn't allow this * for the module that has IMPORT * */ SMIMEError asnSetSignerCaps( SMIME_CONTEXT *smime, int signer, ASN_CMS_SignedData *signedData, const PGPCipherAlgorithm *algs, int nalgs ) { ASN_CMS_SignerInfo *signerInfo; ASN_CMS_Attribute *SMIMECapabilitiesAttr; ASN_CMS_SMIMECapabilities *capabilities; P capabilities_der; int i; SMIMEError smimeerr; int err; pgpAssert( signer < signedData->signerInfos.n ); signerInfo = signedData->signerInfos.elt[signer]; SMIME_TRACE( "Setting signer capabilities" ); /* smimeCapabilities must be at [3] */ SMIMECapabilitiesAttr = signerInfo->signedAttrs->elt[3]; pgpAssert( OIDCMP( &SMIMECapabilitiesAttr->attrType, ASN_CMS_smimeCapabilities_OID )==0 ); pgpAssert( SMIMECapabilitiesAttr->attrValues.n==1 && SMIMECapabilitiesAttr->attrValues.elt[0]!=NULL ); /* Set the content. attrValues is a set of one element: DER SMIMECapabilities */ capabilities = ASN_CMS_NewSMIMECapabilities( smime->asnc ); if( capabilities==NULL ) { return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* initialize a SET of nalgs SMIMECapability attributes */ capabilities->n = nalgs; capabilities->elt = ASN_CMS_Alloc( smime->asnc->memMgr, nalgs * sizeof(ASN_CMS_SMIMECapability*) ); if( capabilities->elt==NULL ) { capabilities->n = 0; ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } for( i=0; ielt[i] = ASN_CMS_NewSMIMECapability( smime->asnc ); if( capabilities->elt[i]==NULL ) break; } if( iasnc, capabilities ); return SMIMEError_NoMem + (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } /* set capability [0] to algs[0], ... */ for( i=0; ielt[i]->capabilityID ); break; case kPGPCipherAlgorithm_AES128: smimeerr = SETOID( smime, ASN_CMS_id_aes128_CBC_OID, &capabilities->elt[i]->capabilityID ); break; case kPGPCipherAlgorithm_AES192: smimeerr = SETOID( smime, ASN_CMS_id_aes192_CBC_OID, &capabilities->elt[i]->capabilityID ); break; case kPGPCipherAlgorithm_AES256: smimeerr = SETOID( smime, ASN_CMS_id_aes256_CBC_OID, &capabilities->elt[i]->capabilityID ); break; default: smimeerr = SMIMEError_UnsupportedEncrAlg; break; } if( smimeerr ) { SMIME_TRACE2("Failed to set capability #%d for cipher %d", i, algs[i]); ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); return smimeerr | (SMIME_ERROR_CATEGORY_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } } /* export the set into capabilities_der */ capabilities_der.l = ASN_CMS_SizeofSMIMECapabilities( smime->asnc, capabilities, TRUE/*outerSizeFlag*/ ); capabilities_der.p = ASN_CMS_Alloc( smime->asnc->memMgr, capabilities_der.l ); capabilities_der.dontFree = FALSE; if( capabilities_der.p==NULL ) { ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } err=0; /* must do this for ASN.1 compiler */ ASN_CMS_PackSMIMECapabilities( smime->asnc, capabilities_der.p, capabilities_der.l, capabilities, &err ); ASN_CMS_FreeSMIMECapabilities( smime->asnc, capabilities ); if( err ) { pgpSMIMEFreePtr( &capabilities_der ); return SMIMEError_NoMem | (SMIME_ERROR_CATEGORY_CRITICAL|SMIME_ERROR_TYPE_RESOURCES|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } if( SMIMECapabilitiesAttr->attrValues.elt[0]->val!=NULL ) { SMIME_TRACE1("Had SMIMECapabilities attribute for signer %d, clean it", signer); ASN_CMS_Free( smime->asnc->memMgr, SMIMECapabilitiesAttr->attrValues.elt[0]->val ); } SMIMECapabilitiesAttr->attrValues.elt[0]->val = capabilities_der.p; SMIMECapabilitiesAttr->attrValues.elt[0]->len = capabilities_der.l; SMIME_TRACE5("Set up SMIMECapabilitiesAttr as DER [%d] %02x %02x %02x %02x", capabilities_der.l, capabilities_der.p[0], capabilities_der.p[1], capabilities_der.p[2], capabilities_der.p[3] ); return 0; } /* Set same capabilities for all signers */ SMIMEError asnSetCaps( SMIME_CONTEXT *smime, ASN_CMS_SignedData *signedData, const PGPCipherAlgorithm *algs, int nalgs ) { const int signers = signedData->signerInfos.n; int signer; SMIMEError smimeerr = kPGPError_NoErr; /* to make the compiler happy */ if( signers == 0 ) { SMIME_TRACE("No signers, cannot set capabilities"); return SMIMEError_BadParam + (SMIME_ERROR_CATEGORY_LOGICAL_ERROR|SMIME_ERROR_DATA_TYPE_SIGNING|SMIME_ERROR_ENCODING_ENCODING); } for( signer=0; signer < signers; signer++ ) { smimeerr = asnSetSignerCaps( smime, signer, signedData