static int _decode_pkcs8_eddsa_key(ASN1_TYPE pkcs8_asn, gnutls_x509_privkey_t pkey, const char *oid) { int ret; gnutls_datum_t tmp; gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID; const gnutls_ecc_curve_entry_st *ce; gnutls_pk_params_init(&pkey->params); curve = gnutls_oid_to_ecc_curve(oid); if (curve == GNUTLS_ECC_CURVE_INVALID) { _gnutls_debug_log("PKCS#8: unknown curve OID %s\n", oid); return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); } ce = _gnutls_ecc_curve_get_params(curve); if (_curve_is_eddsa(ce)) { ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &tmp, ASN1_ETYPE_OCTET_STRING, 1); if (ret < 0) { gnutls_assert(); return gnutls_assert_val(ret); } if (tmp.size != ce->size) { gnutls_free(tmp.data); return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); } gnutls_free(pkey->params.raw_priv.data); pkey->params.algo = GNUTLS_PK_EDDSA_ED25519; pkey->params.raw_priv.data = tmp.data; pkey->params.raw_priv.size = tmp.size; pkey->params.curve = curve; tmp.data = NULL; return 0; } else { return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); } }
/* initialize single cache entry * for a curve with the given id */ static int _ecc_wmnaf_cache_entry_init (gnutls_ecc_curve_cache_entry_t * p, gnutls_ecc_curve_t id) { int i, j, err; ecc_point *G; mpz_t a, modulus; const gnutls_ecc_curve_entry_st *st = NULL; if (p == NULL || id == 0) return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; G = ecc_new_point (); if (G == NULL) { return GNUTLS_E_MEMORY_ERROR; } st = _gnutls_ecc_curve_get_params (id); if (st == NULL) { err = GNUTLS_E_INTERNAL_ERROR; goto done; } if ((err = mp_init_multi (&a, &modulus, NULL) != 0)) return err; /* set id */ p->id = id; /* set modulus */ mpz_set_str (modulus, st->prime, 16); /* get generator point */ mpz_set_str (G->x, st->Gx, 16); mpz_set_str (G->y, st->Gy, 16); mpz_set_ui (G->z, 1); /* set A */ mpz_set_str (a, st->A, 16); /* alloc ram for precomputed values */ for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i) { p->pos[i] = ecc_new_point (); p->neg[i] = ecc_new_point (); if (p->pos[i] == NULL || p->neg[i] == NULL) { for (j = 0; j < i; ++j) { ecc_del_point (p->pos[j]); ecc_del_point (p->neg[j]); } err = GNUTLS_E_MEMORY_ERROR; goto done; } } /* fill in pos and neg arrays with precomputed values * pos holds kG for k == 1, 3, 5, ..., (2^w - 1) * neg holds kG for k == -1,-3,-5, ...,-(2^w - 1) */ /* pos[0] == 2G for a while, later it will be set to the expected 1G */ if ((err = ecc_projective_dbl_point (G, p->pos[0], a, modulus)) != 0) goto done; /* pos[1] == 3G */ if ((err = ecc_projective_add_point (p->pos[0], G, p->pos[1], a, modulus)) != 0) goto done; /* fill in kG for k = 5, 7, ..., (2^w - 1) */ for (j = 2; j < WMNAF_PRECOMPUTED_LENGTH; ++j) { if ((err = ecc_projective_add_point (p->pos[j - 1], p->pos[0], p->pos[j], a, modulus)) != 0) goto done; } /* set pos[0] == 1G as expected * after this step we don't need G at all */ mpz_set (p->pos[0]->x, G->x); mpz_set (p->pos[0]->y, G->y); mpz_set (p->pos[0]->z, G->z); /* map to affine all elements in pos * this will allow to use ecc_projective_madd later * set neg[i] == -pos[i] */ for (j = 0; j < WMNAF_PRECOMPUTED_LENGTH; ++j) { if ((err = ecc_map (p->pos[j], modulus)) != 0) goto done; if ((err = ecc_projective_negate_point (p->pos[j], p->neg[j], modulus)) != 0) goto done; } err = 0; done: ecc_del_point (G); mp_clear_multi (&a, &modulus, NULL); return err; }
static int wrap_nettle_pk_generate_params (gnutls_pk_algorithm_t algo, unsigned int level /*bits */ , gnutls_pk_params_st * params) { int ret; unsigned int i, q_bits; memset(params, 0, sizeof(*params)); switch (algo) { case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; dsa_public_key_init (&pub); dsa_private_key_init (&priv); /* the best would be to use _gnutls_pk_bits_to_subgroup_bits() * but we do NIST DSA here */ if (level <= 1024) q_bits = 160; else q_bits = 256; ret = dsa_generate_keypair (&pub, &priv, NULL, rnd_func, NULL, NULL, level, q_bits); if (ret != 1) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto dsa_fail; } params->params_nr = 0; for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like (&pub.p); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto dsa_fail; } params->params_nr++; } ret = 0; _gnutls_mpi_set (params->params[0], pub.p); _gnutls_mpi_set (params->params[1], pub.q); _gnutls_mpi_set (params->params[2], pub.g); _gnutls_mpi_set (params->params[3], pub.y); _gnutls_mpi_set (params->params[4], priv.x); dsa_fail: dsa_private_key_clear (&priv); dsa_public_key_clear (&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; struct rsa_private_key priv; rsa_public_key_init (&pub); rsa_private_key_init (&priv); _gnutls_mpi_set_ui (&pub.e, 65537); ret = rsa_generate_keypair (&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); if (ret != 1) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like (&pub.n); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto rsa_fail; } params->params_nr++; } ret = 0; _gnutls_mpi_set (params->params[0], pub.n); _gnutls_mpi_set (params->params[1], pub.e); _gnutls_mpi_set (params->params[2], priv.d); _gnutls_mpi_set (params->params[3], priv.p); _gnutls_mpi_set (params->params[4], priv.q); _gnutls_mpi_set (params->params[5], priv.c); _gnutls_mpi_set (params->params[6], priv.a); _gnutls_mpi_set (params->params[7], priv.b); rsa_fail: rsa_private_key_clear (&priv); rsa_public_key_clear (&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_EC: { ecc_key key; ecc_set_type tls_ecc_set; const gnutls_ecc_curve_entry_st *st; st = _gnutls_ecc_curve_get_params(level); if (st == NULL) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); tls_ecc_set.size = st->size; tls_ecc_set.prime = st->prime; tls_ecc_set.order = st->order; tls_ecc_set.Gx = st->Gx; tls_ecc_set.Gy = st->Gy; tls_ecc_set.A = st->A; tls_ecc_set.B = st->B; ret = ecc_make_key(NULL, rnd_func, &key, &tls_ecc_set, st->id); if (ret != 0) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); params->params_nr = 0; for (i = 0; i < ECC_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like(&key.prime); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto ecc_fail; } params->params_nr++; } params->flags = level; mpz_set(TOMPZ(params->params[ECC_PRIME]), key.prime); mpz_set(TOMPZ(params->params[ECC_ORDER]), key.order); mpz_set(TOMPZ(params->params[ECC_A]), key.A); mpz_set(TOMPZ(params->params[ECC_B]), key.B); mpz_set(TOMPZ(params->params[ECC_GX]), key.Gx); mpz_set(TOMPZ(params->params[ECC_GY]), key.Gy); mpz_set(TOMPZ(params->params[ECC_X]), key.pubkey.x); mpz_set(TOMPZ(params->params[ECC_Y]), key.pubkey.y); mpz_set(TOMPZ(params->params[ECC_K]), key.k); ecc_fail: ecc_free(&key); if (ret < 0) goto fail; break; } default: gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } return 0; fail: for (i = 0; i < params->params_nr; i++) { _gnutls_mpi_release (¶ms->params[i]); } params->params_nr = 0; return ret; }