iaik.cms
Class AuthEnvelopedDataStream

java.lang.Object
  extended by iaik.cms.AuthEnvelopedDataStream
All Implemented Interfaces:
EncodeListener, ContentStream, EOFListener, java.util.EventListener
Direct Known Subclasses:
AuthEnvelopedData, SMimeAuthEncrypted

public class AuthEnvelopedDataStream
extends java.lang.Object
implements ContentStream, EncodeListener, EOFListener

This class represents the stream-supporting implementation of the CMS content type AuthEnvelopedData as defined in RFC 5083.

The AuthEnvelopedData content type is identified by the following object identifier (see RFC 5083):

 id-ct-authEnvelopedData OBJECT IDENTIFIER ::= { iso(1)
      member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-9(9)
      smime(16) ct(1) 23 }
 
which corresponds to the OID string "1.2.840.113549.1.9.16.1.23".

RFC 5083 specifies the AuthEnvelopedData content type for use with authenticated cipher modes like AES-CCM or AES-GCM (RFC 5084). RFC 8103 specifies the AuthEnvelopedData content type for use with the ChaCha20-Poly1305 authenticated encryption algorithm (RFC 7539).
Using authenticated encryption the data is not only encrypted but also integrity protected by a message authentication code. Similar to the EnvelopedData and AuthenticatedData types content of any type may be authenticated enveloped for any number of recipients in parallel. For each recipient, a commonly at random generated content-authenticated-encryption key is encrypted with the particular recipient key and - together with recipient-specific information - collected into a RecipientInfo value. Using a authenticated encryption method the content is authenticated and encrypted with the content-authenticated-encryption key. All RecipientInfo values are collected together with the authenticated encrypted content into an AuthEnvelopedData object to be sent to each intended recipients. The AuthEnvelopedData may also contain authenticated attributes (which are authenticated but not encrypted) and unauthenticated attributes (which are neither encrypted nor authenticated), (see RFC 5083:

 AuthEnvelopedData ::= SEQUENCE {
      version CMSVersion,
      originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
      recipientInfos RecipientInfos,
      authEncryptedContentInfo EncryptedContentInfo,
      authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
      mac MessageAuthenticationCode,
      unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }

 
The recipientInfos field is a non-empty collection of per-recipient information. The authEncryptedContentInfo field specifies the type of the content being authenticated encrypted, the content-authenticated-encryption algorithm (the same for all recipients) used for authenticated encrypting the content, and the result of the content authenticated encryption.
CMS provides five alternatives for authenticated encrypting the content depending on the key management algorithm used to protect the content-authenticated-encryption key for a specific recipient: The optional originatorInfo field may be used to include certificate/crl information about the originator if required by the key management protocol. The unauthAttrs field may contain some attributes that are authenticated but not encrypted, the unauthAttrs may provide some attributes that are not protected.

A recipient, when receiving the AuthEnvelopedData message, decrypts the corresponding encrypted content-authenticated-encryption key with his/her key according the right key management protocol for subsequently decrypting the encrypted content and verifying the mac value using the content-authenticated-encryption key just recovered. The recipient key is referenced by proper KeyIdentifier included in the corresponding RecipientInfo object.

See RFC 5652 for more information.


When creating a new AuthEnvelopedDataStream object for the data to be authenticated enveloped the symmetric algorithm has to be specified to be used for content-authenticated-encryption. After setting the recipients, the AuthEnvelopedDataStream object may be encoded and written to an output stream by using a proper writeTo method, e.g.:

  1. Create a new AuthEnvelopedDataStream object and specify the content authenticated encryption algorithm to be used by means of the AuthEnvelopedDataStream(InputStream is, AlgorithmID contentAuthEncAlg) constructor. When using this constructor automatically a temporary symmetric key for authenticated content encryption will be generated. If you want to use a content-authenticated-encryption algorithm allowing keys of different size, you may specify the key length by using the AuthEnvelopedDataStream(InputStream is, AlgorithmID contentAuthEncAlg, int keyLength) constructor.
         //the data to be auth-enveloped supplied from an input stream:
         InputStream dataStream = ...;
         //use AES-GCM mode for authenticated encrypting the content
         AuthEnvelopedDataStream authEnvelopedData = new AuthEnvelopedDataStream(dataStream, (AlgorithmID)AlgorithmID.aes256_GCM.clone());
         
  2. For each intended recipient, create a RecipientInfo object of requested type (KeyTransRecipientInfo, KeyAgreeRecipientInfo, or KEKRecipientInfo), and add all RecipientInfos to the AuthEnvelopedDataStream object by calling the setRecipientInfos method, e.g. (assuming to use KeyTransRecipientInfos for two recipients with corresponding certificates cert1 and cert2):
         RecipientInfo[] recipients = new RecipientInfo[2];
         recipients[0] = new KeyTransRecipientInfo(cert1, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
         recipients[1] = new KeyTransRecipientInfo(cert2, (AlgorithmID)AlgorithmID.rsaEncryption.clone());
         authEnvelopedData.setRecipientInfos(recipients);
         
  3. Use a proper writeTo method for BER encoding the AuthEnvelopedData object and writing it to an output stream. You optionally may specify a particular block size for splitting the encoding of encrypted content. This step also will perform generation and encryption of the symmetric content-authenticated-encryption key for each participated recipient.
         int blockSize = ...;
         OutputStream encodedStream = ...;
         authEnvelopedData.writeTo(encoded_stream, blockSize);
         
    respectively
         authEnvelopedData.writeTo(encodedStream);
         
A recipient, when receiving an AuthEnvelopedData encoding, uses the AuthEnvelopedDataStream(InputStream is) constructor for parsing the internal structure. Before reading the recovered content by means of the getInputStream method, the cipher has to be initialized for decryption and mac verification with the particular recipient key by calling one of the following setupCipher methods: Since in our example both recipients use a RecipientInfo of type KeyTransRecipientInfo, we can use any of the setupCipher methods to setup the cipher for decrypting the encrypted content-authenticated-encryption key, decrypting the encrypted content and verifying the message authenitication code:
  1. Create an AuthEnvelopedDataStream structure from the supplied encoding, decode and parse the internal structure:
         InputStream encodedStream = ...;
         AuthEnvelopedDataStream authEnvelopedData = new AuthEnvelopedDataStream(encodedStream);
         
  2. Get information about the inherent EncryptedContentInfo:
         EncryptedContentInfoStream eci = (EncryptedContentInfoStream)authEnvelopedData.getEncryptedContentInfo();
         System.out.println("Content type: "+eci.getContentType().getName());
         System.out.println("content authenticated encryption algorithm: "+eci.getContentEncryptionAlgorithm().getName());
         
  3. Get information about the included RecipientInfos:
         RecipientInfo[] recipients = authEnvelopedData.getRecipientInfos();
         System.out.println("Included RecipientInfos:");
         for (int i=0; i < recipients.length; i++) {
            System.out.print("Recipient "+(i+1)+":");
            System.out.println(recipients[i]);
         }
         
  4. Use some recipient specific key to decrypt the inherent encrypted secret key to be used for initializing the cipher for encrypted-content decryption and mac verification:
         // the private key of recipient 1:
         Key privateKey = ...;
         //setup cipher for recipient 1:
         int recipientInfoIndex = 0;
         authEnvelopedData.setupCipher(privateKey, recipientInfoIndex);
         
    Unlike the non-stream supporting AuthEnvelopedData class where the encrypted-content decryption already is performed inside the setupCipher method, the cipher will be only initialized for decryption in this class. The encrypted-content decryption actually is done during reading the data obtained by calling the getInputStream method. So do not call getInputStream before setting up the cipher!

  5. Get and read the recovered content:
         InputStream dataIs = authEnvelopedData.getInputStream();
         byte[] buf = new byte[2048];
         int r;
         while ((r = dataIs.read(buf)) > 0) {
            // do something useful
         }
         

Note: RFC 5084 specifies the usage of the AuthEnvelopedData type for the AES-CCM and AES-GCM authenticated encryption algorithms, both are supported by this implementation when used with IAIK-JCE, version > 3.17.
RFC 8103 specifies the AuthEnvelopedData content type for use with the ChaCha20-Poly1305 authenticated encryption algorithm (RFC 7539). ChaCha20-Poly1305 for CMS requires IAIK-JCE version 5.62 or later.
Unfortunately the structure of the AuthEnvelopedData type does not allow one-pass processing when parsing an AuthEnvelopedData object that uses AES-CCM or AES-GCM or ChaCha20-Poly1305 for authenticated content encryption since they require to know the additional authenticated data (authenticated attributes) before processing the content data. However, the authAttrs field is located behind the authEncryptedContentInfo field. Thus the content must be read before having access to the authenticated attributes which are needed as additional authenticated data input the AEAD Cipher. For that reason a non-stream EncryptedContentInfo is used by this AuthenticatedDataStream implementation for parsing the encrypted content of AuthEnvelopedData objects that have AES-CCM, AES-GCM or ChaCha20Poly1305 as content-authenticated encryption algorithm.
AES-CCM furthermore needs to know the size of the to-be-auth-encrypted content in advance when creating an AuthEnvelopedData object. If you know to data input length (e.g. the size of a data file) you may set it by calling method setInputLength, otherwise tha data has to be internally buffered before starting the authentication-encryption process.

Note: This class does not provide a verifyMac method. For authenticated encryption modes like CCM and GCM Mac verification is part of the decryption/verification procedure. When using some other content authentication encryption method that follows a different verification strategy, be sure to implement corresponding authentication cipher engines.

See Also:
RecipientInfo, KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo, PasswordRecipientInfo, OtherRecipientInfo

Field Summary
protected  EncryptedContentInfoStream encryptedContentInfo_
          The EncryptedContentInfo for the encrypted content.
static int EXPLICIT
          Denotes a mode where the authenticated encrypted message is not transported within the AuthEnvelopedData (EncryptedContentInfo).
static int IMPLICIT
          Denotes a mode where the authenticated encrypted message is included in the AuthEnvelopedData (EncryptedContentInfo).
 
Constructor Summary
protected AuthEnvelopedDataStream()
          Default constructor for dynamic object creation in ContentInfoStream.
  AuthEnvelopedDataStream(java.io.InputStream is)
          Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream.
  AuthEnvelopedDataStream(java.io.InputStream is, AlgorithmID contentAuthEncAlg)
          Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.
  AuthEnvelopedDataStream(java.io.InputStream is, AlgorithmID contentAuthEncAlg, int keyLength)
          Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.
  AuthEnvelopedDataStream(java.io.InputStream is, byte[] encodedAuthAttributes, long inputLength)
          Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream.
  AuthEnvelopedDataStream(java.io.InputStream is, byte[] encodedAuthAttributes, long inputLength, SecurityProvider securityProvider)
          Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream.
  AuthEnvelopedDataStream(java.io.InputStream is, SecurityProvider securityProvider)
          Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream.
  AuthEnvelopedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID contentAuthEncAlg)
          Creates a new AuthEnvelopedDataStream object to be authenticated enveloped is read from the supplied InputStream.
  AuthEnvelopedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID contentAuthEncAlg, int keyLength)
          Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.
  AuthEnvelopedDataStream(ObjectID contentType, java.io.InputStream is, AlgorithmID contentAuthEncAlg, int keyLength, SecurityProvider securityProvider)
          Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.
  AuthEnvelopedDataStream(RecipientInfo[] recipients, EncryptedContentInfoStream encryptedContentInfo)
          Constructs an AuthEnvelopedDataStream object with an already created EncryptedContentInfoStream.
 
