cSslContext supports setting own cert / privkey.
This commit is contained in:
parent
e6786074d5
commit
47feb91e57
@ -10,15 +10,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cPublicKey::cPublicKey(const AString & a_PublicKeyDER)
|
cPublicKey::cPublicKey(void)
|
||||||
{
|
{
|
||||||
pk_init(&m_Pk);
|
pk_init(&m_Pk);
|
||||||
if (pk_parse_public_key(&m_Pk, (const Byte *)a_PublicKeyDER.data(), a_PublicKeyDER.size()) != 0)
|
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPublicKey::cPublicKey(const AString & a_PublicKeyData)
|
||||||
{
|
{
|
||||||
|
pk_init(&m_Pk);
|
||||||
|
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
||||||
|
int res = ParsePublic(a_PublicKeyData.data(), a_PublicKeyData.size());
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
LOGWARNING("Failed to parse public key: -0x%x", res);
|
||||||
|
ASSERT(!"Cannot parse PubKey");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cPublicKey::cPublicKey(const AString & a_PrivateKeyData, const AString & a_Password)
|
||||||
|
{
|
||||||
|
pk_init(&m_Pk);
|
||||||
|
m_CtrDrbg.Initialize("rsa_privkey", 11);
|
||||||
|
int res = ParsePrivate(a_PrivateKeyData.data(), a_PrivateKeyData.size(), a_Password);
|
||||||
|
if (res != 0)
|
||||||
|
{
|
||||||
|
LOGWARNING("Failed to parse private key: -0x%x", res);
|
||||||
ASSERT(!"Cannot parse PubKey");
|
ASSERT(!"Cannot parse PubKey");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_CtrDrbg.Initialize("rsa_pubkey", 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +65,8 @@ cPublicKey::~cPublicKey()
|
|||||||
|
|
||||||
int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength, Byte * a_DecryptedData, size_t a_DecryptedMaxLength)
|
||||||
{
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
size_t DecryptedLen = a_DecryptedMaxLength;
|
size_t DecryptedLen = a_DecryptedMaxLength;
|
||||||
int res = pk_decrypt(&m_Pk,
|
int res = pk_decrypt(&m_Pk,
|
||||||
a_EncryptedData, a_EncryptedLength,
|
a_EncryptedData, a_EncryptedLength,
|
||||||
@ -55,6 +86,8 @@ int cPublicKey::Decrypt(const Byte * a_EncryptedData, size_t a_EncryptedLength,
|
|||||||
|
|
||||||
int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength)
|
||||||
{
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
size_t EncryptedLength = a_EncryptedMaxLength;
|
size_t EncryptedLength = a_EncryptedMaxLength;
|
||||||
int res = pk_encrypt(&m_Pk,
|
int res = pk_encrypt(&m_Pk,
|
||||||
a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength,
|
a_PlainData, a_PlainLength, a_EncryptedData, &EncryptedLength, a_EncryptedMaxLength,
|
||||||
@ -71,3 +104,46 @@ int cPublicKey::Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cPublicKey::ParsePublic(const void * a_Data, size_t a_NumBytes)
|
||||||
|
{
|
||||||
|
ASSERT(!IsValid()); // Cannot parse a second key
|
||||||
|
|
||||||
|
return pk_parse_public_key(&m_Pk, (const unsigned char *)a_Data, a_NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cPublicKey::ParsePrivate(const void * a_Data, size_t a_NumBytes, const AString & a_Password)
|
||||||
|
{
|
||||||
|
ASSERT(!IsValid()); // Cannot parse a second key
|
||||||
|
|
||||||
|
if (a_Password.empty())
|
||||||
|
{
|
||||||
|
return pk_parse_key(&m_Pk, (const unsigned char *)a_Data, a_NumBytes, NULL, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return pk_parse_key(
|
||||||
|
&m_Pk,
|
||||||
|
(const unsigned char *)a_Data, a_NumBytes,
|
||||||
|
(const unsigned char *)a_Password.c_str(), a_Password.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPublicKey::IsValid(void) const
|
||||||
|
{
|
||||||
|
return (pk_get_type(&m_Pk) != POLARSSL_PK_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,9 +18,18 @@
|
|||||||
|
|
||||||
class cPublicKey
|
class cPublicKey
|
||||||
{
|
{
|
||||||
|
friend class cSslContext;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Constructs the public key out of the DER-encoded pubkey data */
|
/** Constructs an empty key instance. Before use, it needs to be filled by ParsePublic() or ParsePrivate() */
|
||||||
cPublicKey(const AString & a_PublicKeyDER);
|
cPublicKey(void);
|
||||||
|
|
||||||
|
/** Constructs the public key out of the DER- or PEM-encoded pubkey data */
|
||||||
|
cPublicKey(const AString & a_PublicKeyData);
|
||||||
|
|
||||||
|
/** Constructs the private key out of the DER- or PEM-encoded privkey data, with the specified password.
|
||||||
|
If a_Password is empty, no password is assumed. */
|
||||||
|
cPublicKey(const AString & a_PrivateKeyData, const AString & a_Password);
|
||||||
|
|
||||||
~cPublicKey();
|
~cPublicKey();
|
||||||
|
|
||||||
@ -34,14 +43,33 @@ public:
|
|||||||
Returns the number of bytes decrypted, or negative number for error. */
|
Returns the number of bytes decrypted, or negative number for error. */
|
||||||
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
int Encrypt(const Byte * a_PlainData, size_t a_PlainLength, Byte * a_EncryptedData, size_t a_EncryptedMaxLength);
|
||||||
|
|
||||||
|
/** Parses the specified data into a public key representation.
|
||||||
|
The key can be DER- or PEM-encoded.
|
||||||
|
Returns 0 on success, PolarSSL error code on failure. */
|
||||||
|
int ParsePublic(const void * a_Data, size_t a_NumBytes);
|
||||||
|
|
||||||
|
/** Parses the specified data into a private key representation.
|
||||||
|
If a_Password is empty, no password is assumed.
|
||||||
|
The key can be DER- or PEM-encoded.
|
||||||
|
Returns 0 on success, PolarSSL error code on failure. */
|
||||||
|
int ParsePrivate(const void * a_Data, size_t a_NumBytes, const AString & a_Password);
|
||||||
|
|
||||||
|
/** Returns true if the contained key is valid. */
|
||||||
|
bool IsValid(void) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** The public key PolarSSL representation */
|
/** The public key PolarSSL representation */
|
||||||
pk_context m_Pk;
|
pk_context m_Pk;
|
||||||
|
|
||||||
/** The random generator used in encryption and decryption */
|
/** The random generator used in encryption and decryption */
|
||||||
cCtrDrbgContext m_CtrDrbg;
|
cCtrDrbgContext m_CtrDrbg;
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the internal context ptr. Only use in PolarSSL API calls. */
|
||||||
|
pk_context * GetInternal(void) { return &m_Pk; }
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
typedef SharedPtr<cPublicKey> cPublicKeyPtr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
/** Encapsulates an RSA private key used in PKI cryptography */
|
/** Encapsulates an RSA private key used in PKI cryptography */
|
||||||
class cRsaPrivateKey
|
class cRsaPrivateKey
|
||||||
{
|
{
|
||||||
|
friend class cSslContext;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Creates a new empty object, the key is not assigned */
|
/** Creates a new empty object, the key is not assigned */
|
||||||
cRsaPrivateKey(void);
|
cRsaPrivateKey(void);
|
||||||
@ -51,8 +53,14 @@ protected:
|
|||||||
|
|
||||||
/** The random generator used for generating the key and encryption / decryption */
|
/** The random generator used for generating the key and encryption / decryption */
|
||||||
cCtrDrbgContext m_CtrDrbg;
|
cCtrDrbgContext m_CtrDrbg;
|
||||||
|
|
||||||
|
|
||||||
|
/** Returns the internal context ptr. Only use in PolarSSL API calls. */
|
||||||
|
rsa_context * GetInternal(void) { return &m_Rsa; }
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
typedef SharedPtr<cRsaPrivateKey> cRsaPrivateKeyPtr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
|
|||||||
if (m_IsValid)
|
if (m_IsValid)
|
||||||
{
|
{
|
||||||
LOGWARNING("SSL: Double initialization is not supported.");
|
LOGWARNING("SSL: Double initialization is not supported.");
|
||||||
return POLARSSL_ERR_SSL_MALLOC_FAILED; // There is no return value well-suited for this, reuse this one.
|
return POLARSSL_ERR_SSL_BAD_INPUT_DATA; // There is no return value well-suited for this, reuse this one.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the CtrDrbg context, create a new one if needed:
|
// Set the CtrDrbg context, create a new one if needed:
|
||||||
@ -80,8 +80,56 @@ int cSslContext::Initialize(bool a_IsClient, const SharedPtr<cCtrDrbgContext> &
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKeyPtr & a_OwnCertPrivKey)
|
||||||
|
{
|
||||||
|
ASSERT(m_IsValid); // Call Initialize() first
|
||||||
|
|
||||||
|
// Check that both the cert and the key is valid:
|
||||||
|
if ((a_OwnCert.get() == NULL) || (a_OwnCertPrivKey.get() == NULL))
|
||||||
|
{
|
||||||
|
LOGWARNING("SSL: Own certificate is not valid, skipping the set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have the cert stored for later, PolarSSL only uses the cert later on
|
||||||
|
m_OwnCert = a_OwnCert;
|
||||||
|
m_OwnCertPrivKey = a_OwnCertPrivKey;
|
||||||
|
|
||||||
|
// Set into the context:
|
||||||
|
ssl_set_own_cert_rsa(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey->GetInternal());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cSslContext::SetOwnCert(const cX509CertPtr & a_OwnCert, const cPublicKeyPtr & a_OwnCertPrivKey)
|
||||||
|
{
|
||||||
|
ASSERT(m_IsValid); // Call Initialize() first
|
||||||
|
|
||||||
|
// Check that both the cert and the key is valid:
|
||||||
|
if ((a_OwnCert.get() == NULL) || (a_OwnCertPrivKey.get() == NULL))
|
||||||
|
{
|
||||||
|
LOGWARNING("SSL: Own certificate is not valid, skipping the set.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have the cert stored for later, PolarSSL only uses the cert later on
|
||||||
|
m_OwnCert = a_OwnCert;
|
||||||
|
m_OwnCertPrivKey2 = a_OwnCertPrivKey;
|
||||||
|
|
||||||
|
// Set into the context:
|
||||||
|
ssl_set_own_cert(&m_Ssl, m_OwnCert->GetInternal(), m_OwnCertPrivKey2->GetInternal());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName)
|
void cSslContext::SetCACerts(const cX509CertPtr & a_CACert, const AString & a_ExpectedPeerName)
|
||||||
{
|
{
|
||||||
|
ASSERT(m_IsValid); // Call Initialize() first
|
||||||
|
|
||||||
// Store the data in our internal buffers, to avoid losing the pointers later on
|
// Store the data in our internal buffers, to avoid losing the pointers later on
|
||||||
// PolarSSL will need these after this call returns, and the caller may move / delete the data before that:
|
// PolarSSL will need these after this call returns, and the caller may move / delete the data before that:
|
||||||
m_ExpectedPeerName = a_ExpectedPeerName;
|
m_ExpectedPeerName = a_ExpectedPeerName;
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "polarssl/ssl.h"
|
#include "polarssl/ssl.h"
|
||||||
#include "../ByteBuffer.h"
|
#include "../ByteBuffer.h"
|
||||||
|
#include "PublicKey.h"
|
||||||
|
#include "RsaPrivateKey.h"
|
||||||
#include "X509Cert.h"
|
#include "X509Cert.h"
|
||||||
|
|
||||||
|
|
||||||
@ -47,7 +49,16 @@ public:
|
|||||||
/** Returns true if the object has been initialized properly. */
|
/** Returns true if the object has been initialized properly. */
|
||||||
bool IsValid(void) const { return m_IsValid; }
|
bool IsValid(void) const { return m_IsValid; }
|
||||||
|
|
||||||
/** Sets a cert chain as the trusted cert store for this context.
|
/** Sets the certificate to use as our own. Must be used when representing a server, optional when client.
|
||||||
|
Must be called after Initialize(). */
|
||||||
|
void SetOwnCert(const cX509CertPtr & a_OwnCert, const cRsaPrivateKeyPtr & a_OwnCertPrivKey);
|
||||||
|
|
||||||
|
/** Sets the certificate to use as our own. Must be used when representing a server, optional when client.
|
||||||
|
Must be called after Initialize().
|
||||||
|
Despite the class name, a_OwnCertPrivKey is a PRIVATE key. */
|
||||||
|
void SetOwnCert(const cX509CertPtr & a_OwnCert, const cPublicKeyPtr & a_OwnCertPrivKey);
|
||||||
|
|
||||||
|
/** Sets a cert chain as the trusted cert store for this context. Must be called after Initialize().
|
||||||
Calling this will switch the context into strict cert verification mode.
|
Calling this will switch the context into strict cert verification mode.
|
||||||
a_ExpectedPeerName is the CommonName that we expect the SSL peer to have in its cert,
|
a_ExpectedPeerName is the CommonName that we expect the SSL peer to have in its cert,
|
||||||
if it is different, the verification will fail. An empty string will disable the CN check. */
|
if it is different, the verification will fail. An empty string will disable the CN check. */
|
||||||
@ -93,6 +104,15 @@ protected:
|
|||||||
/** The SSL context that PolarSSL uses. */
|
/** The SSL context that PolarSSL uses. */
|
||||||
ssl_context m_Ssl;
|
ssl_context m_Ssl;
|
||||||
|
|
||||||
|
/** The certificate that we present to the peer. */
|
||||||
|
cX509CertPtr m_OwnCert;
|
||||||
|
|
||||||
|
/** Private key for m_OwnCert, if initialized from a cRsaPrivateKey */
|
||||||
|
cRsaPrivateKeyPtr m_OwnCertPrivKey;
|
||||||
|
|
||||||
|
/** Private key for m_OwnCert, if initialized from a cPublicKey. Despite the class name, this is a PRIVATE key. */
|
||||||
|
cPublicKeyPtr m_OwnCertPrivKey2;
|
||||||
|
|
||||||
/** True if the SSL handshake has been completed. */
|
/** True if the SSL handshake has been completed. */
|
||||||
bool m_HasHandshaken;
|
bool m_HasHandshaken;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user