コード例 #1
0
ファイル: CryptoKey.cpp プロジェクト: Wafflespeanut/gecko-dev
// NSS exports private EC keys without the CKA_EC_POINT attribute, i.e. the
// public value. To properly export the private key to JWK or PKCS #8 we need
// the public key data though and so we use this method to augment a private
// key with data from the given public key.
nsresult
CryptoKey::AddPublicKeyData(SECKEYPublicKey* aPublicKey)
{
  // This should be a private key.
  MOZ_ASSERT(GetKeyType() == PRIVATE);
  // There should be a private NSS key with type 'EC'.
  MOZ_ASSERT(mPrivateKey && mPrivateKey->keyType == ecKey);
  // The given public key should have the same key type.
  MOZ_ASSERT(aPublicKey->keyType == mPrivateKey->keyType);

  nsNSSShutDownPreventionLock locker;

  // Read EC params.
  ScopedAutoSECItem params;
  SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey.get(),
                                       CKA_EC_PARAMS, &params);
  if (rv != SECSuccess) {
    return NS_ERROR_DOM_OPERATION_ERR;
  }

  // Read private value.
  ScopedAutoSECItem value;
  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey.get(), CKA_VALUE,
                             &value);
  if (rv != SECSuccess) {
    return NS_ERROR_DOM_OPERATION_ERR;
  }

  SECItem* point = &aPublicKey->u.ec.publicValue;
  CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
  CK_BBOOL falseValue = CK_FALSE;
  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) },
    // PrivateKeyFromPrivateKeyTemplate sets the ID.
    { CKA_ID,               nullptr,              0 },
    { CKA_EC_PARAMS,        params.data,          params.len },
    { CKA_EC_POINT,         point->data,          point->len },
    { CKA_VALUE,            value.data,           value.len },
  };

  mPrivateKey = PrivateKeyFromPrivateKeyTemplate(keyTemplate,
                                                 ArrayLength(keyTemplate));
  NS_ENSURE_TRUE(mPrivateKey, NS_ERROR_DOM_OPERATION_ERR);

  return NS_OK;
}
コード例 #2
0
ファイル: CryptoKey.cpp プロジェクト: LordJZ/gecko-dev
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;
}
コード例 #3
0
// NSS exports private EC keys without the CKA_EC_POINT attribute, i.e. the
// public value. To properly export the private key to JWK or PKCS #8 we need
// the public key data though and so we use this method to augment a private
// key with data from the given public key.
nsresult
CryptoKey::AddPublicKeyData(SECKEYPublicKey* aPublicKey)
{
  // This should be a private key.
  MOZ_ASSERT(GetKeyType() == PRIVATE);
  // There should be a private NSS key with type 'EC'.
  MOZ_ASSERT(mPrivateKey && mPrivateKey->keyType == ecKey);
  // The given public key should have the same key type.
  MOZ_ASSERT(aPublicKey->keyType == mPrivateKey->keyType);

  nsNSSShutDownPreventionLock locker;

  ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
  if (!slot) {
    return NS_ERROR_DOM_OPERATION_ERR;
  }

  // Generate a random 160-bit object ID.
  ScopedSECItem objID(::SECITEM_AllocItem(nullptr, nullptr, 20));
  SECStatus rv = PK11_GenerateRandomOnSlot(slot, objID->data, objID->len);
  if (rv != SECSuccess) {
    return NS_ERROR_DOM_OPERATION_ERR;
  }

  // Read EC params.
  ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0));
  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey, CKA_EC_PARAMS,
                             params);
  if (rv != SECSuccess) {
    return NS_ERROR_DOM_OPERATION_ERR;
  }

  // Read private value.
  ScopedSECItem value(::SECITEM_AllocItem(nullptr, nullptr, 0));
  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, mPrivateKey, CKA_VALUE, value);
  if (rv != SECSuccess) {
    return NS_ERROR_DOM_OPERATION_ERR;
  }

  SECItem* point = &aPublicKey->u.ec.publicValue;
  CK_OBJECT_CLASS privateKeyValue = CKO_PRIVATE_KEY;
  CK_BBOOL falseValue = CK_FALSE;
  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,         point->data,          point->len },
    { CKA_VALUE,            value->data,          value->len },
  };

  mPrivateKey = PrivateKeyFromPrivateKeyTemplate(objID, keyTemplate,
                                                 PR_ARRAY_SIZE(keyTemplate));
  NS_ENSURE_TRUE(mPrivateKey, NS_ERROR_DOM_OPERATION_ERR);

  return NS_OK;
}