Method Summary
 void addRecipientInfo(RecipientInfo recipient)
          Adds one recipient to the list of recipient infos.
 void decode(java.io.InputStream is)
          Reads and decodes an BER encoded AuthEnvelopedData from a the given input stream.
 void decode(java.io.InputStream is, boolean useStream)
          Reads and decodes an BER encoded AuthEnvelopedData from a the given input stream.
 void encodeCalled(ASN1Object obj, int id)
          This method implements the EncodeListener interface.
 Attribute getAuthenticatedAttribute(ObjectID oid)
          Returns the first authenticated attribute matching to the given ObjectID, if included in this AuthEnvelopedData object.
 Attribute[] getAuthenticatedAttributes()
          Gets the authenticated attributes included in this AuthEnvelopedData.
 int getBlockSize()
          Gets the block size defining the length of each definite primitive encoded octet string component.
 ObjectID getContentType()
          Returns the content type this class implements.
 EncryptedContentInfoStream getEncryptedContentInfo()
          Returns the EncryptedContentInfo included in this AuthEnvelopedDataStream object.
 long getInputLength()
          Gets the length of input data.
 java.io.InputStream getInputStream()
          Returns an InputStream from where the decrypted data can be read.
 byte[] getMac()
          Gets the MAC value.
 int getMode()
          Gets the mode of this AuthEnvelopedDataStream.
 OriginatorInfo getOriginatorInfo()
          Gets the OriginatorInfo, if included.
 RecipientInfo getRecipientInfo(KeyIdentifier recipientIdentifier)
          Returns the RecipientInfo belonging to the recipient identified by the given recipient identifier.
 RecipientInfo getRecipientInfo(X509Certificate recipientCertificate)
          Returns the recipient info matching to the supplied recipient certificate.
 RecipientInfo[] getRecipientInfos()
          Returns all the recipient infos included in this AuthEnvelopedData object.
 RecipientInfo[] getRecipientInfos(int type)
          Returns all the recipient infos included in this AuthEnvelopedData object that have the specified type.
 SecurityProvider getSecurityProvider()
          Gets the SecurityProvider installed for this EncryptedDataStream.
 Attribute getUnauthenticatedAttribute(ObjectID oid)
          Returns the first unauthenticated attribute matching to the given ObjectID, if included in this AuthEnvelopedData object.
 Attribute[] getUnauthenticatedAttributes()
          Gets the unauthenticated attributes included in this AuthEnvelopedData.
 int getVersion()
          Returns the syntax version number.
 void notifyEOF()
          This method implements the EOFListener interface for performing the final decoding of the attributes and mac field components.
 void setAuthenticatedAttributes(Attribute[] attributes)
          Sets a set of authenticated attributes.
 void setBlockSize(int blockSize)
          Sets the block size for defining the length of each definite primitive encoded octet string component.
 void setInputLength(long inputLength)
          Sets the length of input data.
 void setInputStream(java.io.InputStream is)
          Sets the input stream that supplies the content data to be authenticated encrypted.
 void setMac(byte[] mac)
          Sets the MAC value (if calculated outside).
 void setMode(int mode)
          Sets the mode for this AuthEnvelopedDataStream.
 void setOriginatorInfo(OriginatorInfo originatorInfo)
          Sets the optional OriginatorInfo.
 void setRecipientInfos(RecipientInfo[] recipients)
          Sets the recipient infos.
 void setSecurityProvider(SecurityProvider securityProvider)
          Sets the SecurityProvider for this AuthEnvelopedDataStream.
 void setUnauthenticatedAttributes(Attribute[] attributes)
          Sets a set of unauthenticated attributes.
 void setupCipher(java.security.Key key)
          Uses the given symmetric key to setup the cipher for decrypting the content and verifying the message authentication code.
 javax.crypto.SecretKey setupCipher(java.security.Key recipientKey, int recipientInfoIndex)
          Uses the specified key for decrypting the content-authenticated-encryption key to setup the cipher for decrypting the encrypted content and verifying the mac of this AuthEnvelopedDataStream object for the requesting recipient, specified by its recipientInfoIndex.
 javax.crypto.SecretKey setupCipher(java.security.Key recipientKey, KeyIdentifier recipientIdentifier)
          Uses the specified key for decrypting the content-authenticated-encryption key to setup the cipher for decrypting the encrypted content and verifying the mac of this AuthEnvelopedDataStream object for the requesting recipient, specified by the given recipient identifier.
 javax.crypto.SecretKey setupCipher(java.security.Key recipientKey, X509Certificate recipientCertificate)
          Uses the specified key for decrypting the content-authenticated-encryption key to setup the cipher for decrypting the encrypted content and verifying the mac of this AuthEnvelopedDataStream object for the requesting recipient, specified by the given recipient certificate.
 ASN1Object toASN1Object()
          Returns this AuthEnvelopedDataStream as ASN1Object.
