/*
* Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#ifndef __ASNPKCS_H__
#define __ASNPKCS_H__
#include <e32std.h>
#include <e32base.h>
#include <s32file.h>
#include <signed.h>
#include <x509cert.h>
#include <mctkeystore.h>
/**
* @file
* @publishedPartner
* @released
*/
class CASN1EncSequence;
class CPBEncryptParms;
/**
* This class provides the means to encode PKCS#5 parameters
* into an ASN1 sequence as specified in the PKCS#5 specifications.
*
*/
class TASN1EncPKCS5
{
public:
/**
* Returns an ASN1 sequence encoding the given PKCS#5 PBE parameters.
* The ASN1 syntax used is specified in the PKCS#5 v2.0 specifications.
* Refer to the specs for a detailed description of the returned sequence.
*
* This class is used, for instance, by TASN1EncPKCS8 to specify the PBE
* parameters of encrypted private keys.
*
* @param aParms The PBE parameters to be encoded
*
* @return An ASN1 sequence encoding the given PBE parameters.
*/
IMPORT_C static CASN1EncSequence* EncodeDERL(const CPBEncryptParms& aParms);
};
/**
* This class provides the means to decode an ASN1 sequence encoding
* PKCS#5 PBE parameters.
*
*/
class TASN1DecPKCS5
{
public:
/**
* Decodes a ASN1 sequence encoding PKCS#5 PBE parameters.
* The ASN1 syntax is specified in the PKCS#5 v2.0 specifications.
*
* @param aBinaryData A descriptor containing the ASN1 data in binary format.
*
* @return The decoded PBE parameters.
*/
IMPORT_C static CPBEncryptParms* DecodeDERL(const TDesC8& aBinaryData);
};
//!
//! Converts stored key data and key info to PKCS8 and returns ASN1 encoding thereof
//!
class CDecPKCS8Data;
/// The minimum number of bytes necessary to determine that data is cleartext pkcs8
const TInt KIsPKCS8DataMinLength = 24;
/// The minimum number of bytes necessary to determine that data is encrypted pkcs8
const TInt KIsEncryptedPKCS8DataMinLength = 36;
/**
* Provides the means to decode PKCS#8 encoded private keys.
*
*/
class TASN1DecPKCS8
{
public:
/**
* Decodes DER encoded ASN1 data representing a PKCS#8 clear text private key.
* See the PKCS#8 specifications for the ASN1 syntax.
*
* @param aBinaryData A descriptor containing the ASN1 data.
*
* @return A pointer to a CDecPKCS8Data object containing the decoded private key.
*/
IMPORT_C static CDecPKCS8Data* DecodeDERL(const TDesC8& aBinaryData);
/**
* Decodes DER encoded ASN1 data representing a PKCS#8 encrypted private key.
* See the PKCS#8 specifications for the ASN1 syntax.
*
* @param aBinaryData A descriptor containing the ASN1 data.
* @param aPassword The password to decrypt the key.
*
* @return A pointer to a CDecPKCS8Data object containing the decoded private key.
*/
IMPORT_C static CDecPKCS8Data* DecodeEncryptedDERL(const TDesC8& aBinaryData, const TDesC8& aPassword);
/**
* Determines if some binary data is a pkcs#8 clear text private key.
*
* @param aBinaryData A descriptor containing the data. This must be at
* least KIsPKCS8DataMinLength bytes long.
*
* @return ETrue if binary data is pkcs#8 clear text private key or EFalse if it is not.
*/
IMPORT_C static TBool IsPKCS8Data(const TDesC8& aBinaryData);
/**
* Determines if some binary data is an encrypted pkcs#8 private key.
*
* @param aBinaryData A descriptor containing the data.
*
* @return ETrue if binary data is an encrypted pkcs#8 private key or EFalse if it is not.
*/
IMPORT_C static TBool IsEncryptedPKCS8Data(const TDesC8& aBinaryData);
private:
static TBool IsASN1Sequence(const TDesC8& aBinaryData, TInt& aPos);
static TBool IsExpectedData(const TDesC8& aBinaryData, TInt& aPos, const TDesC8& aExpectedData);
};
//!
//! Server side object decodes a PKCS8 data object incoming from client
//! On construction, decodes the data to determine version, key
//! algorithm and gives access to the key data by creating the appropriate
//! MPKCS8DecodedKeyPairData object for the algorithm
//!
//! PrivateKeyInfo ::= SEQUENCE {
//! version Version,
//! privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
//! privateKey PrivateKey,
//! attributes [0] IMPLICIT Attributes OPTIONAL }
//!
//! Version ::= INTEGER
//! PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
//! PrivateKey ::= OCTET STRING
//! Attributes ::= SET OF Attribute
//!
class MPKCS8DecodedKeyPairData; // Forward declare
/**
* This class provides the means to decode PKCS#8 encoded private keys.
*
*/
class CDecPKCS8Data : public CBase
{
public:
/**
* @internalComponent
*
* Decodes a ASN1 sequence encoding PKCS#8 encrypted private key.
*
* @param aData A descriptor containing the data.
*
* @return A pointer to a CDecPKCS8Data object containing the decoded private key.
*/
static CDecPKCS8Data* NewL(const TDesC8& aData);
public:
/**
* Destructor
*/
virtual ~CDecPKCS8Data();
public:
/*
* Returns the version number of the certificate.
*
* @return Version number of the certificate.
*/
inline TInt Version() const;
/*
* Return the algorithm identifier.
*
* @return algorithm identifier.
*/
inline TAlgorithmId Algorithm() const;
/*
* Returns the key pair data. This depends on the value returned by CDecPKCS8Data::Algorithm()
*
* @return either RSA or DSA to M class key pair data.
*/
inline MPKCS8DecodedKeyPairData* KeyPairData() const;
/*
* Returns a DER-encoded set of PKCS8 attributes (use TASN1DecSet to decode)
*
* @return a PKCS8 attributes
*/
inline const TDesC8& PKCS8Attributes() const;
protected:
/** @internalComponent */
CDecPKCS8Data();
/** @internalComponent */
void ConstructL(const TDesC8& aData);
private: // No copying
CDecPKCS8Data(const CDecPKCS8Data&);
CDecPKCS8Data& operator=(CDecPKCS8Data&);
private:
TInt iVersion;
TAlgorithmId iAlgorithmID;
MPKCS8DecodedKeyPairData* iKeyPairData;
HBufC8* iAttributes;
};
//! Mixin class for generic actions to be performed on a keypair
//!
//!
class MPKCS8DecodedKeyPairData
{
public:
/**
* Gets a key identifier
*
* @param aKeyIdentifier A descriptor containing a key identifier (SHA1 hash of modulus)
*/
virtual void GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const = 0;
virtual TUint KeySize() const = 0;
virtual void Release() = 0;
protected:
virtual ~MPKCS8DecodedKeyPairData();
};
class CRSAPublicKey;
class CRSAPrivateKey;
class TASN1DecGeneric;
//! Represents an RSA key pair and provides the means to externalize it to
//! a stream and generate a key identifier (SHA1 hash of modulus)
//!
class CPKCS8KeyPairRSA : public CBase, public MPKCS8DecodedKeyPairData
{
public:
/**
* @internalComponent
*
* Constructs the ASN1 PKCS#8 RSA private key.
*
* @param aSource A descriptor containing the key identifier
*
* @return A pointer to a MPKCS8DecodedKeyPairData object containing the decoded private key.
*/
static MPKCS8DecodedKeyPairData* NewL(const TASN1DecGeneric& aSource);
public:
/**
* Destructor
*/
virtual ~CPKCS8KeyPairRSA();
public:
/**
* Gets a key identifier
*
* @param aKeyIdentifier A descriptor containing a key identifier
*/
virtual void GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const;
virtual TUint KeySize() const;
virtual void Release();
/**
* Contructs a RSA Public Key
*
* @return A RSA Public Key
*/
inline const CRSAPublicKey& PublicKey() const;
/**
* Contructs a RSA Private Key
*
* @return A RSA Private Key
*/
inline const CRSAPrivateKey& PrivateKey() const;
protected:
CPKCS8KeyPairRSA(){}
/** @internalComponent */
void ConstructL(const TASN1DecGeneric& aSource);
private:
CRSAPublicKey* iPublicKey;
CRSAPrivateKey* iPrivateKey;
};
class CDSAPublicKey;
class CDSAPrivateKey;
//! Represents a DSA key pair and provides the means to externalize it to
//! a stream and generate a key identifier
//!
class CPKCS8KeyPairDSA : public CBase, public MPKCS8DecodedKeyPairData
{
public:
/**
* @internalComponent
*
* Contructs the ASN1 PKCS#8 DSA private key
*
* @param aParamsData A block of PKCS#8 parameters data for DER data to decode
*
* @param aSource A descriptor containing a key identifier
*
* @return A pointer to MPKCS8DecodedKeyPairData object containing the decoded key.
*/
static MPKCS8DecodedKeyPairData* NewL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource);
public:
/**
* Destructor
*/
virtual ~CPKCS8KeyPairDSA();
public:
/**
* Gets a key identifier
*
* @param aKeyIdentifier A descriptor containing a key identifier
*/
virtual void GetKeyIdentifierL(TKeyIdentifier& aKeyIdentifier) const;
virtual TUint KeySize() const;
virtual void Release();
/**
* Contructs a DSA Public Key
*
* @return A DSA Public Key
*/
inline const CDSAPublicKey& PublicKey() const;
/**
* Contructs a RSA Private Key
*
* @return A RSA Private Key
*/
inline const CDSAPrivateKey& PrivateKey() const;
protected:
CPKCS8KeyPairDSA(){}
/** @internalComponent */
void ConstructL(const TDesC8& aParamsData, const TASN1DecGeneric& aSource);
private:
CDSAPublicKey* iPublicKey;
CDSAPrivateKey* iPrivateKey;
};
class CRSAPrivateKeyCRT;
class CASN1EncOctetString;
class CASN1EncBase;
class CPBEncryptParms;
class CPBEncryptor;
class RInteger;
/**
* Encodes the given private key using the pkcs#8 standard.
*
* The returned ASN1 sequence respects the following grammar:
*
* PrivateKeyInfo ::= SEQUENCE {
* version Version,
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
* privateKey PrivateKey,
* attributes [0] IMPLICIT Attributes OPTIONAL }
*
* Version ::= INTEGER
* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
* PrivateKey ::= OCTET STRING
* Attributes ::= SET OF Attribute
*
* The PrivateKeyAlgorithmIdentifier format it depends on the
* specific algorithm it represents. For RSA is specified in
* the PKCS#1 document, for DSA in PKCS#11.
*
* Or, in the case of encrypted private keys:
*
* EncryptedPrivateKeyInfo ::= SEQUENCE {
* encryptionAlgorithm EncryptionAlgorithmIdentifier,
* encryptedData EncryptedData }
*
* EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
* EncryptedData ::= OCTET STRING
*
* AlgorithmIdentifier is the ASN1 sequence defined in the
* PKCS#5 standard.
*/
class TASN1EncPKCS8
{
public:
/**
* Returns the ASN1 PKCS#8 encoding of a RSA private key.
*
* The private key syntax for this key type is defined in
* the PKCS#1 document. It follows the grammar:
*
* RSAPrivateKey ::= SEQUENCE {
* version Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER, -- (inverse of q) mod p
* otherPrimeInfos OtherPrimeInfos OPTIONAL
* }
*
* @param aPrivateKey The private key to be encoded (must be in CRT format)
* @param aPublicKey The corresponding public key.
* @param attributes A set of attributes of the extended information
* that is encrypted along with the private-key
* information.
*
* @return An ASN1 Sequence encoding the key.
*/
IMPORT_C static CASN1EncSequence* EncodeL(const CRSAPrivateKeyCRT& aPrivateKey,
const CRSAPublicKey& aPublicKey, const TDesC8& attributes);
/**
* Encodes an RSA key in encrypted format.
*
* @param aPrivateKey The private key to be encoded (must be in CRT format)
* @param aPublicKey The corresponding public key.
* @param aEncryptor The object used to encrypt the data.
* @param aData The encryption parameters of the given encryptor.
* These parameters are stored in the resulting sequence.
* @param attributes A set of attributes of the extended information
* that is encrypted along with the private-key
* information.
*
* @return An ASN1 Sequence encoding the encrypted key.
*/
IMPORT_C static CASN1EncSequence* EncodeEncryptedL(const CRSAPrivateKeyCRT& aPrivateKey,
const CRSAPublicKey& aPublicKey,
CPBEncryptor& aEncryptor,
CPBEncryptParms& aData, const TDesC8& attributes);
/**
* Returns the ASN1 PKCS#8 encoding of a DSA private key.
*
* The private key syntax for this key type is defined in
* the PKCS#11 document.
*
* @param aPrivateKey The private key to be encoded
* @param attributes A set of attributes of the extended information
* that is encrypted along with the private-key
* information.
*
* @return An ASN1 Sequence encoding the key.
*/
IMPORT_C static CASN1EncSequence* EncodeL(const CDSAPrivateKey& aPrivateKey, const TDesC8& attributes);
/**
* Encodes a DSA key in encrypted format.
*
* @param aPrivateKey The private key to be encoded.
* @param aEncryptor The object used to encrypt the data.
* @param aData The encryption parameters of the given encryptor.
* These parameters are stored in the resulting sequence.
* @param attributes
*
* @return An ASN1 Sequence encoding the encrypted key.
*/
IMPORT_C static CASN1EncSequence* EncodeEncryptedL(const CDSAPrivateKey& aPrivateKey,
CPBEncryptor& aEncryptor,
CPBEncryptParms& aData,
const TDesC8& attributes);
private:
/**
*
* Converts the ASN1 element to an octet string.
*
* @param aAsnElement The ASN1 element to be converted
*
* @return An ASN1 Octet string representing the input element.
*/
static CASN1EncOctetString* ElementToOctetL(CASN1EncBase& aAsnElement);
/**
* Given a ASN1 sequence representing a private key and a CPBEncryptor object,
* it returns an ASN1 octet string containing the key sequence encrypted by
* the given encryptor.
*
* @param aKeySeq The key sequence to be encrypted.
* @param aEncryptor The CPBEncryptor object used to encrypt the given key.
*
* @return An ASN1 octet string containing the encrypted key.
*/
static CASN1EncOctetString* EncryptKeySequenceL(CASN1EncSequence& aKeySeq,
CPBEncryptor& aEncryptor);
/**
*
* Given a valid key sequence and appropriate PBE encryptors it
* encrypts the key and creates a PKCS#8 sequence of type
* EncryptedPrivateKeyInfo.
*
* @param aPrivateKeySequence A ASN1 sequence of the private key to be
* encrypted. Generally the structure of the
* sequence will depend on the key type.
* @param aEncryptor The PBE encryptor to be used to encrypt the key.
* @param aData The PBE encryptor parameters. This information must be
* included in the final ASN1 sequence.
*
* @return An ASN1 sequence of type EncryptedPrivateKeyInfo.
*/
static CASN1EncSequence* EncryptedSequenceL(CASN1EncSequence& aPrivateKeySequence,
CPBEncryptor& aEncryptor,
CPBEncryptParms& aData);
/**
* Given a CRT RSA private key it calculates the RSA private exponent "d".
*
* @param aPrivateKey The RSA private key in CRT format we are interested in.
* @param aPublicKey The RSA public key
*
* @return The RSA private exponent "d".
*/
static const RInteger CalculateRSAPrivExpL(const CRSAPrivateKeyCRT& aPrivateKey, const CRSAPublicKey& aPublicKey);
/**
* Adds the given DER encoded ASN1 structure to the given sequence. If the structure is KNullDesC8
* nothing is added. This method is used by the encoder to add the optional pkcs8 attributes to
* the ASN1 pkcs8 key it generates. PKCS8 attributes are stored as uninterpreted DER encoded
* binary data in the keystore.
*
* @param aAttribute The DER encoded ASN1 structure.
* @param aSeq The sequence to which we want to add the attributes.
*/
static void AddAttributesL(CASN1EncSequence& aSeq, const TDesC8& aAttribute);
};
// Inline function definition //
inline TInt CDecPKCS8Data::Version() const
{
return (iVersion);
}
inline TAlgorithmId CDecPKCS8Data::Algorithm() const
{
return (iAlgorithmID);
}
inline MPKCS8DecodedKeyPairData* CDecPKCS8Data::KeyPairData() const
{
return (iKeyPairData);
}
inline const TDesC8& CDecPKCS8Data::PKCS8Attributes() const
{
if (iAttributes)
return (*iAttributes);
else
return (KNullDesC8);
}
inline const CRSAPublicKey& CPKCS8KeyPairRSA::PublicKey() const
{
return *iPublicKey;
}
inline const CRSAPrivateKey& CPKCS8KeyPairRSA::PrivateKey() const
{
return *iPrivateKey;
}
inline const CDSAPublicKey& CPKCS8KeyPairDSA::PublicKey() const
{
return *iPublicKey;
}
inline const CDSAPrivateKey& CPKCS8KeyPairDSA::PrivateKey() const
{
return *iPrivateKey;
}
#endif // __ASNPKCS_H__