mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
ensured maximum backward compatibility for crypto changes that will occur in future v0.7
This commit is contained in:
parent
e2c1661c49
commit
f6d69e09d5
@ -708,7 +708,6 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
|
||||
#define SERIAL_RAND_BITS 64
|
||||
|
||||
//const EVP_MD *digest = EVP_sha1();
|
||||
ASN1_INTEGER *serial = ASN1_INTEGER_new();
|
||||
EVP_PKEY *tmppkey;
|
||||
X509 *x509 = X509_new();
|
||||
if (x509 == NULL)
|
||||
@ -733,12 +732,28 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
|
||||
|
||||
std::cerr << "AuthSSLimpl::SignX509Req() Issuer name: " << AuthGPG::getAuthGPG()->getGPGOwnId().toStdString() << std::endl;
|
||||
|
||||
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_002
|
||||
static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_07_0001 ;
|
||||
#else
|
||||
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_001
|
||||
static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0001 ;
|
||||
#else
|
||||
static const uint64_t CERTIFICATE_SERIAL_NUMBER = RS_CERTIFICATE_VERSION_NUMBER_06_0000 ;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BIGNUM *btmp = BN_new();
|
||||
BN_set_word(btmp,CERTIFICATE_SERIAL_NUMBER) ;
|
||||
|
||||
#ifdef OLD_CODE
|
||||
if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
|
||||
{
|
||||
std::cerr << "AuthSSLimpl::SignX509Req() rand FAIL" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
ASN1_INTEGER *serial = ASN1_INTEGER_new();
|
||||
|
||||
if (!BN_to_ASN1_INTEGER(btmp, serial))
|
||||
{
|
||||
std::cerr << "AuthSSLimpl::SignX509Req() asn1 FAIL" << std::endl;
|
||||
@ -769,21 +784,6 @@ X509 *AuthSSLimpl::SignX509ReqWithGPG(X509_REQ *req, long /*days*/)
|
||||
ASN1_TIME_set(X509_get_notBefore(x509), 0);
|
||||
ASN1_TIME_set(X509_get_notAfter(x509), 0);
|
||||
|
||||
// OLD code, sets validity time of cert to be between now and some days in the future
|
||||
/*
|
||||
if (!X509_gmtime_adj(X509_get_notBefore(x509),0))
|
||||
{
|
||||
std::cerr << "AuthSSLimpl::SignX509Req() notbefore FAIL" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60*60*24*days))
|
||||
{
|
||||
std::cerr << "AuthSSLimpl::SignX509Req() notafter FAIL" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
if (!X509_set_subject_name(x509, X509_REQ_get_subject_name(req)))
|
||||
{
|
||||
std::cerr << "AuthSSLimpl::SignX509Req() sub FAIL" << std::endl;
|
||||
@ -1053,11 +1053,12 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
|
||||
#endif
|
||||
|
||||
hashoutl=EVP_MD_size(type);
|
||||
unsigned char *buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl);
|
||||
unsigned char *buf_hashout=NULL ;
|
||||
|
||||
sigoutl=2048; //hashoutl; //EVP_PKEY_size(pkey);
|
||||
unsigned char *buf_sigout=(unsigned char *)OPENSSL_malloc((unsigned int)sigoutl);
|
||||
|
||||
uint32_t certificate_version = getX509RetroshareCertificateVersion(x509) ;
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "Buffer Sizes: in: " << inl;
|
||||
std::cerr << " HashOut: " << hashoutl;
|
||||
@ -1065,7 +1066,8 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
if ((buf_in == NULL) || (buf_hashout == NULL) || (buf_sigout == NULL)) {
|
||||
if ((buf_in == NULL) || (buf_sigout == NULL))
|
||||
{
|
||||
hashoutl=0;
|
||||
sigoutl=0;
|
||||
fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n");
|
||||
@ -1082,23 +1084,34 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
|
||||
i2d(data,&p);
|
||||
#endif
|
||||
|
||||
#ifndef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003
|
||||
/* data in buf_in, ready to be hashed */
|
||||
EVP_DigestInit_ex(ctx,type, NULL);
|
||||
EVP_DigestUpdate(ctx,(unsigned char *)buf_in,inl);
|
||||
|
||||
if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, (unsigned int *)&hashoutl))
|
||||
if(certificate_version < RS_CERTIFICATE_VERSION_NUMBER_07_0001)
|
||||
{
|
||||
hashoutl=0;
|
||||
fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n");
|
||||
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ;
|
||||
goto err;
|
||||
}
|
||||
buf_hashout=(unsigned char *)OPENSSL_malloc((unsigned int)hashoutl);
|
||||
|
||||
if(buf_hashout == NULL)
|
||||
{
|
||||
hashoutl=0;
|
||||
sigoutl=0;
|
||||
fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE)\n");
|
||||
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ;
|
||||
goto err;
|
||||
}
|
||||
/* data in buf_in, ready to be hashed */
|
||||
EVP_DigestInit_ex(ctx,type, NULL);
|
||||
EVP_DigestUpdate(ctx,(unsigned char *)buf_in,inl);
|
||||
|
||||
if (!EVP_DigestFinal(ctx,(unsigned char *)buf_hashout, (unsigned int *)&hashoutl))
|
||||
{
|
||||
hashoutl=0;
|
||||
fprintf(stderr, "AuthSSLimpl::AuthX509: ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB)\n");
|
||||
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_MALLOC_ERROR ;
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "Digest Applied: len: " << hashoutl << std::endl;
|
||||
#endif
|
||||
std::cerr << "Digest Applied: len: " << hashoutl << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* copy data into signature */
|
||||
if(sigoutl < signature->length)
|
||||
@ -1180,11 +1193,17 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
|
||||
|
||||
// passed, verify the signature itself
|
||||
|
||||
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_003
|
||||
if (!AuthGPG::getAuthGPG()->VerifySignBin(buf_in, inl, buf_sigout, (unsigned int) sigoutl, pd.fpr)) {
|
||||
#else
|
||||
if (!AuthGPG::getAuthGPG()->VerifySignBin(buf_hashout, hashoutl, buf_sigout, (unsigned int) sigoutl, pd.fpr)) {
|
||||
#endif
|
||||
if(certificate_version < RS_CERTIFICATE_VERSION_NUMBER_07_0001)
|
||||
{
|
||||
if (!AuthGPG::getAuthGPG()->VerifySignBin(buf_hashout, hashoutl, buf_sigout, (unsigned int) sigoutl, pd.fpr))
|
||||
{
|
||||
sigoutl = 0;
|
||||
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE ;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else if (!AuthGPG::getAuthGPG()->VerifySignBin(buf_in, inl, buf_sigout, (unsigned int) sigoutl, pd.fpr))
|
||||
{
|
||||
sigoutl = 0;
|
||||
diagnostic = RS_SSL_HANDSHAKE_DIAGNOSTIC_WRONG_SIGNATURE ;
|
||||
goto err;
|
||||
@ -1193,7 +1212,8 @@ bool AuthSSLimpl::AuthX509WithGPG(X509 *x509,uint32_t& diagnostic)
|
||||
RsPeerId peerIdstr ;
|
||||
getX509id(x509, peerIdstr) ;
|
||||
|
||||
std::cerr << "Verified signature of type " << sigtypestring << " on certificate " << peerIdstr << " using PGP key with fingerprint " << pd.fpr.toStdString() << std::endl;
|
||||
std::cerr << "Verified signature of type " << sigtypestring << " on certificate " << peerIdstr << " Version " << std::hex << certificate_version
|
||||
<< std::dec << " using PGP key with fingerprint " << pd.fpr.toStdString() << std::endl;
|
||||
}
|
||||
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
|
@ -611,47 +611,52 @@ bool getX509id(X509 *x509, RsPeerId& xid)
|
||||
X509_get0_signature(&signature,&algor,x509);
|
||||
#endif
|
||||
|
||||
#ifdef V07_NON_BACKWARD_COMPATIBLE_CHANGE_001
|
||||
// What: Computes the node id by performing a sha256 hash of the certificate's PGP signature, instead of simply picking up the last 20 bytes of it.
|
||||
//
|
||||
// Why: There is no real risk in forging a certificate with the same ID as the authentication is performed over the PGP signature of the certificate
|
||||
// which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to
|
||||
// create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software.
|
||||
//
|
||||
// Backward compat: makes connexions impossible with non patched peers, probably because the SSL id that is computed is not the same on both side,
|
||||
// and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was
|
||||
// submitted when making friends.
|
||||
//
|
||||
// Note: the advantage of basing the ID on the signature rather than the public key is not very clear, given that the signature is based on a hash
|
||||
// of the public key (and the rest of the certificate info).
|
||||
//
|
||||
uint32_t version_number = getX509RetroshareCertificateVersion(x509) ;
|
||||
|
||||
if(RsPeerId::SIZE_IN_BYTES > Sha256CheckSum::SIZE_IN_BYTES)
|
||||
return false ;
|
||||
|
||||
xid = RsPeerId(RsDirUtil::sha256sum(ASN1_STRING_data(const_cast<ASN1_BIT_STRING*>(signature)),ASN1_STRING_length(signature)).toByteArray()) ;
|
||||
#else
|
||||
int signlen = ASN1_STRING_length(signature);
|
||||
if (signlen < CERTSIGNLEN)
|
||||
if(version_number >= RS_CERTIFICATE_VERSION_NUMBER_06_0001)
|
||||
{
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "AuthSSL::getX509id() ERROR: Short Signature";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
// What: Computes the node id by performing a sha256 hash of the certificate's PGP signature, instead of simply picking up the last 20 bytes of it.
|
||||
//
|
||||
// Why: There is no real risk in forging a certificate with the same ID as the authentication is performed over the PGP signature of the certificate
|
||||
// which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to
|
||||
// create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software.
|
||||
//
|
||||
// Backward compat: makes connexions impossible with non patched peers, probably because the SSL id that is computed is not the same on both side,
|
||||
// and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was
|
||||
// submitted when making friends.
|
||||
//
|
||||
// Note: the advantage of basing the ID on the signature rather than the public key is not very clear, given that the signature is based on a hash
|
||||
// of the public key (and the rest of the certificate info).
|
||||
//
|
||||
|
||||
if(RsPeerId::SIZE_IN_BYTES > Sha256CheckSum::SIZE_IN_BYTES)
|
||||
return false ;
|
||||
|
||||
xid = RsPeerId(RsDirUtil::sha256sum(ASN1_STRING_data(const_cast<ASN1_BIT_STRING*>(signature)),ASN1_STRING_length(signature)).toByteArray()) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
int signlen = ASN1_STRING_length(signature);
|
||||
if (signlen < CERTSIGNLEN)
|
||||
{
|
||||
#ifdef AUTHSSL_DEBUG
|
||||
std::cerr << "AuthSSL::getX509id() ERROR: Short Signature";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// else copy in the first CERTSIGNLEN.
|
||||
unsigned char *signdata = ASN1_STRING_data(const_cast<ASN1_BIT_STRING*>(signature));
|
||||
// else copy in the first CERTSIGNLEN.
|
||||
unsigned char *signdata = ASN1_STRING_data(const_cast<ASN1_BIT_STRING*>(signature));
|
||||
|
||||
/* switched to the other end of the signature. for
|
||||
* more randomness
|
||||
*/
|
||||
/* switched to the other end of the signature. for
|
||||
* more randomness
|
||||
*/
|
||||
|
||||
#warning csoler 2017-02-19: This is cryptographically horrible. We should hash the entire signature here!
|
||||
|
||||
xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ;
|
||||
#endif
|
||||
xid = RsPeerId(&signdata[signlen - CERTSIGNLEN]) ;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -680,6 +685,34 @@ bool CheckX509Certificate(X509 */*x509*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t getX509SerialNumber(X509 *cert)
|
||||
{
|
||||
ASN1_INTEGER *serial = X509_get_serialNumber(cert);
|
||||
|
||||
BIGNUM *btmp = ASN1_INTEGER_to_BN(serial, NULL);
|
||||
|
||||
uint64_t res = BN_get_word(btmp) ;
|
||||
BN_free(btmp);
|
||||
|
||||
return res ;
|
||||
}
|
||||
|
||||
uint32_t getX509RetroshareCertificateVersion(X509 *cert)
|
||||
{
|
||||
// Because the serial number was totally random before being used to identity the handshake protocol, we check if we see known version strings. If not,
|
||||
// we assume v0.6-0000
|
||||
//
|
||||
// We compare the uint32_t into a uint64_t on purpose,to make sure that the highest bits are 0 and not random.
|
||||
|
||||
switch(getX509SerialNumber(cert))
|
||||
{
|
||||
case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0000): return RS_CERTIFICATE_VERSION_NUMBER_06_0000 ;
|
||||
case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_06_0001): return RS_CERTIFICATE_VERSION_NUMBER_06_0001 ;
|
||||
case uint64_t(RS_CERTIFICATE_VERSION_NUMBER_07_0001): return RS_CERTIFICATE_VERSION_NUMBER_07_0001 ;
|
||||
default:
|
||||
return RS_CERTIFICATE_VERSION_NUMBER_06_0000;
|
||||
}
|
||||
}
|
||||
|
||||
// Not dependent on sslroot. load, and detroys the X509 memory.
|
||||
int LoadCheckX509(const char *cert_file, RsPgpId& issuerName, std::string &location, RsPeerId &userId)
|
||||
|
@ -61,7 +61,15 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
|
||||
|
||||
#endif
|
||||
|
||||
// Certificates serial number is used to store the protocol version for the handshake. (*) means current version.
|
||||
//
|
||||
// 06_0000: < Nov.2017.
|
||||
// * 06_0001: > Nov 2017. SSL id is computed by hashing the entire signature of the cert instead of simply picking up the last bytes.
|
||||
// 07_0001: Signatures are performed using SHA256+RSA instead of SHA1+RSA
|
||||
|
||||
static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0000 = 0x00060000 ; // means version RS-0.6, certificate version 0. Default version before patch.
|
||||
static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_06_0001 = 0x00060001 ; // means version RS-0.6, certificate version 1.
|
||||
static const uint32_t RS_CERTIFICATE_VERSION_NUMBER_07_0001 = 0x00070001 ; // means version RS-0.7, certificate version 1.
|
||||
|
||||
X509_REQ *GenerateX509Req(
|
||||
std::string pkey_file, std::string passwd,
|
||||
@ -122,6 +130,9 @@ std::string getX509OrgString(X509_NAME *name);
|
||||
std::string getX509CountryString(X509_NAME *name);
|
||||
std::string getX509Info(X509 *cert);
|
||||
|
||||
uint64_t getX509SerialNumber(X509 *cert);
|
||||
uint32_t getX509RetroshareCertificateVersion(X509 *cert) ;
|
||||
|
||||
/********** SSL ERROR STUFF ******************************************/
|
||||
|
||||
int printSSLError(SSL *ssl, int retval, int err, unsigned long err2, std::string &out);
|
||||
|
@ -273,7 +273,7 @@ rs_chatserver {
|
||||
# which hashes the full SSL certificate (i.e. the full serialized CERT_INFO structure). However the possibility to
|
||||
# create two certificates with the same IDs is a problem, as it can be used to cause disturbance in the software.
|
||||
#
|
||||
# Backward compat: makes connexions impossible with non patched peers, probably because the SSL id that is computed is not the same on both side,
|
||||
# Backward compat: connexions impossible with non patched peers older than Nov 2017, probably because the SSL id that is computed is not the same on both side,
|
||||
# and in particular unpatched peers see a cerficate with ID different (because computed with the old method) than the ID that was
|
||||
# submitted when making friends.
|
||||
#
|
||||
@ -286,7 +286,7 @@ rs_chatserver {
|
||||
#
|
||||
# Why: Sha1 is likely to be prone to primary collisions anytime soon, so it is urgent to turn to a more secure solution.
|
||||
#
|
||||
# Backward compat: unpatched peers are able to verify signatures since openpgp-sdk already handle it.
|
||||
# Backward compat: unpatched peers after Nov 2017 are able to verify signatures since openpgp-sdk already handle it.
|
||||
#
|
||||
# V07_NON_BACKWARD_COMPATIBLE_CHANGE_003:
|
||||
#
|
||||
@ -294,7 +294,7 @@ rs_chatserver {
|
||||
#
|
||||
# Why: hasing twice is not per se a security issue, but it makes it harder to change the settings for hashing.
|
||||
#
|
||||
# Backward compat: patched peers cannot connect to non patched peers.
|
||||
# Backward compat: patched peers cannot connect to non patched peers older than Nov 2017.
|
||||
###########################################################################################################################################################
|
||||
|
||||
rs_v07_changes {
|
||||
|
Loading…
Reference in New Issue
Block a user