protected  ASN1Object toASN1Object(int blockSize)
          Returns this AuthEnvelopedData as ASN1Object.
 java.lang.String toString()
          Returns a string giving some information about this AuthEnvelopedData object.
 java.lang.String toString(boolean detailed)
          Returns a string giving some - if requested - detailed information about this AuthEnvelopedData object.
 void writeTo(java.io.OutputStream os)
          Writes this AuthEnvelopedData BER encoded to the supplied output stream.
 void writeTo(java.io.OutputStream os, int blockSize)
          Writes this AuthEnvelopedData BER encoded to the supplied output stream where a constructed OCTET STRING may be used for encoding the content.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

IMPLICIT

public static final int IMPLICIT
Denotes a mode where the authenticated encrypted message is included in the AuthEnvelopedData (EncryptedContentInfo).

See Also:
Constant Field Values

EXPLICIT

public static final int EXPLICIT
Denotes a mode where the authenticated encrypted message is not transported within the AuthEnvelopedData (EncryptedContentInfo).

See Also:
Constant Field Values

encryptedContentInfo_

protected EncryptedContentInfoStream encryptedContentInfo_
The EncryptedContentInfo for the encrypted content.

Constructor Detail

AuthEnvelopedDataStream

protected AuthEnvelopedDataStream()
Default constructor for dynamic object creation in ContentInfoStream. The block size is set to 2048 to enforce indefinite constructed encoding.


