Example #1
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;

  // 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;
}
Example #2
0
bool ReadAndEncodeAttribute(SECKEYPrivateKey* aKey,
                            CK_ATTRIBUTE_TYPE aAttribute,
                            Optional<nsString>& aDst)
{
  ScopedSECItem item(::SECITEM_AllocItem(nullptr, nullptr, 0));
  if (!item) {
    return false;
  }

  if (PK11_ReadRawAttribute(PK11_TypePrivKey, aKey, aAttribute, item)
        != SECSuccess) {
    return false;
  }

  CryptoBuffer buffer;
  if (!buffer.Assign(item)) {
    return false;
  }

  if (NS_FAILED(buffer.ToJwkBase64(aDst.Value()))) {
    return false;
  }

  return true;
}
Example #3
0
/* Create an ECDHE key pair for a given curve */
SECStatus
ssl_CreateECDHEphemeralKeyPair(const sslSocket *ss,
                               const sslNamedGroupDef *ecGroup,
                               sslEphemeralKeyPair **keyPair)
{
    SECKEYPrivateKey *privKey = NULL;
    SECKEYPublicKey *pubKey = NULL;
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
    sslEphemeralKeyPair *pair;

    if (ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams) != SECSuccess) {
        return SECFailure;
    }
    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, ss->pkcs11PinArg);
    SECITEM_FreeItem(&ecParams, PR_FALSE);

    if (!privKey || !pubKey ||
        !(pair = ssl_NewEphemeralKeyPair(ecGroup, privKey, pubKey))) {
        if (privKey) {
            SECKEY_DestroyPrivateKey(privKey);
        }
        if (pubKey) {
            SECKEY_DestroyPublicKey(pubKey);
        }
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        return SECFailure;
    }

    *keyPair = pair;
    SSL_TRC(50, ("%d: SSL[%d]: Create ECDH ephemeral key %d",
                 SSL_GETPID(), ss ? ss->fd : NULL, ecGroup->name));
    PRINT_BUF(50, (ss, "Public Key", pubKey->u.ec.publicValue.data,
                   pubKey->u.ec.publicValue.len));
#ifdef TRACE
    if (ssl_trace >= 50) {
        SECItem d = { siBuffer, NULL, 0 };
        SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey,
                                             CKA_VALUE, &d);
        if (rv == SECSuccess) {
            PRINT_BUF(50, (ss, "Private Key", d.data, d.len));
            SECITEM_FreeItem(&d, PR_FALSE);
        } else {
            SSL_TRC(50, ("Error extracting private key"));
        }
    }
#endif
    return SECSuccess;
}
Example #4
0
static bool
isExtractable(SECKEYPrivateKey *privKey)
{
  SECItem value;
  bool    isExtractable = false;
  SECStatus rv;

  rv=PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_EXTRACTABLE, &value);
  if (rv != SECSuccess) {
    return false;
  }
  if ((value.len == 1) && (value.data != NULL)) {
    isExtractable = !!(*(CK_BBOOL*)value.data);
  }
  SECITEM_FreeItem(&value, false);
  return isExtractable;
}
// Attempt to read the CKA_EXTRACTABLE attribute on a private key inside
// a token. On success, store the attribute in |extractable| and return
// SECSuccess.
SECStatus
isExtractable(SECKEYPrivateKey *privKey, PRBool *extractable)
{
    SECItem value;
    SECStatus rv;

    rv=PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_EXTRACTABLE, &value);
    if (rv != SECSuccess)
        return rv;

    if ((value.len == 1) && (value.data != NULL))
        *extractable = !!(*(CK_BBOOL*)value.data);
    else
        rv = SECFailure;
    SECITEM_FreeItem(&value, PR_FALSE);
    return rv;
}
Example #6
0
static PRBool
isExtractable(SECKEYPrivateKey *privKey)
{
  SECItem value;
  PRBool  isExtractable = PR_FALSE;
  SECStatus rv;

  rv=PK11_ReadRawAttribute(PK11_TypePrivKey, privKey, CKA_EXTRACTABLE, &value);
  if (rv != SECSuccess) {
    return PR_FALSE;
  }
  if ((value.len == 1) && (value.data != NULL)) {
    isExtractable = *(CK_BBOOL*)value.data;
  }
  SECITEM_FreeItem(&value, PR_FALSE);
  return isExtractable;
}
Example #7
0
/**
 *
 * Callback to pick the SSL client certificate.
 */
