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);
|
||||
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");
|
||||
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)
|
||||
{
|
||||
ASSERT(IsValid());
|
||||
|
||||
size_t DecryptedLen = a_DecryptedMaxLength;
|
||||
int res = pk_decrypt(&m_Pk,
|
||||
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)
|
||||
{
|
||||
ASSERT(IsValid());
|
||||
|
||||
size_t EncryptedLength = a_EncryptedMaxLength;
|
||||
int res = pk_encrypt(&m_Pk,
|
||||
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
|
||||
{
|
||||
friend class cSslContext;
|
||||
|
||||
public:
|
||||
/** Constructs the public key out of the DER-encoded pubkey data */
|
||||
cPublicKey(const AString & a_PublicKeyDER);
|
||||
/** Constructs an empty key instance. Before use, it needs to be filled by ParsePublic() or ParsePrivate() */
|
||||
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();
|
||||
|
||||
@ -33,6 +42,20 @@ public:
|
||||
Both a_EncryptedData and a_DecryptedData must be at least <KeySizeBytes> bytes large.
|
||||
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);
|
||||
|
||||
/** 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:
|
||||
/** The public key PolarSSL representation */
|
||||
@ -40,8 +63,13 @@ protected:
|
||||
|
||||
/** The random generator used in encryption and decryption */
|
||||
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 */
|
||||
class cRsaPrivateKey
|
||||
{
|
||||
friend class cSslContext;
|
||||
|
||||
public:
|
||||
/** Creates a new empty object, the key is not assigned */
|
||||
cRsaPrivateKey(void);
|
||||
@ -51,8 +53,14 @@ protected:
|
||||
|
||||
/** The random generator used for generating the key and encryption / decryption */
|
||||
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)
|
||||
{
|
||||
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:
|
||||
@ -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)
|
||||
{
|
||||
ASSERT(m_IsValid); // Call Initialize() first
|
||||
|
||||
// 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:
|
||||
m_ExpectedPeerName = a_ExpectedPeerName;
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "polarssl/ssl.h"
|
||||
#include "../ByteBuffer.h"
|
||||
#include "PublicKey.h"
|
||||
#include "RsaPrivateKey.h"
|
||||
#include "X509Cert.h"
|
||||
|
||||
|
||||
@ -47,7 +49,16 @@ public:
|
||||
/** Returns true if the object has been initialized properly. */
|
||||
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.
|
||||
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. */
|
||||
@ -93,6 +104,15 @@ protected:
|
||||
/** The SSL context that PolarSSL uses. */
|
||||
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. */
|
||||
bool m_HasHandshaken;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user