AuthEnvelopedDataStream

public AuthEnvelopedDataStream(java.io.InputStream is,
                               AlgorithmID contentAuthEncAlg)
Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.

The content type is set to CMS Data.

When using this constructor, automatically a temporary symmetric key for authenticated content encryption will be generated. If you want to use a content-authenticated-encryption algorithm allowing keys of different size, you may specify the key length by using the AuthEnvelopedDataStream(InputStream is, AlgorithmID contentAuthEncAlg, int keyLength) constructor.
Note that the supplied contentAuthEncAlg AlgorithmID internally is cloned.

Parameters:
is - the InputStream supplying the data to be authenticated enveloped
contentAuthEncAlg - the id of the content-authenticated encryption algorithm

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(ObjectID contentType,
                               java.io.InputStream is,
                               AlgorithmID contentAuthEncAlg)
Creates a new AuthEnvelopedDataStream object to be authenticated enveloped is read from the supplied InputStream.

When using this constructor, automatically a temporary symmetric key for authenticated content encryption will be generated. If you want to use a content-authenticated-encryption algorithm allowing keys of different size, you may specify the key length by using the AuthEnvelopedDataStream(ObjectID contentType, InputStream is, AlgorithmID contentAuthEncAlg, int keyLength) constructor.
Note that the supplied contentAuthEncAlg AlgorithmID internally is cloned.

Parameters:
contentType - the content type of the content to be authenticated enveloped
is - the InputStream containing the data to be authenticated enveloped
contentAuthEncAlg - the id of the content-authenticated encryption algorithm

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(java.io.InputStream is,
                               AlgorithmID contentAuthEncAlg,
                               int keyLength)
Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.
The content type is set to CMS Data.

When using this constructor, automatically a symmetric key for authenticated content encryption will be generated. If the specified content authenticated encryption algorithm supports variable key lengths, a particular key length may be set by means of the keyLength parameter. If no length is specified, the defined default key length will be used. If the algorithm only works with keys of fixed-size length, the keyLength parameter may be set to -1 or the AuthEnvelopedDataStream(InputStream is, AlgorithmID contentAuthEncAlg) constructor may be used.
Note that the supplied contentAuthEncAlg AlgorithmID internally is cloned.

Parameters:
is - the InputStream containing the data to be authenticated enveloped
contentAuthEncAlg - the id of the content-authenticated encryption algorithm
keyLength - the length of the content-authenticated-encryption key to be generated (when using a content-authenticated-encryption algorithm that supports variable key lengths)

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(ObjectID contentType,
                               java.io.InputStream is,
                               AlgorithmID contentAuthEncAlg,
                               int keyLength)
Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.

When using this constructor, automatically a symmetric key for authenticated content encryption is generated. If the specified content authenticated encryption algorithm supports variable key lengths, a particular key length may be set by means of the keyLength parameter. If no length is specified, the defined default key length will be used. If the algorithm only works with keys of fixed-size length, the keyLength parameter may be set to -1 or the AuthEnvelopedDataStream(ObjectID contentType, InputStream is, AlgorithmID contentAuthEncAlg) constructor may be used.
Note that the supplied contentAuthEncAlg AlgorithmID internally is cloned.

Parameters:
contentType - the content type of the content to be authenticated enveloped
is - the InputStream containing the data to be authenticated enveloped
contentAuthEncAlg - the id of the content-authenticated encryption algorithm
keyLength - the length of the content-authenticated-encryption key to be generated (when using a content-authenticated-encryption algorithm that supports variable key lengths)

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(ObjectID contentType,
                               java.io.InputStream is,
                               AlgorithmID contentAuthEncAlg,
                               int keyLength,
                               SecurityProvider securityProvider)
Creates a new AuthEnvelopedDataStream object where the content to be authenticated enveloped is read from the supplied InputStream.

When using this constructor, automatically a symmetric key for authenticated content encryption will be generated. If the specified content authenticated encryption algorithm supports variable key lengths, a particular key length may be set by means of the keyLength parameter. If no length is specified, the defined default key length will be used. If the algorithm only works with keys of fixed-size length, the keyLength parameter may be set to -1 or the AuthEnvelopedDataStream(ObjectID contentType, InputStream is, AlgorithmID contentAuthEncAlg) constructor may be used.
Note that the supplied contentAuthEncAlg AlgorithmID internally is cloned.

Parameters:
contentType - the content type of the content to be authenticated enveloped
is - the InputStream containing the data to be authenticated enveloped
contentAuthEncAlg - the id of the content-authenticated encryption algorithm
keyLength - the length of the content-authenticated-encryption key to be generated (when using a content-authenticated-encryption algorithm that supports variable key lengths)
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(RecipientInfo[] recipients,
                               EncryptedContentInfoStream encryptedContentInfo)
Constructs an AuthEnvelopedDataStream object with an already created EncryptedContentInfoStream.

The given array of RecipientInfo specifies a collection of per-recipient information, and the given EncryptedContentInfoStream is responsible for authenticated content encryption.

Parameters:
recipients - information about the recipients
encryptedContentInfo - the EncryptedContentInfo

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(java.io.InputStream is)
                        throws CMSParsingException,
                               java.io.IOException
Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream. The encoded AuthEnvelopedData may (or may not) be wrapped into a ContentInfo.

Parameters:
is - the InputStream supplying a BER encoded CMS AuthEnvelopedData object
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(java.io.InputStream is,
                               SecurityProvider securityProvider)
                        throws CMSParsingException,
                               java.io.IOException
Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream. The encoded AuthEnvelopedData may (or may not) be wrapped into a ContentInfo.