static SECStatus SelectClientCert(void *arg, PRFileDesc *sock,
                                  struct CERTDistNamesStr *caNames,
                                  struct CERTCertificateStr **pRetCert,
                                  struct SECKEYPrivateKeyStr **pRetKey)
{
  struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg;
  struct SessionHandle *data = connssl->data;
  const char *nickname = connssl->client_nickname;

  if(connssl->obj_clicert) {
    /* use the cert/key provided by PEM reader */
    static const char pem_slotname[] = "PEM Token #1";
    SECItem cert_der = { 0, NULL, 0 };
    void *proto_win = SSL_RevealPinArg(sock);
    struct CERTCertificateStr *cert;
    struct SECKEYPrivateKeyStr *key;

    PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname);
    if(NULL == slot) {
      failf(data, "NSS: PK11 slot not found: %s", pem_slotname);
      return SECFailure;
    }

    if(PK11_ReadRawAttribute(PK11_TypeGeneric, connssl->obj_clicert, CKA_VALUE,
                             &cert_der) != SECSuccess) {
      failf(data, "NSS: CKA_VALUE not found in PK11 generic object");
      PK11_FreeSlot(slot);
      return SECFailure;
    }

    cert = PK11_FindCertFromDERCertItem(slot, &cert_der, proto_win);
    SECITEM_FreeItem(&cert_der, PR_FALSE);
    if(NULL == cert) {
      failf(data, "NSS: client certificate from file not found");
      PK11_FreeSlot(slot);
      return SECFailure;
    }

    key = PK11_FindPrivateKeyFromCert(slot, cert, NULL);
    PK11_FreeSlot(slot);
    if(NULL == key) {
      failf(data, "NSS: private key from file not found");
      CERT_DestroyCertificate(cert);
      return SECFailure;
    }

    infof(data, "NSS: client certificate from file\n");
    display_cert_info(data, cert);

