summaryrefslogtreecommitdiffstats
path: root/lib/ncrypto_nss.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ncrypto_nss.c')
-rw-r--r--lib/ncrypto_nss.c347
1 files changed, 347 insertions, 0 deletions
diff --git a/lib/ncrypto_nss.c b/lib/ncrypto_nss.c
index dc250cd..a430c3f 100644
--- a/lib/ncrypto_nss.c
+++ b/lib/ncrypto_nss.c
@@ -1041,6 +1041,353 @@ ncr_key_pair_generate_rsa (struct ncr_public_key **public_key,
return key_pair_generate (public_key, private_key, mech, sensitive, &params);
}
+ /* DSA keys */
+
+/* Contains both the "key" and domain parameters */
+struct dsa_public_values
+{
+ SECItem items[NCR_DSA_PUBLIC_NUM_MPIS];
+};
+
+static const SEC_ASN1Template dsa_public_values_params_asn1_template[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (struct dsa_public_values) },
+#define INT(X) \
+ { \
+ SEC_ASN1_INTEGER, \
+ offsetof (struct dsa_public_values, items) + (X) * sizeof (SECItem), \
+ NULL, 0 \
+ }
+
+ INT (NCR_DSA_PUBLIC_MPI_PRIME), INT (NCR_DSA_PUBLIC_MPI_SUBPRIME),
+ INT (NCR_DSA_PUBLIC_MPI_BASE),
+#undef INT
+ { 0, 0, NULL, 0 }
+ };
+
+static const SEC_ASN1Template dsa_public_values_key_asn1_template[] =
+ {
+ {
+ SEC_ASN1_INTEGER,
+ offsetof (struct dsa_public_values, items)
+ + NCR_DSA_PUBLIC_MPI_VALUE * sizeof (SECItem), NULL, 0
+ }
+ };
+
+/* Contains both the "key" and domain parameters */
+struct dsa_private_values
+{
+ SECItem items[NCR_DSA_PRIVATE_NUM_MPIS];
+};
+
+static const SEC_ASN1Template dsa_private_values_params_asn1_template[] =
+ {
+ { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (struct dsa_private_values) },
+#define INT(X) \
+ { \
+ SEC_ASN1_INTEGER, \
+ offsetof (struct dsa_private_values, items) + (X) * sizeof (SECItem), \
+ NULL, 0 \
+ }
+
+ INT (NCR_DSA_PRIVATE_MPI_PRIME), INT (NCR_DSA_PRIVATE_MPI_SUBPRIME),
+ INT (NCR_DSA_PRIVATE_MPI_BASE),
+#undef INT
+ { 0, 0, NULL, 0 }
+ };
+
+static const SEC_ASN1Template dsa_private_values_key_asn1_template[] =
+ {
+ {
+ SEC_ASN1_INTEGER,
+ offsetof (struct dsa_private_values, items)
+ + NCR_DSA_PRIVATE_MPI_VALUE * sizeof (SECItem), NULL, 0
+ }
+ };
+
+static CK_RV
+dsa_validate_algorithm_id (const SECAlgorithmID *id)
+{
+ const SECOidData *oid;
+
+ oid = SECOID_FindOIDByTag (SEC_OID_ANSIX9_DSA_SIGNATURE);
+ if (oid == NULL || !SECITEM_ItemsAreEqual(&id->algorithm, &oid->oid))
+ return CKR_GENERAL_ERROR;
+ return CKR_OK;
+}
+
+CK_RV
+ncr_public_key_create_dsa (struct ncr_public_key **key,
+ const struct ncr_mpi
+ mpis[static NCR_DSA_PUBLIC_NUM_MPIS])
+{
+ struct dsa_public_values der_input;
+ CERTSubjectPublicKeyInfo spki;
+ SECItem params;
+ SECStatus ss;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ res = mpi_create_SECItems_for_encoding (der_input.items, mpis,
+ NCR_DSA_PUBLIC_NUM_MPIS);
+ if (res != CKR_OK)
+ return res;
+
+ spki.subjectPublicKey.data = NULL;
+ spki.subjectPublicKey.len = 0;
+ if (SEC_ASN1EncodeItem (NULL, &spki.subjectPublicKey, &der_input,
+ dsa_public_values_key_asn1_template) == NULL)
+ return CKR_HOST_MEMORY;
+ /* spki->subjectPublicKey is encoded as BIT_STRING, so "len" needs to be a
+ number of _bits_. */
+ if (spki.subjectPublicKey.len > UINT_MAX / 8)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_subjectPublicKey;
+ }
+ spki.subjectPublicKey.len *= 8;
+
+ params.data = NULL;
+ params.len = 0;
+ if (SEC_ASN1EncodeItem (NULL, &params, &der_input,
+ dsa_public_values_params_asn1_template) == NULL)
+ {
+ res = CKR_HOST_MEMORY;
+ goto end_subjectPublicKey;
+ }
+ memset (&spki.algorithm, 0, sizeof (spki.algorithm));
+ ss = SECOID_SetAlgorithmID (NULL, &spki.algorithm,
+ SEC_OID_ANSIX9_DSA_SIGNATURE, &params);
+ PORT_Free (params.data);
+ if (ss != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_subjectPublicKey;
+ }
+
+ res = public_key_create (key, &spki);
+
+ SECOID_DestroyAlgorithmID (&spki.algorithm, PR_FALSE);
+ end_subjectPublicKey:
+ PORT_Free (spki.subjectPublicKey.data);
+
+ return res;
+}
+
+CK_RV
+ncr_public_key_export_dsa (struct ncr_public_key *key,
+ struct ncr_mpi
+ mpis [static NCR_DSA_PUBLIC_NUM_MPIS])
+{
+ struct dsa_public_values der_output;
+ CERTSubjectPublicKeyInfo *spki;
+ PRArenaPool *arena;
+ SECItem key_item;
+ CK_RV res;
+ size_t i;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ g_return_val_if_fail (key != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (mpis != NULL, CKR_ARGUMENTS_BAD);
+
+ spki = SECKEY_CreateSubjectPublicKeyInfo(key->key);
+ if (spki == NULL)
+ return CKR_GENERAL_ERROR;
+
+ res = dsa_validate_algorithm_id (&spki->algorithm);
+ if (res != CKR_OK)
+ goto end_spki;
+
+ /* Ugly... the PLArenaPool type is from NSPR, but NSS implementation accesses
+ memory only initialized through NSS's PORT_* */
+ arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL)
+ {
+ res = CKR_HOST_MEMORY;
+ goto end_spki;
+ }
+
+ /* Setting type to siUnsignedInteger requests removal of leading zeroes. */
+ for (i = 0; i < NCR_DSA_PUBLIC_NUM_MPIS; i++)
+ der_output.items[i].type = siUnsignedInteger;
+
+ if (SEC_QuickDERDecodeItem (arena, &der_output,
+ dsa_public_values_params_asn1_template,
+ &spki->algorithm.parameters) != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_arena;
+ }
+ /* spki->subjectPublicKey is encoded as BIT_STRING, so "len" is a number of
+ _bits_. */
+ key_item.data = spki->subjectPublicKey.data;
+ key_item.len = (spki->subjectPublicKey.len / 8
+ + (spki->subjectPublicKey.len % 8 != 0));
+ if (SEC_QuickDERDecodeItem (arena, &der_output,
+ dsa_public_values_key_asn1_template, &key_item)
+ != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end_arena;
+ }
+
+ res = mpi_output_decoded_SECItems(mpis, der_output.items,
+ NCR_DSA_PUBLIC_NUM_MPIS);
+
+ end_arena:
+ PORT_FreeArena (arena, PR_FALSE);
+ end_spki:
+ SECKEY_DestroySubjectPublicKeyInfo (spki);
+ return res;
+}
+
+CK_RV
+ncr_private_key_create_dsa (struct ncr_private_key **key, _Bool sensitive,
+ const struct ncr_mpi
+ mpis[static NCR_DSA_PRIVATE_NUM_MPIS],
+ const struct ncr_mpi *public_value)
+{
+ struct dsa_private_values der_input;
+ SECItem public_item, params;
+ struct private_key_info pki;
+ SECStatus ss;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ res = mpi_create_SECItems_for_encoding (der_input.items, mpis,
+ NCR_DSA_PRIVATE_NUM_MPIS);
+ if (res != CKR_OK)
+ return res;
+ res = mpi_create_SECItems_for_encoding (&public_item, public_value, 1);
+ if (res != CKR_OK)
+ return res;
+
+ params.data = NULL;
+ params.len = 0;
+ if (SEC_ASN1EncodeItem (NULL, &params, &der_input,
+ dsa_private_values_params_asn1_template) == NULL)
+ return CKR_HOST_MEMORY;
+ memset (&pki.algorithm, 0, sizeof (pki.algorithm));
+ ss = SECOID_SetAlgorithmID (NULL, &pki.algorithm,
+ SEC_OID_ANSIX9_DSA_SIGNATURE, &params);
+ PORT_Free (params.data);
+ if (ss != SECSuccess)
+ return CKR_GENERAL_ERROR;
+
+ pki.private_key.data = NULL;
+ pki.private_key.len = 0;
+ if (SEC_ASN1EncodeItem (NULL, &pki.private_key, &der_input,
+ dsa_private_values_key_asn1_template) == NULL)
+ {
+ res = CKR_HOST_MEMORY;
+ goto end_algorithm;
+ }
+
+ res = private_key_create_components (key, CKK_DSA, sensitive, &pki,
+ &public_item);
+ SECITEM_ZfreeItem (&pki.private_key, PR_FALSE);
+
+ end_algorithm:
+ SECOID_DestroyAlgorithmID (&pki.algorithm, PR_FALSE);
+ return res;
+}
+
+CK_RV
+ncr_private_key_export_dsa (struct ncr_private_key *key,
+ struct ncr_mpi
+ mpis[static NCR_DSA_PRIVATE_NUM_MPIS])
+{
+ struct private_key_info pki;
+ struct dsa_private_values der_output;
+ PRArenaPool *arena;
+ CK_RV res;
+ size_t i;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ g_return_val_if_fail (mpis != NULL, CKR_ARGUMENTS_BAD);
+
+ /* Ugly... the PLArenaPool type is from NSPR, but NSS implementation accesses
+ memory only initialized through NSS's PORT_* */
+ arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
+ if (arena == NULL)
+ return CKR_HOST_MEMORY;
+
+ res = private_key_export_components (key, arena, &pki);
+ if (res != CKR_OK)
+ goto end;
+
+ res = dsa_validate_algorithm_id (&pki.algorithm);
+ if (res != CKR_OK)
+ goto end;
+
+ /* Setting type to siUnsignedInteger requests removal of leading zeroes. */
+ for (i = 0; i < NCR_DSA_PRIVATE_NUM_MPIS; i++)
+ der_output.items[i].type = siUnsignedInteger;
+ if (SEC_QuickDERDecodeItem (arena, &der_output,
+ dsa_private_values_params_asn1_template,
+ &pki.algorithm.parameters) != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end;
+ }
+ if (SEC_QuickDERDecodeItem (arena, &der_output,
+ dsa_private_values_key_asn1_template,
+ &pki.private_key) != SECSuccess)
+ {
+ res = CKR_GENERAL_ERROR;
+ goto end;
+ }
+
+ res = mpi_output_decoded_SECItems(mpis, der_output.items,
+ NCR_DSA_PRIVATE_NUM_MPIS);
+
+ end:
+ PORT_FreeArena (arena, PR_TRUE);
+ return res;
+}
+
+CK_RV
+ncr_key_pair_generate_dsa (struct ncr_public_key **public_key,
+ struct ncr_private_key **private_key,
+ CK_MECHANISM_TYPE mech, _Bool sensitive,
+ const struct ncr_mpi
+ mpis[static NCR_DSA_GEN_NUM_MPIS])
+{
+ SECKEYPQGParams params;
+ size_t i;
+ CK_RV res;
+
+ res = ensure_ncr_is_open ();
+ if (res != CKR_OK)
+ return res;
+
+ g_return_val_if_fail (mech == CKM_DSA_KEY_PAIR_GEN, CKR_MECHANISM_INVALID);
+ g_return_val_if_fail (mpis != NULL, CKR_ARGUMENTS_BAD);
+ for (i = 0; i < NCR_DSA_GEN_NUM_MPIS; i++)
+ g_return_val_if_fail (mpis[i].data != NULL, CKR_ARGUMENTS_BAD);
+
+ params.prime.data = mpis[NCR_DSA_GEN_MPI_PRIME].data;
+ params.prime.len = mpis[NCR_DSA_GEN_MPI_PRIME].size;
+ params.subPrime.data = mpis[NCR_DSA_GEN_MPI_SUBPRIME].data;
+ params.subPrime.len = mpis[NCR_DSA_GEN_MPI_SUBPRIME].size;
+ params.base.data = mpis[NCR_DSA_GEN_MPI_BASE].data;
+ params.base.len = mpis[NCR_DSA_GEN_MPI_BASE].size;
+
+ return key_pair_generate (public_key, private_key, mech, sensitive, &params);
+}
+
/* Asymmetric operations */
CK_RV