コード例 #1
0
void
PushSubscription::ToJSON(PushSubscriptionJSON& aJSON)
{
  aJSON.mEndpoint.Construct();
  aJSON.mEndpoint.Value() = mEndpoint;

  aJSON.mKeys.mP256dh.Construct();
  nsresult rv = Base64URLEncode(mRawP256dhKey.Length(),
                                mRawP256dhKey.Elements(),
                                aJSON.mKeys.mP256dh.Value());
  Unused << NS_WARN_IF(NS_FAILED(rv));

  aJSON.mKeys.mAuth.Construct();
  rv = Base64URLEncode(mAuthSecret.Length(), mAuthSecret.Elements(),
                       aJSON.mKeys.mAuth.Value());
  Unused << NS_WARN_IF(NS_FAILED(rv));
}
コード例 #2
0
nsresult
CryptoBuffer::ToJwkBase64(nsString& aBase64) const
{
  // Shortcut for the empty octet string
  if (Length() == 0) {
    aBase64.Truncate();
    return NS_OK;
  }

  nsAutoCString base64;
  nsresult rv = Base64URLEncode(Length(), Elements(),
                                Base64URLEncodePaddingPolicy::Omit, base64);
  NS_ENSURE_SUCCESS(rv, rv);

  CopyASCIItoUTF16(base64, aBase64);
  return NS_OK;
}
コード例 #3
0
// A U2F Sign operation creates a signature over the "param" arguments (plus
// some other stuff) using the private key indicated in the key handle argument.
//
// The format of the signed data is as follows:
//
//  32    Application parameter
//  1     User presence (0x01)
//  4     Counter
//  32    Challenge parameter
//
// The format of the signature data is as follows:
//
//  1     User presence
//  4     Counter
//  *     Signature
//
nsresult
U2FSoftTokenManager::Sign(nsTArray<uint8_t>& aApplication,
                          nsTArray<uint8_t>& aChallenge,
                          nsTArray<uint8_t>& aKeyHandle,
                          nsTArray<uint8_t>& aSignature)
{
  nsNSSShutDownPreventionLock locker;
  if (NS_WARN_IF(isAlreadyShutDown())) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  MOZ_ASSERT(mInitialized);
  if (NS_WARN_IF(!mInitialized)) {
    nsresult rv = Init();
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return rv;
    }
  }

  MOZ_ASSERT(mWrappingKey);

  UniquePK11SlotInfo slot(PK11_GetInternalSlot());
  MOZ_ASSERT(slot.get());

  if (NS_WARN_IF((aChallenge.Length() != kParamLen) || (aApplication.Length() != kParamLen))) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
            ("Parameter lengths are wrong! challenge=%d app=%d expected=%d",
             (uint32_t)aChallenge.Length(), (uint32_t)aApplication.Length(), kParamLen));

    return NS_ERROR_ILLEGAL_VALUE;
  }

  // Decode the key handle
  UniqueSECKEYPrivateKey privKey = PrivateKeyFromKeyHandle(slot, mWrappingKey,
                                                           aKeyHandle.Elements(),
                                                           aKeyHandle.Length(),
                                                           aApplication.Elements(),
                                                           aApplication.Length(),
                                                           locker);
  if (NS_WARN_IF(!privKey.get())) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning, ("Couldn't get the priv key!"));
    return NS_ERROR_FAILURE;
  }

  // Increment the counter and turn it into a SECItem
  mCounter += 1;
  ScopedAutoSECItem counterItem(4);
  counterItem.data[0] = (mCounter >> 24) & 0xFF;
  counterItem.data[1] = (mCounter >> 16) & 0xFF;
  counterItem.data[2] = (mCounter >>  8) & 0xFF;
  counterItem.data[3] = (mCounter >>  0) & 0xFF;
  uint32_t counter = mCounter;
  AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction(
                                           [counter] () {
                                             MOZ_ASSERT(NS_IsMainThread());
                                             Preferences::SetUint(PREF_U2F_NSSTOKEN_COUNTER, counter);
                                           }));

  // Compute the signature
  mozilla::dom::CryptoBuffer signedDataBuf;
  if (NS_WARN_IF(!signedDataBuf.SetCapacity(1 + 4 + (2 * kParamLen), mozilla::fallible))) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // It's OK to ignore the return values here because we're writing into
  // pre-allocated space
  signedDataBuf.AppendElements(aApplication.Elements(), aApplication.Length(),
                               mozilla::fallible);
  signedDataBuf.AppendElement(0x01, mozilla::fallible);
  signedDataBuf.AppendSECItem(counterItem);
  signedDataBuf.AppendElements(aChallenge.Elements(), aChallenge.Length(),
                               mozilla::fallible);

  if (MOZ_LOG_TEST(gNSSTokenLog, LogLevel::Debug)) {
    nsAutoCString base64;
    nsresult rv = Base64URLEncode(signedDataBuf.Length(), signedDataBuf.Elements(),
                                  Base64URLEncodePaddingPolicy::Omit, base64);
    if (NS_WARN_IF(NS_FAILED(rv))) {
      return NS_ERROR_FAILURE;
    }

    MOZ_LOG(gNSSTokenLog, LogLevel::Debug,
            ("U2F Token signing bytes (base64): %s", base64.get()));
  }

  ScopedAutoSECItem signatureItem;
  SECStatus srv = SEC_SignData(&signatureItem, signedDataBuf.Elements(),
                               signedDataBuf.Length(), privKey.get(),
                               SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE);
  if (NS_WARN_IF(srv != SECSuccess)) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
            ("Signature failure: %d", PORT_GetError()));
    return NS_ERROR_FAILURE;
  }

  // Assemble the signature data into a buffer for return
  mozilla::dom::CryptoBuffer signatureBuf;
  if (NS_WARN_IF(!signatureBuf.SetCapacity(1 + counterItem.len + signatureItem.len,
                                           mozilla::fallible))) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // It's OK to ignore the return values here because we're writing into
  // pre-allocated space
  signatureBuf.AppendElement(0x01, mozilla::fallible);
  signatureBuf.AppendSECItem(counterItem);
  signatureBuf.AppendSECItem(signatureItem);

  aSignature = signatureBuf;
  return NS_OK;
}