Parameters:
is - the InputStream supplying a BER encoded CMS AuthEnvelopedData object
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(java.io.InputStream is,
                               byte[] encodedAuthAttributes,
                               long inputLength)
                        throws CMSParsingException,
                               java.io.IOException
Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream. The encoded AuthEnvelopedData may (or may not) be wrapped into a ContentInfo.

AEAD algorithm modes like GCM or CCM need to know the additional authenticated data before processing (decrypting) the encrypted data. However, the authAttrs field of an AuthEnvelopedData lies behind the authEncryptedContentInfo field that holds the encrypted data, (see RFC 5083:

 AuthEnvelopedData ::= SEQUENCE {
      version CMSVersion,
      originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
      recipientInfos RecipientInfos,
      authEncryptedContentInfo EncryptedContentInfo,
      authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
      mac MessageAuthenticationCode,
      unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }

 
For that reason this implementation by default uses a non-stream EncryptedContentInfo to parse whole the encrypted and read the authAttrs field before initializing the Cipher for decryption. However, when no authenticated attributes have been used (or the authenticated attributes are known in advance) the decryption process can be done stream based. For doing so this constructor uses an EncryptedContentInfoStream for parsing the encrypted content. If authenticated attributes have been used, their encoding may be specified.
CCM additionally needs to know the length of the input data before starting the decryption process. When knowing the input length and specifying it when creating the AuthEnvelopedDataStream it can be parsed stream-based, too. Otherwise a non-stream EncryptedContentInfo will be used to read the encrypted data and determining its length before starting the decryption process.

Parameters:
is - the InputStream supplying a BER encoded CMS AuthEnvelopedData object
encodedAuthAttributes - the encoded authenticated attributes (or null if no authenticated attributes have been used)
inputLength - the length of the input data (or -1 if not known)
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object

AuthEnvelopedDataStream

public AuthEnvelopedDataStream(java.io.InputStream is,
                               byte[] encodedAuthAttributes,
                               long inputLength,
                               SecurityProvider securityProvider)
                        throws CMSParsingException,
                               java.io.IOException
Creates a new AuthEnvelopedDataStream from a BER encoded AuthEnvelopedData object which is read from the given InputStream. The encoded AuthEnvelopedData may (or may not) be wrapped into a ContentInfo.

AEAD algorithm modes like GCM or CCM need to know the additional authenticated data before processing (decrypting) the encrypted data. However, the authAttrs field of an AuthEnvelopedData lies behind the authEncryptedContentInfo field that holds the encrypted data, (see RFC 5083:

 AuthEnvelopedData ::= SEQUENCE {
      version CMSVersion,
      originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
      recipientInfos RecipientInfos,
      authEncryptedContentInfo EncryptedContentInfo,
      authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
      mac MessageAuthenticationCode,
      unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }

 
For that reason this implementation by default uses a non-stream EncryptedContentInfo to parse whole the encrypted and read the authAttrs field before initializing the Cipher for decryption. However, when no authenticated attributes have been used (or the authenticated attributes are known in advance) the decryption process can be done stream based. For doing so this constructor uses an EncryptedContentInfoStream for parsing the encrypted content. If authenticated attributes have been used, their encoding may be specified.
CCM additionally needs to know the length of the input data before starting the decryption process. When knowing the input length and specifying it when creating the AuthEnvelopedDataStream it can be parsed stream-based, too. Otherwise a non-stream EncryptedContentInfo will be used to read the encrypted data and determining its length before starting the decryption process.

Parameters:
is - the InputStream supplying a BER encoded CMS AuthEnvelopedData object
encodedAuthAttributes - the encoded authenticated attributes (or null if no authenticated attributes have been used)
inputLength - the length of the input data (or -1 if not known)
securityProvider - the security provider to be used; if null the default system-wide SecurityProvider is used
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object
Method Detail

setSecurityProvider

public void setSecurityProvider(SecurityProvider securityProvider)
Sets the SecurityProvider for this AuthEnvelopedDataStream.

This method allows to explicitly set a SecurityProvider for this AuthEnvelopedDataStream. If no explicit SecurityProvider is set, the default system wide installed SecurityProvider will be used for the required cryptographic operations.

This class uses the following method(s) of the SecurityProvider, which may be overriden by an application, if required:

An application may supply the SecurityProvider immediately when creating an AuthEnvelopedData object. This may be preferable on the parsing side, and also when creating a new AuthEnvelopedData object where the EncryptedContentInfo and the RecipientInfos are have to be created by this class.

Parameters:
securityProvider - the SecurityProvider to be set

getSecurityProvider

public SecurityProvider getSecurityProvider()
Gets the SecurityProvider installed for this EncryptedDataStream.

This class uses the following method(s) of the SecurityProvider, which may be overriden by an application, if required:

If no explicit SecurityProvider has been set for this object, the default system wide installed SecurityProvider will be used for the required cryptographic operations. However, this method will return null if it does not have its own SecurityProvider.

Returns:
the SecurityProvider explicitly installed for this object, or null if this object does not have its own SecurityProvider

setMode

public void setMode(int mode)
Sets the mode for this AuthEnvelopedDataStream.

This method may be only called to set the mode to EXPLICIT for creating a new AuthEnvelopedDataStream in EXPLICIT mode where the authenticated encrypted content shall not be included in the AuthEnvelopedData. In this case the authenticated encrypted content has to be transmitted by other means. This method may not be called in IMPLICIT mode (default) where the authenticated encrypted content is included in the AuthEnvelopedData. This method MUST not be called when parsing an AuthEnvelopedData where the mode is automatically detected and cannot be changed.

Parameters:
mode - the mode, either IMPLICIT (to include the authenticated encrypted content (default) or EXPLICIT to not include it)
Throws:
java.lang.IllegalArgumentException - if the mode is not IMPLICIT or EXPLICIT; or if this method is called when parsing an AuthEnvelopedData

getMode

public int getMode()
Gets the mode of this AuthEnvelopedDataStream.

Returns:
the mode, either IMPLICIT (to include the authenticated encrypted content (default) or EXPLICIT to not include it)

decode

public void decode(java.io.InputStream is)
            throws java.io.IOException,
                   CMSParsingException
Reads and decodes an BER encoded AuthEnvelopedData from a the given input stream. The encoded AuthEnvelopedData may (or may not) be wrapped into a ContentInfo.

Specified by:
decode in interface ContentStream
Parameters:
is - the InputStream holding a BER encoded AuthEnvelopedData object
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object

decode

public void decode(java.io.InputStream is,
                   boolean useStream)
            throws java.io.IOException,
                   CMSParsingException
Reads and decodes an BER encoded AuthEnvelopedData from a the given input stream. The encoded AuthEnvelopedData may (or may not) be wrapped into a ContentInfo.

Parameters:
is - the InputStream holding a BER encoded AuthEnvelopedData object
useStream - whether to try to use EncryptedContentInfoStream
Throws:
java.io.IOException - if an I/O error occurs during reading from the InputStream
CMSParsingException - if an error occurs while parsing the object

getContentType

public ObjectID getContentType()
Returns the content type this class implements.

Use getEncryptedContentInfo().getContentType() for getting the type the authenticated encrypted content represents.

Specified by:
getContentType in interface ContentStream
Returns:
ObjectID.cms_authEnvelopedData

setOriginatorInfo

public void setOriginatorInfo(OriginatorInfo originatorInfo)
Sets the optional OriginatorInfo.

The originatorInfo may be set for including certificates and/or certificate revocation lists for the originator if required by the key management algorithm used.

Parameters:
originatorInfo - the OriginatorInfo to be set

setRecipientInfos

public void setRecipientInfos(RecipientInfo[] recipients)
Sets the recipient infos.

Any RecipientInfo added supplies recipient-specific information used for identifying the key of the recipient to be used for authenticated en/decrypting the content.

Parameters:
recipients - a collection of per-recipient information
See Also:
RecipientInfo, KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo, PasswordRecipientInfo, OtherRecipientInfo

addRecipientInfo

public void addRecipientInfo(RecipientInfo recipient)
Adds one recipient to the list of recipient infos.

Any RecipientInfo added supplies recipient-specific information used for identifying the key of the recipient to be used for authenticated en/decrypting the content.

Parameters:
recipient - the RecipientInfo to be added
See Also:
RecipientInfo, KeyTransRecipientInfo, KeyAgreeRecipientInfo, KEKRecipientInfo, PasswordRecipientInfo, OtherRecipientInfo

setAuthenticatedAttributes

public void setAuthenticatedAttributes(Attribute[] attributes)
Sets a set of authenticated attributes. These attributed will be authenticated only, but not encrypted.

Parameters:
attributes - the authenticated attributes to be set

setUnauthenticatedAttributes

public void setUnauthenticatedAttributes(Attribute[] attributes)
Sets a set of unauthenticated attributes.

Parameters:
attributes - the unauthenticated attributes to be set

setBlockSize

public void setBlockSize(int blockSize)
Sets the block size for defining the length of each definite primitive encoded octet string component. If the value of blockSize is smaller or equal to zero the whole encrypted data is encoded as definite primitive octet string.

Specified by:
setBlockSize in interface ContentStream
Parameters:
blockSize - for defining the encoding scheme and setting the octet string component length, if positive

getBlockSize

public int getBlockSize()
Gets the block size defining the length of each definite primitive encoded octet string component. If the value of blockSize is smaller or equal to zero the whole data is encoded as definite primitive octet string.

Specified by:
getBlockSize in interface ContentStream
Returns:
the block size defining the encoding scheme and setting the octet string component length, if positive

setupCipher

public javax.crypto.SecretKey setupCipher(java.security.Key recipientKey,
                                          int recipientInfoIndex)
                                   throws CMSException,
                                          java.security.NoSuchAlgorithmException,
                                          java.security.InvalidKeyException
Uses the specified key for decrypting the content-authenticated-encryption key to setup the cipher for decrypting the encrypted content and verifying the mac of this AuthEnvelopedDataStream object for the requesting recipient, specified by its recipientInfoIndex.

This method has to be called before reading the decrypted content. method. So do not call method getInputStream before setting up the cipher!

Note that you have to know the right index into the recipientInfos field when using this method for setting up the cipher for decryption. You may search for the index by using one of the getRecipientInfo methods thereby identifying the recipient by its keyIdentifier or -- if suitable for the key management algorithm used -- certificate.
However, when having some recipient using a key agreement protocol the corresponding RecipientInfo is of type KeyAgreeRecipientInfo which may hold encrypted content-authenticated-encryption keys for more than only one recipients using the same key agreement algorithm with same domain parameters. Since this setupCipher method only can get the KeyAgreeRecipientInfo with the given index (but not search for the right recipient in the KeyAgreeRecipientInfo), it will step through any recipient included in the KeyAgreeRecipientInfo trying to decrypt the encrypted content-authenticated-encryption key with the supplied key. This may give some overhead and it might be more appropriate to use another setupCipher method allowing to immediately identify the particular recipient in mind by its #setupCipher(Key, KeyIdentifier) keyIdentifier} or certificate.

Parameters:
recipientKey - the key of the recipient to be used for decrypting the encrypted content-authenticated-encryption key.
recipientInfoIndex - the index into the recipientInfos field
Returns:
the (decrypted) secret content authenticated encryption key
Throws:
CMSException - if there occurs an error while decrypting the content-authenticated-encryption key or setting up the cipher for decrypting the content
java.security.NoSuchAlgorithmException - if there is no implementation of the content-authenticated-encryption algorithm
java.security.InvalidKeyException - if the specified key is not valid

setupCipher

public javax.crypto.SecretKey setupCipher(java.security.Key recipientKey,
                                          KeyIdentifier recipientIdentifier)
                                   throws CMSException,
                                          java.security.NoSuchAlgorithmException,
                                          java.security.InvalidKeyException
Uses the specified key for decrypting the content-authenticated-encryption key to setup the cipher for decrypting the encrypted content and verifying the mac of this AuthEnvelopedDataStream object for the requesting recipient, specified by the given recipient identifier.

This method has to be called before reading the decrypted content. method. So do not call method getInputStream before setting up the cipher!

This setupCipher can be used to setup the cipher for decryption for any type of RecipientInfo. The supplied recipient identifier will be used for searching for the right RecipientInfo in the recipientInfos field.

Parameters:
recipientKey - the key of the recipient to be used for decrypting the encrypted content-authenticated-encryption key.
recipientIdentifier - specifies which RecipientInfo the given key belongs to
Returns:
the (decrypted) secret content authenticated encryption key
Throws:
CMSException - if there occurs an error while decrypting the content-authenticated-encryption key or setting up the cipher for decrypting the content, or no RecipientInfo for the requested recipient is included
java.security.NoSuchAlgorithmException - if there is no implementation of the content-authenticated-encryption algorithm
java.security.InvalidKeyException - if the specified key is not valid

setupCipher

public javax.crypto.SecretKey setupCipher(java.security.Key recipientKey,
                                          X509Certificate recipientCertificate)
                                   throws CMSException,
                                          java.security.NoSuchAlgorithmException,
                                          java.security.InvalidKeyException
Uses the specified key for decrypting the content-authenticated-encryption key to setup the cipher for decrypting the encrypted content and verifying the mac of this AuthEnvelopedDataStream object for the requesting recipient, specified by the given recipient certificate.

This method has to be called before reading the decrypted content. method. So do not call method getInputStream before setting up the cipher!

Note that this method only can be used for decrypting the encrypted content if the recipient in mind has a RecipientInfo of type KeyTransRecipientInfo or KeyAgreeRecipientInfo using a public key from a certificate for its key management protocol.

Parameters:
recipientKey - the private key of the recipient to be used for decrypting the encrypted content-authenticated-encryption key.
recipientCertificate - the certificate of the recipient specifying which RecipientInfo the recipient private key belongs to
Returns:
the (decrypted) secret content authenticated encryption key
Throws:
CMSException - if there occurs an error while decrypting the content-authenticated-encryption key or setting up the cipher for decrypting the content, or no RecipientInfo for the requested recipient is included
java.security.NoSuchAlgorithmException - if there is no implementation of the content-authenticated-encryption algorithm
java.security.InvalidKeyException - if the specified private key is not valid

setupCipher

public void setupCipher(java.security.Key key)
                 throws CMSException,
                        java.security.NoSuchAlgorithmException,
                        java.security.InvalidKeyException
Uses the given symmetric key to setup the cipher for decrypting the content and verifying the message authentication code.

The secret key supplied to this method has to be the already decrypted content authenticated encryption key.

This method has to be called before reading the decrypted content. method. So do not call method getInputStream before setting up the cipher!

Parameters:
key - the temporary symmetric key that has been used to encrypt the content, and now is used for decrypting it again
Throws:
CMSException - if there occurs an error while setting up the cipher for decrypting the content
java.security.NoSuchAlgorithmException - if there is no implementation for the content-authenticated-encryption algorithm
java.security.InvalidKeyException - if the specified key is not valid

getInputStream

public java.io.InputStream getInputStream()
Returns an InputStream from where the decrypted data can be read.

Attention! The stream only may be read once.

When having created a new AuthEnvelopedDataStream object to be encoded to a stream, this method should not be called at all, since the stream automatically will be read during performing the encoding (which is done when calling a writeTo method).
When having decoded and parsed a received AuthEnvelopedDataStream object comimg from some stream, this method may be used for obtaining the raw (decrypted) data after having setup the cipher for decrypting the content and verifying the mac.

Returns:
an InputStream for reading the decrypted data

setInputStream

public void setInputStream(java.io.InputStream is)
Sets the input stream that supplies the content data to be authenticated encrypted.

Parameters:
is - the input stream holding the content data to authenticated and encrypt

setInputLength

public void setInputLength(long inputLength)
                    throws java.lang.IllegalArgumentException
Sets the length of input data. The input data length may be required for stream-processing CCM which needs to know the data input length in advance.

Parameters:
inputLength - the length (number of bytes) of the input data
Throws:
java.lang.IllegalArgumentException - if the specified input length is not valid

getInputLength

public long getInputLength()
Gets the length of input data. The input data length may be required for stream-processing CCM which needs to know the data input length in advance.

Returns:
the length (number of bytes) of the input data or -1 if it has not been set
Throws:
java.lang.IllegalArgumentException - if the specified input length is not valid
See Also:
setInputLength(long)

getVersion

public int getVersion()
Returns the syntax version number.

Returns:
the syntax version number

getOriginatorInfo

public OriginatorInfo getOriginatorInfo()
Gets the OriginatorInfo, if included.

The originatorInfo may be set for including certificates and/or certificate revocation lists if required by the key management algorithm used.

Returns:
the originatorInfo, if included; otherwise null

getRecipientInfos

public RecipientInfo[] getRecipientInfos()
Returns all the recipient infos included in this AuthEnvelopedData object.

Returns:
an array containing all the RecipientInfo objects included into this AuthEnvelopedData

getRecipientInfos

public RecipientInfo[] getRecipientInfos(int type)
Returns all the recipient infos included in this AuthEnvelopedData object that have the specified type.

Returns:
an array containing all the RecipientInfo objects included into this AuthEnvelopedData that have the specified type (e.g. all KeyTransRecipientInfos); the array may be empty if no RecipientInfo with the requested type is included

getRecipientInfo

public RecipientInfo getRecipientInfo(X509Certificate recipientCertificate)
Returns the recipient info matching to the supplied recipient certificate.

This method may be used by a recipient for quering for the recipient info that holds the content authenticated encryption key encrypted with the public key of the given certificate.
Note that this method only can be used for searching for RecipientInfos of type KeyTransRecipientInfo or KeyAgreeRecipientInfo, but NOT for a RecipientInfo of type KEKRecipientInfo which does use a certificate.

Returns:
the RecipientInfo matching to the supplied recipient certificate, or null if no recipient info belonging to the given certificate can be found

getRecipientInfo

public RecipientInfo getRecipientInfo(KeyIdentifier recipientIdentifier)
Returns the RecipientInfo belonging to the recipient identified by the given recipient identifier.

Parameters:
recipientIdentifier - the recipient identifier identifying the recipient in mind
Returns:
the RecipientInfo matching to the supplied recipient identifier, or null if no recipient info belonging to the given recipient identifier can be found

getEncryptedContentInfo

public EncryptedContentInfoStream getEncryptedContentInfo()
Returns the EncryptedContentInfo included in this AuthEnvelopedDataStream object.

Returns:
the inherent EncryptedContentInfo

getAuthenticatedAttributes

public Attribute[] getAuthenticatedAttributes()
Gets the authenticated attributes included in this AuthEnvelopedData.

Returns:
the authenticated attributes; if included

getAuthenticatedAttribute

public Attribute getAuthenticatedAttribute(ObjectID oid)
Returns the first authenticated attribute matching to the given ObjectID, if included in this AuthEnvelopedData object.

Returns:
the first authenticated attribute belonging to the given ObjectID or null if there is no attribute for the given OID.

getMac

public byte[] getMac()
Gets the MAC value.

Returns:
the MAC value.

setMac

public void setMac(byte[] mac)
Sets the MAC value (if calculated outside).

Parameters:
mac - the MAC value.

getUnauthenticatedAttributes

public Attribute[] getUnauthenticatedAttributes()
Gets the unauthenticated attributes included in this AuthEnvelopedData.

Returns:
the unauthenticated attributes; if included

getUnauthenticatedAttribute

public Attribute getUnauthenticatedAttribute(ObjectID oid)
Returns the first unauthenticated attribute matching to the given ObjectID, if included in this AuthEnvelopedData object.

Returns:
the first unauthenticated attribute belonging to the given ObjectID or null if there is no attribute for the given OID.

toASN1Object

public ASN1Object toASN1Object()
                        throws CMSException
Returns this AuthEnvelopedDataStream as ASN1Object.

Specified by:
toASN1Object in interface ContentStream
Returns:
this AuthEnvelopedDataStream as ASN1Object.
Throws:
CMSException - if the ASN1Object could not be created

toASN1Object

protected ASN1Object toASN1Object(int blockSize)
                           throws CMSException
Returns this AuthEnvelopedData as ASN1Object.

If is positive a constructed OCTET STRING is used for encoding the encrypted content. This method actually will perform the encryption of the symmetric content-authenticated-encryption key for each participated recipient.

Parameters:
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive
Returns:
this AuthEnvelopedData as ASN1Object
Throws:
CMSException - if the ASN1Object could not be created

writeTo

public void writeTo(java.io.OutputStream os)
             throws java.io.IOException
Writes this AuthEnvelopedData BER encoded to the supplied output stream.

Parameters:
os - the output stream to which this AuthEnvelopedData shall be written
Throws:
java.io.IOException

writeTo

public void writeTo(java.io.OutputStream os,
                    int blockSize)
             throws java.io.IOException
Writes this AuthEnvelopedData BER encoded to the supplied output stream where a constructed OCTET STRING may be used for encoding the content.

When encoding the content data to the given stream it is piped through a cipher stream thereby performing the content authenticated encryption.

If the a positive blockSize value is specified, the encrypted content is encoded as indefinite constructed octet string being composed of a certain number of definite primitive encoded octet strings of blockSize length:

 0x24 0x80
           0x04 <blocksize> <first encrypted content block>
           0x04 <blocksize> <second encrypted content block>
           0x04 <blocksize> <third encrypted content block>
                ...
 0x00 0x00
 
Otherwise, whole the encrypted content is encoded as definite primitive octet string:
  0x04 <length> <encrypted content>
 

Parameters:
os - the output stream to which this SignedData shall be written
blockSize - the block size defining the encoding scheme - and specifying the length of each primitive encoded octet string component, if positive
Throws:
java.io.IOException - if an error occurs during writing the object

encodeCalled

public void encodeCalled(ASN1Object obj,
                         int id)
                  throws CodingException
This method implements the EncodeListener interface. During the encoding process the DerCoder calls this method when it actually is time for encoding the attributes and mac value components.

This method shall not be called by an application!

Specified by:
encodeCalled in interface EncodeListener
Parameters:
obj - the AuthEnvelopedData SEQUENCE
id - the id identifying the SEQUENCE to be processed
Throws:
CodingException - if an error occurs when computing/signing the message digest

notifyEOF

public void notifyEOF()
               throws java.io.IOException
This method implements the EOFListener interface for performing the final decoding of the attributes and mac field components.
An application shall not call this method! This method only is qualified as public method since it implements the IAIK-JCE iaik.utils.EOFListener interface.

Specified by:
notifyEOF in interface EOFListener
Throws:
java.io.IOException - if an error occurs while parsing the stream

toString

public java.lang.String toString()
Returns a string giving some information about this AuthEnvelopedData object.

Overrides:
toString in class java.lang.Object
Returns:
the string representation

toString

public java.lang.String toString(boolean detailed)
Returns a string giving some - if requested - detailed information about this AuthEnvelopedData object.

Specified by:
toString in interface ContentStream
Parameters:
detailed - - whether or not to give detailed information
Returns:
the string representation

This Javadoc may contain text parts from text parts from IETF Internet Standard specifications (see copyright note).

IAIK-CMS 6.0, (c) 2002 IAIK, (c) 2003, 2023 SIC