Пример #1
0
void StoreSecretAddress(Point address)
{
    Point offset_point = depositdata[address]["offset_point"];
    Point secret_address = address + offset_point;
    uint160 secret_address_hash = KeyHash(secret_address);
    uint160 full_secret_address_hash = FullKeyHash(secret_address);
    keydata[secret_address_hash]["pubkey"] = secret_address;
    keydata[full_secret_address_hash]["pubkey"] = secret_address;
    depositdata[secret_address_hash]["offset_point"] = offset_point;
    depositdata[secret_address_hash]["confirmed"] = true;
    depositdata[secret_address_hash]["address"] = secret_address;
    depositdata[full_secret_address_hash]["offset_point"] = offset_point;
    depositdata[full_secret_address_hash]["confirmed"] = true;
    depositdata[full_secret_address_hash]["address"] = secret_address;
    depositdata[secret_address]["public_address"] = address;
}
Пример #2
0
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
// "The hash shall be calculated over the value (excluding tag and length) of
// the subject public key field in the issuer's certificate."
//
// From http://tools.ietf.org/html/rfc6960#appendix-B.1:
// KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
//                          -- (i.e., the SHA-1 hash of the value of the
//                          -- BIT STRING subjectPublicKey [excluding
//                          -- the tag, length, and number of unused
//                          -- bits] in the responder's certificate)
static Result
MatchKeyHash(TrustDomain& trustDomain, const SECItem& keyHash,
             const SECItem& subjectPublicKeyInfo, /*out*/ bool& match)
{
  if (keyHash.len != TrustDomain::DIGEST_LENGTH)  {
    return Fail(RecoverableError, SEC_ERROR_OCSP_MALFORMED_RESPONSE);
  }
  static uint8_t hashBuf[TrustDomain::DIGEST_LENGTH];
  Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
                      sizeof hashBuf);
  if (rv != Success) {
    return rv;
  }
  match = !memcmp(hashBuf, keyHash.data, keyHash.len);
  return Success;
}
Пример #3
0
// From http://tools.ietf.org/html/rfc6960#section-4.1.1:
// "The hash shall be calculated over the value (excluding tag and length) of
// the subject public key field in the issuer's certificate."
//
// From http://tools.ietf.org/html/rfc6960#appendix-B.1:
// KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
//                          -- (i.e., the SHA-1 hash of the value of the
//                          -- BIT STRING subjectPublicKey [excluding
//                          -- the tag, length, and number of unused
//                          -- bits] in the responder's certificate)
static Result
MatchKeyHash(TrustDomain& trustDomain, Input keyHash,
             const Input subjectPublicKeyInfo, /*out*/ bool& match)
{
  if (keyHash.GetLength() != TrustDomain::DIGEST_LENGTH)  {
    return Result::ERROR_OCSP_MALFORMED_RESPONSE;
  }
  static uint8_t hashBuf[TrustDomain::DIGEST_LENGTH];
  Result rv = KeyHash(trustDomain, subjectPublicKeyInfo, hashBuf,
                      sizeof hashBuf);
  if (rv != Success) {
    return rv;
  }
  Input computed(hashBuf);
  match = InputsAreEqual(computed, keyHash);
  return Success;
}
Пример #4
0
void DoScheduledPostDisclosureCheck(uint160 request_hash)
{
    log_ << "DoScheduledPostDisclosureCheck: " << request_hash << "\n";
    if (depositdata[request_hash]["cancelled"])
    {
        log_ << request_hash << " has been cancelled\n";
        return;
    }
    Point address = depositdata[request_hash]["address"];
    log_ << "deposit address created: " << address << "\n";
    uint160 address_hash = KeyHash(address);
    depositdata[address_hash]["address"] = address;
    log_ << "address for " << address_hash << " is " << address << "\n";
    log_ << "keyhash_ is " << FullKeyHash(address) << "\n";
    DepositAddressRequest request = msgdata[request_hash]["deposit_request"];
    string address_string;
    if (request.currency_code != FLX)
    {
        Currency currency = flexnode.currencies[request.currency_code];
        address_string = currency.crypto.PubKeyToAddress(address);
    }
    else
    {
        address_string = FlexAddressFromPubKey(address);
    }
    log_ << "final address is " << address_string << "\n";
    CBitcoinAddress address_(address_string);
    CKeyID keyid;
    address_.GetKeyID(keyid);
    vch_t keydata_(BEGIN(keyid), END(keyid));
    log_ << "keydata is " << keydata_ << "\n";
    uint160 hash(keydata_);
    log_ << "hash is " << hash << "\n";
    depositdata[hash]["address"] = address;
    CKeyID keyID(hash);
    log_ << "btc address is " << CBitcoinAddress(keyID).ToString() << "\n";
    depositdata[address_hash]["confirmed"] = true;
    depositdata[FullKeyHash(address)]["confirmed"] = true;

    if (depositdata[address].HasProperty("offset_point"))
    {
        StoreSecretAddress(address);
    }
}
Пример #5
0
Result
CreateEncodedOCSPRequest(TrustDomain& trustDomain, const struct CertID& certID,
                         /*out*/ uint8_t (&out)[OCSP_REQUEST_MAX_LENGTH],
                         /*out*/ size_t& outLen)
{
  // We do not add any extensions to the request.

  // RFC 6960 says "An OCSP client MAY wish to specify the kinds of response
  // types it understands. To do so, it SHOULD use an extension with the OID
  // id-pkix-ocsp-response." This use of MAY and SHOULD is unclear. MSIE11
  // on Windows 8.1 does not include any extensions, whereas NSS has always
  // included the id-pkix-ocsp-response extension. Avoiding the sending the
  // extension is better for OCSP GET because it makes the request smaller,
  // and thus more likely to fit within the 255 byte limit for OCSP GET that
  // is specified in RFC 5019 Section 5.

  // Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.

  // Since we don't know whether the OCSP responder supports anything other
  // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
  // issuerKeyHash.
  static const uint8_t hashAlgorithm[11] = {
    0x30, 0x09,                               // SEQUENCE
    0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, //   OBJECT IDENTIFIER id-sha1
    0x05, 0x00,                               //   NULL
  };
  static const uint8_t hashLen = TrustDomain::DIGEST_LENGTH;

  static const unsigned int totalLenWithoutSerialNumberData
    = 2                             // OCSPRequest
    + 2                             //   tbsRequest
    + 2                             //     requestList
    + 2                             //       Request
    + 2                             //         reqCert (CertID)
    + sizeof(hashAlgorithm)         //           hashAlgorithm
    + 2 + hashLen                   //           issuerNameHash
    + 2 + hashLen                   //           issuerKeyHash
    + 2;                            //           serialNumber (header)

  // The only way we could have a request this large is if the serialNumber was
  // ridiculously and unreasonably large. RFC 5280 says "Conforming CAs MUST
  // NOT use serialNumber values longer than 20 octets." With this restriction,
  // we allow for some amount of non-conformance with that requirement while
  // still ensuring we can encode the length values in the ASN.1 TLV structures
  // in a single byte.
  static_assert(totalLenWithoutSerialNumberData < OCSP_REQUEST_MAX_LENGTH,
                "totalLenWithoutSerialNumberData too big");
  if (certID.serialNumber.GetLength() >
        OCSP_REQUEST_MAX_LENGTH - totalLenWithoutSerialNumberData) {
    return Result::ERROR_BAD_DER;
  }

  outLen = totalLenWithoutSerialNumberData + certID.serialNumber.GetLength();

  uint8_t totalLen = static_cast<uint8_t>(outLen);

  uint8_t* d = out;
  *d++ = 0x30; *d++ = totalLen - 2u;  // OCSPRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 4u;  //   tbsRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 6u;  //     requestList (SEQUENCE OF)
  *d++ = 0x30; *d++ = totalLen - 8u;  //       Request (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 10u; //         reqCert (CertID SEQUENCE)

  // reqCert.hashAlgorithm
  for (size_t i = 0; i < sizeof(hashAlgorithm); ++i) {
    *d++ = hashAlgorithm[i];
  }

  // reqCert.issuerNameHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  Result rv = trustDomain.DigestBuf(certID.issuer, d, hashLen);
  if (rv != Success) {
    return rv;
  }
  d += hashLen;

  // reqCert.issuerKeyHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  rv = KeyHash(trustDomain, certID.issuerSubjectPublicKeyInfo, d, hashLen);
  if (rv != Success) {
    return rv;
  }
  d += hashLen;

  // reqCert.serialNumber (INTEGER)
  *d++ = 0x02; // INTEGER
  *d++ = static_cast<uint8_t>(certID.serialNumber.GetLength());
  Reader serialNumber(certID.serialNumber);
  do {
    rv = serialNumber.Read(*d);
    if (rv != Success) {
      return rv;
    }
    ++d;
  } while (!serialNumber.AtEnd());

  assert(d == out + totalLen);

  return Success;
}
Пример #6
0
SECItem*
CreateEncodedOCSPRequest(TrustDomain& trustDomain, PLArenaPool* arena,
                         const struct CertID& certID)
{
  if (!arena) {
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return nullptr;
  }

  // We do not add any extensions to the request.

  // RFC 6960 says "An OCSP client MAY wish to specify the kinds of response
  // types it understands. To do so, it SHOULD use an extension with the OID
  // id-pkix-ocsp-response." This use of MAY and SHOULD is unclear. MSIE11
  // on Windows 8.1 does not include any extensions, whereas NSS has always
  // included the id-pkix-ocsp-response extension. Avoiding the sending the
  // extension is better for OCSP GET because it makes the request smaller,
  // and thus more likely to fit within the 255 byte limit for OCSP GET that
  // is specified in RFC 5019 Section 5.

  // Bug 966856: Add the id-pkix-ocsp-pref-sig-algs extension.

  // Since we don't know whether the OCSP responder supports anything other
  // than SHA-1, we have no choice but to use SHA-1 for issuerNameHash and
  // issuerKeyHash.
  static const uint8_t hashAlgorithm[11] = {
    0x30, 0x09,                               // SEQUENCE
    0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, //   OBJECT IDENTIFIER id-sha1
    0x05, 0x00,                               //   NULL
  };
  static const uint8_t hashLen = TrustDomain::DIGEST_LENGTH;

  static const unsigned int totalLenWithoutSerialNumberData
    = 2                             // OCSPRequest
    + 2                             //   tbsRequest
    + 2                             //     requestList
    + 2                             //       Request
    + 2                             //         reqCert (CertID)
    + PR_ARRAY_SIZE(hashAlgorithm)  //           hashAlgorithm
    + 2 + hashLen                   //           issuerNameHash
    + 2 + hashLen                   //           issuerKeyHash
    + 2;                            //           serialNumber (header)

  // The only way we could have a request this large is if the serialNumber was
  // ridiculously and unreasonably large. RFC 5280 says "Conforming CAs MUST
  // NOT use serialNumber values longer than 20 octets." With this restriction,
  // we allow for some amount of non-conformance with that requirement while
  // still ensuring we can encode the length values in the ASN.1 TLV structures
  // in a single byte.
  if (certID.serialNumber.len > 127u - totalLenWithoutSerialNumberData) {
    PR_SetError(SEC_ERROR_BAD_DATA, 0);
    return nullptr;
  }

  uint8_t totalLen = static_cast<uint8_t>(totalLenWithoutSerialNumberData +
    certID.serialNumber.len);

  SECItem* encodedRequest = SECITEM_AllocItem(arena, nullptr, totalLen);
  if (!encodedRequest) {
    return nullptr;
  }

  uint8_t* d = encodedRequest->data;
  *d++ = 0x30; *d++ = totalLen - 2u;  // OCSPRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 4u;  //   tbsRequest (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 6u;  //     requestList (SEQUENCE OF)
  *d++ = 0x30; *d++ = totalLen - 8u;  //       Request (SEQUENCE)
  *d++ = 0x30; *d++ = totalLen - 10u; //         reqCert (CertID SEQUENCE)

  // reqCert.hashAlgorithm
  for (size_t i = 0; i < PR_ARRAY_SIZE(hashAlgorithm); ++i) {
    *d++ = hashAlgorithm[i];
  }

  // reqCert.issuerNameHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  if (trustDomain.DigestBuf(certID.issuer, d, hashLen) != SECSuccess) {
    return nullptr;
  }
  d += hashLen;

  // reqCert.issuerKeyHash (OCTET STRING)
  *d++ = 0x04;
  *d++ = hashLen;
  if (KeyHash(trustDomain, certID.issuerSubjectPublicKeyInfo, d, hashLen)
        != Success) {
    return nullptr;
  }
  d += hashLen;

  // reqCert.serialNumber (INTEGER)
  *d++ = 0x02; // INTEGER
  *d++ = static_cast<uint8_t>(certID.serialNumber.len);
  for (size_t i = 0; i < certID.serialNumber.len; ++i) {
    *d++ = certID.serialNumber.data[i];
  }

  PR_ASSERT(d == encodedRequest->data + totalLen);

  return encodedRequest;
}