mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 19:07:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
214
media/mtransport/dtlsidentity.cpp
Normal file
214
media/mtransport/dtlsidentity.cpp
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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 "dtlsidentity.h"
|
||||
|
||||
#include "cert.h"
|
||||
#include "cryptohi.h"
|
||||
#include "keyhi.h"
|
||||
#include "nsError.h"
|
||||
#include "pk11pub.h"
|
||||
#include "sechash.h"
|
||||
#include "ssl.h"
|
||||
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
RefPtr<DtlsIdentity> DtlsIdentity::Generate() {
|
||||
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
|
||||
if (!slot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t random_name[16];
|
||||
|
||||
SECStatus rv = PK11_GenerateRandomOnSlot(slot, random_name,
|
||||
sizeof(random_name));
|
||||
if (rv != SECSuccess)
|
||||
return nullptr;
|
||||
|
||||
std::string name;
|
||||
char chunk[3];
|
||||
for (size_t i = 0; i < sizeof(random_name); ++i) {
|
||||
SprintfLiteral(chunk, "%.2x", random_name[i]);
|
||||
name += chunk;
|
||||
}
|
||||
|
||||
std::string subject_name_string = "CN=" + name;
|
||||
ScopedCERTName subject_name(CERT_AsciiToName(subject_name_string.c_str()));
|
||||
if (!subject_name) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned char paramBuf[12]; // OIDs are small
|
||||
SECItem ecdsaParams = { siBuffer, paramBuf, sizeof(paramBuf) };
|
||||
SECOidData* oidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
|
||||
if (!oidData || (oidData->oid.len > (sizeof(paramBuf) - 2))) {
|
||||
return nullptr;
|
||||
}
|
||||
ecdsaParams.data[0] = SEC_ASN1_OBJECT_ID;
|
||||
ecdsaParams.data[1] = oidData->oid.len;
|
||||
memcpy(ecdsaParams.data + 2, oidData->oid.data, oidData->oid.len);
|
||||
ecdsaParams.len = oidData->oid.len + 2;
|
||||
|
||||
ScopedSECKEYPrivateKey private_key;
|
||||
ScopedSECKEYPublicKey public_key;
|
||||
SECKEYPublicKey *pubkey;
|
||||
|
||||
private_key =
|
||||
PK11_GenerateKeyPair(slot,
|
||||
CKM_EC_KEY_PAIR_GEN, &ecdsaParams, &pubkey,
|
||||
PR_FALSE, PR_TRUE, nullptr);
|
||||
if (private_key == nullptr)
|
||||
return nullptr;
|
||||
public_key = pubkey;
|
||||
|
||||
ScopedCERTSubjectPublicKeyInfo spki(
|
||||
SECKEY_CreateSubjectPublicKeyInfo(pubkey));
|
||||
if (!spki) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedCERTCertificateRequest certreq(
|
||||
CERT_CreateCertificateRequest(subject_name, spki, nullptr));
|
||||
if (!certreq) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// From 1 day before todayto 30 days after.
|
||||
// This is a sort of arbitrary range designed to be valid
|
||||
// now with some slack in case the other side expects
|
||||
// some before expiry.
|
||||
//
|
||||
// Note: explicit casts necessary to avoid
|
||||
// warning C4307: '*' : integral constant overflow
|
||||
static const PRTime oneDay = PRTime(PR_USEC_PER_SEC)
|
||||
* PRTime(60) // sec
|
||||
* PRTime(60) // min
|
||||
* PRTime(24); // hours
|
||||
PRTime now = PR_Now();
|
||||
PRTime notBefore = now - oneDay;
|
||||
PRTime notAfter = now + (PRTime(30) * oneDay);
|
||||
|
||||
ScopedCERTValidity validity(CERT_CreateValidity(notBefore, notAfter));
|
||||
if (!validity) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned long serial;
|
||||
// Note: This serial in principle could collide, but it's unlikely
|
||||
rv = PK11_GenerateRandomOnSlot(slot,
|
||||
reinterpret_cast<unsigned char *>(&serial),
|
||||
sizeof(serial));
|
||||
if (rv != SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedCERTCertificate certificate(
|
||||
CERT_CreateCertificate(serial, subject_name, validity, certreq));
|
||||
if (!certificate) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PLArenaPool *arena = certificate->arena;
|
||||
|
||||
rv = SECOID_SetAlgorithmID(arena, &certificate->signature,
|
||||
SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, 0);
|
||||
if (rv != SECSuccess)
|
||||
return nullptr;
|
||||
|
||||
// Set version to X509v3.
|
||||
*(certificate->version.data) = SEC_CERTIFICATE_VERSION_3;
|
||||
certificate->version.len = 1;
|
||||
|
||||
SECItem innerDER;
|
||||
innerDER.len = 0;
|
||||
innerDER.data = nullptr;
|
||||
|
||||
if (!SEC_ASN1EncodeItem(arena, &innerDER, certificate,
|
||||
SEC_ASN1_GET(CERT_CertificateTemplate))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SECItem *signedCert = PORT_ArenaZNew(arena, SECItem);
|
||||
if (!signedCert) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = SEC_DerSignData(arena, signedCert, innerDER.data, innerDER.len,
|
||||
private_key,
|
||||
SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
|
||||
if (rv != SECSuccess) {
|
||||
return nullptr;
|
||||
}
|
||||
certificate->derCert = *signedCert;
|
||||
|
||||
RefPtr<DtlsIdentity> identity =
|
||||
new DtlsIdentity(private_key.forget(), certificate.forget(), ssl_kea_ecdh);
|
||||
return identity.forget();
|
||||
}
|
||||
|
||||
const std::string DtlsIdentity::DEFAULT_HASH_ALGORITHM = "sha-256";
|
||||
|
||||
nsresult DtlsIdentity::ComputeFingerprint(const std::string algorithm,
|
||||
uint8_t *digest,
|
||||
size_t size,
|
||||
size_t *digest_length) const {
|
||||
const UniqueCERTCertificate& c = cert();
|
||||
MOZ_ASSERT(c);
|
||||
|
||||
return ComputeFingerprint(c, algorithm, digest, size, digest_length);
|
||||
}
|
||||
|
||||
nsresult DtlsIdentity::ComputeFingerprint(const UniqueCERTCertificate& cert,
|
||||
const std::string algorithm,
|
||||
uint8_t *digest,
|
||||
size_t size,
|
||||
size_t *digest_length) {
|
||||
MOZ_ASSERT(cert);
|
||||
|
||||
HASH_HashType ht;
|
||||
|
||||
if (algorithm == "sha-1") {
|
||||
ht = HASH_AlgSHA1;
|
||||
} else if (algorithm == "sha-224") {
|
||||
ht = HASH_AlgSHA224;
|
||||
} else if (algorithm == "sha-256") {
|
||||
ht = HASH_AlgSHA256;
|
||||
} else if (algorithm == "sha-384") {
|
||||
ht = HASH_AlgSHA384;
|
||||
} else if (algorithm == "sha-512") {
|
||||
ht = HASH_AlgSHA512;
|
||||
} else {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
const SECHashObject *ho = HASH_GetHashObject(ht);
|
||||
MOZ_ASSERT(ho);
|
||||
if (!ho) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(ho->length >= 20); // Double check
|
||||
|
||||
if (size < ho->length) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
SECStatus rv = HASH_HashBuf(ho->type, digest,
|
||||
cert->derCert.data,
|
||||
cert->derCert.len);
|
||||
if (rv != SECSuccess) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*digest_length = ho->length;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // close namespace
|
||||
Loading…
Add table
Add a link
Reference in a new issue