Ejemplo n.º 1
0
SECKEYPublicKey*
CreateECPublicKey(const SECItem* aKeyData, const nsString& aNamedCurve)
{
  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  if (!arena) {
    return nullptr;
  }

  SECKEYPublicKey* key = PORT_ArenaZNew(arena, SECKEYPublicKey);
  if (!key) {
    return nullptr;
  }

  key->keyType = ecKey;
  key->pkcs11Slot = nullptr;
  key->pkcs11ID = CK_INVALID_HANDLE;

  // Create curve parameters.
  SECItem* params = CreateECParamsForCurve(aNamedCurve, arena);
  if (!params) {
    return nullptr;
  }
  key->u.ec.DEREncodedParams = *params;

  // Set public point.
  key->u.ec.publicValue = *aKeyData;

  // Ensure the given point is on the curve.
  if (!CryptoKey::PublicKeyValid(key)) {
    return nullptr;
  }

  return SECKEY_CopyPublicKey(key);
}
static nsresult
GenEcKeypair(const UniquePK11SlotInfo& aSlot,
             /*out*/ UniqueSECKEYPrivateKey& aPrivKey,
             /*out*/ UniqueSECKEYPublicKey& aPubKey,
             const nsNSSShutDownPreventionLock&)
{
  MOZ_ASSERT(aSlot);
  if (NS_WARN_IF(!aSlot)) {
    return NS_ERROR_INVALID_ARG;
  }

  UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  if (NS_WARN_IF(!arena)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // Set the curve parameters; keyParams belongs to the arena memory space
  SECItem* keyParams = CreateECParamsForCurve(kEcAlgorithm, arena.get());
  if (NS_WARN_IF(!keyParams)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  // Generate a key pair
  CK_MECHANISM_TYPE mechanism = CKM_EC_KEY_PAIR_GEN;

  SECKEYPublicKey* pubKeyRaw;
  aPrivKey = UniqueSECKEYPrivateKey(
    PK11_GenerateKeyPair(aSlot.get(), mechanism, keyParams, &pubKeyRaw,
                         /* ephemeral */ false, false,
                         /* wincx */ nullptr));
  aPubKey = UniqueSECKEYPublicKey(pubKeyRaw);
  pubKeyRaw = nullptr;
  if (NS_WARN_IF(!aPrivKey.get() || !aPubKey.get())) {
    return NS_ERROR_FAILURE;
  }

  // Check that the public key has the correct length
  if (NS_WARN_IF(aPubKey->u.ec.publicValue.len != kPublicKeyLen)) {
    return NS_ERROR_FAILURE;
  }

  return NS_OK;
}
Ejemplo n.º 3
0
UniqueSECKEYPublicKey
CreateECPublicKey(const SECItem* aKeyData, const nsString& aNamedCurve)
{
  UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  if (!arena) {
    return nullptr;
  }

  // It's important that this be a UniqueSECKEYPublicKey, as this ensures that
  // SECKEY_DestroyPublicKey will be called on it. If this doesn't happen, when
  // CryptoKey::PublicKeyValid is called on it and it gets moved to the internal
  // PKCS#11 slot, it will leak a reference to the slot.
  UniqueSECKEYPublicKey key(PORT_ArenaZNew(arena.get(), SECKEYPublicKey));
  if (!key) {
    return nullptr;
  }

  key->arena = nullptr; // key doesn't own the arena; it won't get double-freed
  key->keyType = ecKey;
  key->pkcs11Slot = nullptr;
  key->pkcs11ID = CK_INVALID_HANDLE;

  // Create curve parameters.
  SECItem* params = CreateECParamsForCurve(aNamedCurve, arena.get());
  if (!params) {
    return nullptr;
  }
  key->u.ec.DEREncodedParams = *params;

  // Set public point.
  key->u.ec.publicValue = *aKeyData;

  // Ensure the given point is on the curve.
  if (!CryptoKey::PublicKeyValid(key.get())) {
    return nullptr;
  }

  return UniqueSECKEYPublicKey(SECKEY_CopyPublicKey(key.get()));
}
Ejemplo n.º 4
0
SECKEYPublicKey*
CryptoKey::PublicKeyFromJwk(const JsonWebKey& aJwk,
                            const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
  if (aJwk.mKty.EqualsLiteral(JWK_TYPE_RSA)) {
    // Verify that all of the required parameters are present
    CryptoBuffer n, e;
    if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
        !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value()))) {
      return nullptr;
    }

    // Transcode to a DER RSAPublicKey structure
    struct RSAPublicKeyData {
      SECItem n;
      SECItem e;
    };
    const RSAPublicKeyData input = {
      { siUnsignedInteger, n.Elements(), (unsigned int) n.Length() },
      { siUnsignedInteger, e.Elements(), (unsigned int) e.Length() }
    };
    const SEC_ASN1Template rsaPublicKeyTemplate[] = {
      {SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(RSAPublicKeyData)},
      {SEC_ASN1_INTEGER, offsetof(RSAPublicKeyData, n),},
      {SEC_ASN1_INTEGER, offsetof(RSAPublicKeyData, e),},
      {0,}
    };

    ScopedSECItem pkDer(SEC_ASN1EncodeItem(nullptr, nullptr, &input,
                                           rsaPublicKeyTemplate));
    if (!pkDer.get()) {
      return nullptr;
    }

    return SECKEY_ImportDERPublicKey(pkDer.get(), CKK_RSA);
  }

  if (aJwk.mKty.EqualsLiteral(JWK_TYPE_EC)) {
    // Verify that all of the required parameters are present
    CryptoBuffer x, y;
    if (!aJwk.mCrv.WasPassed() ||
        !aJwk.mX.WasPassed() || NS_FAILED(x.FromJwkBase64(aJwk.mX.Value())) ||
        !aJwk.mY.WasPassed() || NS_FAILED(y.FromJwkBase64(aJwk.mY.Value()))) {
      return nullptr;
    }

    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
    if (!arena) {
      return nullptr;
    }

    SECKEYPublicKey* key = PORT_ArenaZNew(arena, SECKEYPublicKey);
    if (!key) {
      return nullptr;
    }

    key->keyType = ecKey;
    key->pkcs11Slot = nullptr;
    key->pkcs11ID = CK_INVALID_HANDLE;

    nsString namedCurve;
    if (!NormalizeToken(aJwk.mCrv.Value(), namedCurve)) {
      return nullptr;
    }

    // Create parameters.
    SECItem* params = CreateECParamsForCurve(namedCurve, arena.get());
    if (!params) {
      return nullptr;
    }
    key->u.ec.DEREncodedParams = *params;

    // Create point.
    SECItem* point = CreateECPointForCoordinates(x, y, arena.get());
    if (!point) {
      return nullptr;
    }
    key->u.ec.publicValue = *point;

    if (!PublicKeyValid(key)) {
      return nullptr;
    }

    return SECKEY_CopyPublicKey(key);
  }

  return nullptr;
}
Ejemplo n.º 5
0
SECKEYPrivateKey*
CryptoKey::PrivateKeyFromJwk(const JsonWebKey& aJwk,
                             const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
  CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
  CK_BBOOL falseValue = CK_FALSE;

  if (aJwk.mKty.EqualsLiteral(JWK_TYPE_EC)) {
    // Verify that all of the required parameters are present
    CryptoBuffer x, y, d;
    if (!aJwk.mCrv.WasPassed() ||
        !aJwk.mX.WasPassed() || NS_FAILED(x.FromJwkBase64(aJwk.mX.Value())) ||
        !aJwk.mY.WasPassed() || NS_FAILED(y.FromJwkBase64(aJwk.mY.Value())) ||
        !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value()))) {
      return nullptr;
    }

    nsString namedCurve;
    if (!NormalizeToken(aJwk.mCrv.Value(), namedCurve)) {
      return nullptr;
    }

    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
    if (!arena) {
      return nullptr;
    }

    // Create parameters.
    SECItem* params = CreateECParamsForCurve(namedCurve, arena.get());
    if (!params) {
      return nullptr;
    }

    SECItem* ecPoint = CreateECPointForCoordinates(x, y, arena.get());
    if (!ecPoint) {
      return nullptr;
    }

    // Compute the ID for this key
    // This is generated with a SHA-1 hash, so unlikely to collide
    ScopedSECItem objID(PK11_MakeIDFromPubKey(ecPoint));
    if (!objID.get()) {
      return nullptr;
    }

    // Populate template from parameters
    CK_KEY_TYPE ecValue = CKK_EC;
    CK_ATTRIBUTE keyTemplate[9] = {
      { CKA_CLASS,            &privateKeyValue,     sizeof(privateKeyValue) },
      { CKA_KEY_TYPE,         &ecValue,             sizeof(ecValue) },
      { CKA_TOKEN,            &falseValue,          sizeof(falseValue) },
      { CKA_SENSITIVE,        &falseValue,          sizeof(falseValue) },
      { CKA_PRIVATE,          &falseValue,          sizeof(falseValue) },
      { CKA_ID,               objID->data,          objID->len },
      { CKA_EC_PARAMS,        params->data,         params->len },
      { CKA_EC_POINT,         ecPoint->data,        ecPoint->len },
      { CKA_VALUE,            (void*) d.Elements(), d.Length() },
    };

    return PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
                                            PR_ARRAY_SIZE(keyTemplate));
  }

  if (aJwk.mKty.EqualsLiteral(JWK_TYPE_RSA)) {
    // Verify that all of the required parameters are present
    CryptoBuffer n, e, d, p, q, dp, dq, qi;
    if (!aJwk.mN.WasPassed() || NS_FAILED(n.FromJwkBase64(aJwk.mN.Value())) ||
        !aJwk.mE.WasPassed() || NS_FAILED(e.FromJwkBase64(aJwk.mE.Value())) ||
        !aJwk.mD.WasPassed() || NS_FAILED(d.FromJwkBase64(aJwk.mD.Value())) ||
        !aJwk.mP.WasPassed() || NS_FAILED(p.FromJwkBase64(aJwk.mP.Value())) ||
        !aJwk.mQ.WasPassed() || NS_FAILED(q.FromJwkBase64(aJwk.mQ.Value())) ||
        !aJwk.mDp.WasPassed() || NS_FAILED(dp.FromJwkBase64(aJwk.mDp.Value())) ||
        !aJwk.mDq.WasPassed() || NS_FAILED(dq.FromJwkBase64(aJwk.mDq.Value())) ||
        !aJwk.mQi.WasPassed() || NS_FAILED(qi.FromJwkBase64(aJwk.mQi.Value()))) {
      return nullptr;
    }

    ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
    if (!arena) {
      return nullptr;
    }

    // Compute the ID for this key
    // This is generated with a SHA-1 hash, so unlikely to collide
    SECItem nItem = { siBuffer, nullptr, 0 };
    if (!n.ToSECItem(arena, &nItem)) {
      return nullptr;
    }

    ScopedSECItem objID(PK11_MakeIDFromPubKey(&nItem));
    if (!objID.get()) {
      return nullptr;
    }

    // Populate template from parameters
    CK_KEY_TYPE rsaValue = CKK_RSA;
    CK_ATTRIBUTE keyTemplate[14] = {
      { CKA_CLASS,            &privateKeyValue,      sizeof(privateKeyValue) },
      { CKA_KEY_TYPE,         &rsaValue,             sizeof(rsaValue) },
      { CKA_TOKEN,            &falseValue,           sizeof(falseValue) },
      { CKA_SENSITIVE,        &falseValue,           sizeof(falseValue) },
      { CKA_PRIVATE,          &falseValue,           sizeof(falseValue) },
      { CKA_ID,               objID->data,           objID->len },
      { CKA_MODULUS,          (void*) n.Elements(),  n.Length() },
      { CKA_PUBLIC_EXPONENT,  (void*) e.Elements(),  e.Length() },
      { CKA_PRIVATE_EXPONENT, (void*) d.Elements(),  d.Length() },
      { CKA_PRIME_1,          (void*) p.Elements(),  p.Length() },
      { CKA_PRIME_2,          (void*) q.Elements(),  q.Length() },
      { CKA_EXPONENT_1,       (void*) dp.Elements(), dp.Length() },
      { CKA_EXPONENT_2,       (void*) dq.Elements(), dq.Length() },
      { CKA_COEFFICIENT,      (void*) qi.Elements(), qi.Length() },
    };

    return PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
                                            PR_ARRAY_SIZE(keyTemplate));
  }

  return nullptr;
}