Bug 946348 - Refactor fingerprint handling. r=abr

This commit is contained in:
Martin Thomson 2014-01-02 10:50:14 -05:00
parent fbf5f9b668
commit da6e334879
5 changed files with 101 additions and 58 deletions

View File

@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <iomanip>
#include "logging.h"
#include "nspr.h"
#include "cryptohi.h"
@ -25,6 +26,9 @@ DtlsIdentity::~DtlsIdentity() {
CERT_DestroyCertificate(cert_);
}
const std::string DtlsIdentity::DEFAULT_HASH_ALGORITHM = "sha-256";
const size_t DtlsIdentity::HASH_ALGORITHM_MAX_LENGTH = 64;
TemporaryRef<DtlsIdentity> DtlsIdentity::Generate() {
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
@ -86,7 +90,7 @@ TemporaryRef<DtlsIdentity> DtlsIdentity::Generate() {
// now with some slack in case the other side expects
// some before expiry.
//
// Note: explicit casts necessary to avoid
// Note: explicit casts necessary to avoid
// warning C4307: '*' : integral constant overflow
static const PRTime oneDay = PRTime(PR_USEC_PER_SEC)
* PRTime(60) // sec
@ -206,8 +210,29 @@ nsresult DtlsIdentity::ComputeFingerprint(const CERTCertificate *cert,
return NS_OK;
}
// Format the fingerprint in RFC 4572 Section 5 format, colons and
// all.
// Format the fingerprint in RFC 4572 Section 5 attribute format, including both
// the hash name and the fingerprint, colons and all.
// returns an empty string if there is a problem
std::string DtlsIdentity::GetFormattedFingerprint(const std::string &algorithm) {
unsigned char digest[HASH_ALGORITHM_MAX_LENGTH];
size_t digest_length;
nsresult res = this->ComputeFingerprint(algorithm,
digest,
sizeof(digest),
&digest_length);
if (NS_FAILED(res)) {
MOZ_MTLOG(ML_ERROR, "Unable to compute " << algorithm
<< " hash for identity: nsresult = 0x"
<< std::hex << std::uppercase
<< static_cast<uint32_t>(res)
<< std::nouppercase << std::dec);
return "";
}
return algorithm + " " + this->FormatFingerprint(digest, digest_length);
}
std::string DtlsIdentity::FormatFingerprint(const unsigned char *digest,
std::size_t size) {
std::string str("");
@ -215,7 +240,7 @@ std::string DtlsIdentity::FormatFingerprint(const unsigned char *digest,
for (std::size_t i=0; i < size; i++) {
PR_snprintf(group, sizeof(group), "%.2X", digest[i]);
if (i != 0){
if (i != 0) {
str += ":";
}
str += group;

View File

@ -32,6 +32,8 @@ class DtlsIdentity {
CERTCertificate *cert() { return cert_; }
SECKEYPrivateKey *privkey() { return privkey_; }
std::string GetFormattedFingerprint(const std::string &algorithm = DEFAULT_HASH_ALGORITHM);
nsresult ComputeFingerprint(const std::string algorithm,
unsigned char *digest,
std::size_t size,
@ -43,8 +45,6 @@ class DtlsIdentity {
std::size_t size,
std::size_t *digest_length);
static std::string FormatFingerprint(const unsigned char *digest,
std::size_t size);
static nsresult ParseFingerprint(const std::string fp,
unsigned char *digest,
size_t size, size_t *length);
@ -56,6 +56,12 @@ class DtlsIdentity {
: privkey_(privkey), cert_(cert) {}
DISALLOW_COPY_ASSIGN(DtlsIdentity);
static const std::string DEFAULT_HASH_ALGORITHM;
static const size_t HASH_ALGORITHM_MAX_LENGTH;
std::string FormatFingerprint(const unsigned char *digest,
std::size_t size);
ScopedSECKEYPrivateKey privkey_;
CERTCertificate *cert_; // TODO: Using a smart pointer here causes link
// errors.

View File

@ -1178,10 +1178,10 @@ short vcmAddRemoteStreamHint(
* Get DTLS key data
*
* @param[in] peerconnection - the peerconnection in use
* @param[out] digest_algp - the digest algorithm e.g. 'SHA-1'
* @param[in] max_digest_alg_len - length of string
* @param[out] digest_algp - the digest algorithm e.g. 'sha-256'
* @param[in] max_digest_alg_len - available length of string
* @param[out] digestp - the digest string
* @param[in] max_digest_len - length of string
* @param[in] max_digest_len - available length of string
*
* Returns: zero(0) for success; otherwise, ERROR for failure
*/
@ -1197,33 +1197,10 @@ static short vcmGetDtlsIdentity_m(const char *peerconnection,
sipcc::PeerConnectionWrapper pc(peerconnection);
ENSURE_PC(pc, VCM_ERROR);
unsigned char digest[TransportLayerDtls::kMaxDigestLength];
size_t digest_len;
mozilla::RefPtr<DtlsIdentity> id = pc.impl()->GetIdentity();
if (!id) {
return VCM_ERROR;
}
nsresult res = id->ComputeFingerprint("sha-256", digest, sizeof(digest),
&digest_len);
if (!NS_SUCCEEDED(res)) {
CSFLogError( logTag, "%s: Could not compute identity fingerprint", __FUNCTION__);
return VCM_ERROR;
}
// digest_len should be 32 for SHA-256
PR_ASSERT(digest_len == 32);
std::string fingerprint_txt = DtlsIdentity::FormatFingerprint(digest, digest_len);
if (max_digest_len <= fingerprint_txt.size()) {
CSFLogError( logTag, "%s: Formatted digest will not fit in provided buffer",
__FUNCTION__);
return VCM_ERROR;
}
sstrncpy(digest_algp, "sha-256", max_digest_alg_len);
sstrncpy(digestp, fingerprint_txt.c_str(), max_digest_len);
std::string algorithm = pc.impl()->GetFingerprintAlgorithm();
sstrncpy(digest_algp, algorithm.c_str(), max_digest_alg_len);
std::string value = pc.impl()->GetFingerprintHexValue();
sstrncpy(digestp, value.c_str(), max_digest_len);
return 0;
}

View File

@ -789,26 +789,9 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
return NS_ERROR_FAILURE;
}
// Set the fingerprint. Right now assume we only have one
// DTLS identity
unsigned char fingerprint[DTLS_FINGERPRINT_LENGTH];
size_t fingerprint_length;
res = mIdentity->ComputeFingerprint("sha-256",
fingerprint,
sizeof(fingerprint),
&fingerprint_length);
if (NS_FAILED(res)) {
CSFLogError(logTag, "%s: ComputeFingerprint failed: %u",
__FUNCTION__, static_cast<uint32_t>(res));
return res;
}
mFingerprint = "sha-256 " + mIdentity->FormatFingerprint(fingerprint,
fingerprint_length);
if (NS_FAILED(res)) {
CSFLogError(logTag, "%s: do_GetService failed: %u",
__FUNCTION__, static_cast<uint32_t>(res));
mFingerprint = mIdentity->GetFormattedFingerprint();
if (mFingerprint.empty()) {
CSFLogError(logTag, "%s: unable to get fingerprint", __FUNCTION__);
return res;
}
@ -816,11 +799,56 @@ PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
}
RefPtr<DtlsIdentity> const
PeerConnectionImpl::GetIdentity() {
PeerConnectionImpl::GetIdentity() const
{
PC_AUTO_ENTER_API_CALL_NO_CHECK();
return mIdentity;
}
std::string
PeerConnectionImpl::GetFingerprint() const
{
PC_AUTO_ENTER_API_CALL_NO_CHECK();
return mFingerprint;
}
NS_IMETHODIMP
PeerConnectionImpl::FingerprintSplitHelper(std::string& fingerprint,
size_t& spaceIdx) const
{
fingerprint = GetFingerprint();
spaceIdx = fingerprint.find_first_of(' ');
if (spaceIdx == std::string::npos) {
CSFLogError(logTag, "%s: fingerprint is messed up: %s",
__FUNCTION__, fingerprint.c_str());
return NS_ERROR_FAILURE;
}
return NS_OK;
}
std::string
PeerConnectionImpl::GetFingerprintAlgorithm() const
{
std::string fp;
size_t spc;
if (NS_SUCCEEDED(FingerprintSplitHelper(fp, spc))) {
return fp.substr(0, spc);
}
return "";
}
std::string
PeerConnectionImpl::GetFingerprintHexValue() const
{
std::string fp;
size_t spc;
if (NS_SUCCEEDED(FingerprintSplitHelper(fp, spc))) {
return fp.substr(spc + 1);
}
return "";
}
nsresult
PeerConnectionImpl::CreateFakeMediaStream(uint32_t aHint, nsIDOMMediaStream** aRetval)
{

View File

@ -246,7 +246,10 @@ public:
}
// Get the DTLS identity
mozilla::RefPtr<DtlsIdentity> const GetIdentity();
mozilla::RefPtr<DtlsIdentity> const GetIdentity() const;
std::string GetFingerprint() const;
std::string GetFingerprintAlgorithm() const;
std::string GetFingerprintHexValue() const;
// Create a fake media stream
nsresult CreateFakeMediaStream(uint32_t hint, nsIDOMMediaStream** retval);
@ -532,6 +535,10 @@ private:
nsresult IceGatheringStateChange_m(
mozilla::dom::PCImplIceGatheringState aState);
NS_IMETHOD FingerprintSplitHelper(
std::string& fingerprint, size_t& spaceIdx) const;
#ifdef MOZILLA_INTERNAL_API
// Fills in an RTCStatsReportInternal. Must be run on STS.
void GetStats_s(