    *pRetCert = cert;
    *pRetKey = key;
    return SECSuccess;
  }

  /* use the default NSS hook */
  if(SECSuccess != NSS_GetClientAuthData((void *)nickname, sock, caNames,
                                          pRetCert, pRetKey)
      || NULL == *pRetCert) {

    if(NULL == nickname)
      failf(data, "NSS: client certificate not found (nickname not "
            "specified)");
    else
      failf(data, "NSS: client certificate not found: %s", nickname);

    return SECFailure;
  }

  /* get certificate nickname if any */
  nickname = (*pRetCert)->nickname;
  if(NULL == nickname)
    nickname = "[unknown]";

  if(NULL == *pRetKey) {
    failf(data, "NSS: private key not found for certificate: %s", nickname);
    return SECFailure;
  }

  infof(data, "NSS: using client certificate: %s\n", nickname);
  display_cert_info(data, *pRetCert);
  return SECSuccess;
}
Example #8
0
nsresult
CryptoKey::PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey,
                           JsonWebKey& aRetVal,
                           const nsNSSShutDownPreventionLock& /*proofOfLock*/)
{
  switch (aPrivKey->keyType) {
    case rsaKey: {
      aRetVal.mN.Construct();
      aRetVal.mE.Construct();
      aRetVal.mD.Construct();
      aRetVal.mP.Construct();
      aRetVal.mQ.Construct();
      aRetVal.mDp.Construct();
      aRetVal.mDq.Construct();
      aRetVal.mQi.Construct();

      if (!ReadAndEncodeAttribute(aPrivKey, CKA_MODULUS, aRetVal.mN) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_PUBLIC_EXPONENT, aRetVal.mE) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_PRIVATE_EXPONENT, aRetVal.mD) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_PRIME_1, aRetVal.mP) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_PRIME_2, aRetVal.mQ) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_1, aRetVal.mDp) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_2, aRetVal.mDq) ||
          !ReadAndEncodeAttribute(aPrivKey, CKA_COEFFICIENT, aRetVal.mQi)) {
        return NS_ERROR_DOM_OPERATION_ERR;
      }

      aRetVal.mKty = NS_LITERAL_STRING(JWK_TYPE_RSA);
      return NS_OK;
    }
    case ecKey: {
      // Read EC params.
      ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0));
      SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey,
                                           CKA_EC_PARAMS, params);
      if (rv != SECSuccess) {
        return NS_ERROR_DOM_OPERATION_ERR;
      }

      // Read public point Q.
      ScopedSECItem ecPoint(::SECITEM_AllocItem(nullptr, nullptr, 0));
      rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey, CKA_EC_POINT,
                                 ecPoint);
      if (rv != SECSuccess) {
        return NS_ERROR_DOM_OPERATION_ERR;
      }

      if (!ECKeyToJwk(PK11_TypePrivKey, aPrivKey, params, ecPoint, aRetVal)) {
        return NS_ERROR_DOM_OPERATION_ERR;
      }

      aRetVal.mD.Construct();

      // Read private value.
      if (!ReadAndEncodeAttribute(aPrivKey, CKA_VALUE, aRetVal.mD)) {
        return NS_ERROR_DOM_OPERATION_ERR;
      }

      return NS_OK;
    }
    default:
      return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
  }
}
Example #9
0
/*
 * 'clone' a physical card as a virtual card
 */
static VCard *
vcard_emul_mirror_card(VReader *vreader)
{
    /*
     * lookup certs using the C_FindObjects. The Stan Cert handle won't give
     * us the real certs until we log in.
     */
    PK11GenericObject *firstObj, *thisObj;
    int cert_count;
    unsigned char **certs;
    int *cert_len;
    VCardKey **keys;
    PK11SlotInfo *slot;
    PRBool ret;
    VCard *card;

    slot = vcard_emul_reader_get_slot(vreader);
    if (slot == NULL) {
        return NULL;
    }

    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
    if (firstObj == NULL) {
        return NULL;
    }

    /* count the certs */
    cert_count = 0;
    for (thisObj = firstObj; thisObj;
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
        cert_count++;
    }

    if (cert_count == 0) {
        PK11_DestroyGenericObjects(firstObj);
        return NULL;
    }

    /* allocate the arrays */
    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
    if (ret == PR_FALSE) {
        return NULL;
    }

    /* fill in the arrays */
    cert_count = 0;
    for (thisObj = firstObj; thisObj;
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
        SECItem derCert;
        CERTCertificate *cert;
        SECStatus rv;

        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
                                   CKA_VALUE, &derCert);
        if (rv != SECSuccess) {
            continue;
        }
        /* create floating temp cert. This gives us a cert structure even if
         * the token isn't logged in */
        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
                                       NULL, PR_FALSE, PR_TRUE);
        SECITEM_FreeItem(&derCert, PR_FALSE);
        if (cert == NULL) {
            continue;
        }

        certs[cert_count] = cert->derCert.data;
        cert_len[cert_count] = cert->derCert.len;
        keys[cert_count] = vcard_emul_make_key(slot, cert);
        cert_count++;
        CERT_DestroyCertificate(cert); /* key obj still has a reference */
    }

    /* now create the card */
    card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
    g_free(certs);
    g_free(cert_len);
    g_free(keys);

    return card;
}
Example #10
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;
}