/* * ecgen, tool for generating Elliptic curve domain parameters * Copyright (C) 2017-2018 J08nY */ #include "subgroup.h" #include "gen/point.h" #include "util/memory.h" subgroup_t *subgroup_new(void) { return try_calloc(sizeof(subgroup_t)); } subgroup_t *subgroup_copy(const subgroup_t *src, subgroup_t *dst) { if (src->generator) dst->generator = point_new_copy(src->generator); if (src->points) { dst->points = points_new_copy(src->points, src->npoints); dst->npoints = src->npoints; } return dst; } subgroup_t *subgroup_new_copy(const subgroup_t *src) { subgroup_t *result = subgroup_new(); return subgroup_copy(src, result); } subgroup_t *subgroup_clone(const subgroup_t *src, subgroup_t *dst) { if (src->generator) dst->generator = point_new_clone(src->generator); if (src->points) { dst->points = points_new_clone(src->points, src->npoints); dst->npoints = src->npoints; } return dst; } subgroup_t *subgroup_new_clone(const subgroup_t *src) { subgroup_t *result = subgroup_new(); return subgroup_clone(src, result); } void subgroup_free(subgroup_t **subgroup) { if (*subgroup) { if ((*subgroup)->generator) { point_free(&(*subgroup)->generator); } try_free(*subgroup); *subgroup = NULL; } } void subgroup_free_deep(subgroup_t **subgroup) { if (*subgroup) { points_free_deep(&(*subgroup)->points, (*subgroup)->npoints); subgroup_free(subgroup); } } subgroup_t **subgroups_new(size_t num) { return try_calloc(num * sizeof(subgroup_t *)); } subgroup_t **subgroups_copy(subgroup_t **const src, subgroup_t **dest, size_t num) { for (size_t i = 0; i < num; ++i) { dest[i] = subgroup_new_copy(src[i]); } return dest; } subgroup_t **subgroups_new_copy(subgroup_t **const src, size_t num) { subgroup_t **result = subgroups_new(num); return subgroups_copy(src, result, num); } subgroup_t **subgroups_clone(subgroup_t **const src, subgroup_t **dest, size_t num) { for (size_t i = 0; i < num; ++i) { dest[i] = subgroup_new_clone(src[i]); } return dest; } subgroup_t **subgroups_new_clone(subgroup_t **const src, size_t num) { subgroup_t **result = subgroups_new(num); return subgroups_clone(src, result, num); } void subgroups_free(subgroup_t ***subgroups) { if (*subgroups) { try_free(*subgroups); *subgroups = NULL; } } void subgroups_free_deep(subgroup_t ***subgroups, size_t num) { if (*subgroups) { for (size_t i = 0; i < num; ++i) { subgroup_free(&(*subgroups)[i]); } subgroups_free(subgroups); } } /** * @brief All prime divisors of a given integer with multiplicity. * * subgroups_divisors(27) = [3, 3, 3] * @param order * @return a t_VEC of prime divisors. */ static GEN subgroups_divisors(GEN order) { GEN factors = Z_factor(order); GEN primes = gel(factors, 1); GEN multiples = gel(factors, 2); long uniqs = glength(primes); long size = 0; for (long i = 1; i <= uniqs; ++i) { size += itos(gel(multiples, i)); } GEN result = gtovec0(gen_0, size); long count = 0; for (long i = 1; i <= uniqs; ++i) { long multiple = itos(gel(multiples, i)); for (long j = 1; j <= multiple; ++j) { gel(result, ++count) = gel(primes, i); } } return result; } /** * @brief All factors consisting of at least min_bits prime * factors. * * @param factors * @param min_bits * @return a t_VEC of factors */ static GEN subgroups_2n_factors(GEN factors, size_t min_bits) { pari_sp ltop = avma; long nprimes = glength(factors); if (nprimes == min_bits) return NULL; GEN amount = int2n(nprimes); GEN groups = gtovec0(gen_0, itos(amount) - (min_bits * nprimes) - 1); size_t i = 0; for (size_t count = 1; count < (size_t)(1) << nprimes; ++count) { pari_sp btop = avma; GEN result = gen_1; size_t bits = 0; for (long bit = 0; bit < nprimes; ++bit) { size_t mask = (size_t)(1) << bit; if (count & mask) { result = mulii(result, gel(factors, bit + 1)); bits++; } } if (bits > min_bits) { gel(groups, ++i) = result; } else { avma = btop; } } GEN ret = gtoset(groups); return gerepilecopy(ltop, ret); } GEN subgroups_prime(GEN order) { GEN factors = Z_factor(order); return gtovec(gel(factors, 1)); } GEN subgroups_nonprime(GEN order) { if (isprime(order)) { return NULL; } GEN factors = subgroups_divisors(order); return subgroups_2n_factors(factors, 1); } GEN subgroups_all(GEN order) { if (isprime(order)) { return gtovec(order); } GEN factors = subgroups_divisors(order); return subgroups_2n_factors(factors, 0); } /** * @brief * @param curve * @param min_bits * @return */ /* static GEN subgroups_2n_gens(const curve_t *curve, size_t min_bits) { GEN one_factors = subgroups_divisors(curve->generators[0]->order); GEN one = subgroups_2n_factors(one_factors, min_bits); GEN other_factors = subgroups_divisors(curve->generators[1]->order); GEN other = subgroups_2n_factors(other_factors, min_bits); if (!one) { return other; } if (!other) { return one; } GEN result = gtovec0(gen_0, glength(one) + glength(other)); for (long i = 1; i <= glength(result); ++i) { if (i <= glength(one)) { gel(result, i) = gel(one, i); } else { gel(result, i) = gel(other, i - glength(one)); } } return result; } */ /** * @brief * @param curve * @param min_bits * @return */ /* static GEN subgroups_2n(const curve_t *curve, size_t min_bits) { if (curve->ngens == 1) { GEN factors = subgroups_divisors(curve->order); return subgroups_2n_factors(factors, min_bits); } return subgroups_2n_gens(curve, min_bits); } */