-
+ 992C1ED9B3037031C841DB0BB5D6467D2142ACCE1E9B67DDF91D1661D7A9731452D2F2D95222AAC51EE7672A781FD2BB195692D3949E14EAF46B8E29D2243FE0
smg_comms/rsa/primegen.c
(0 . 0)(1 . 152)
8857 /* primegen.c - prime number generation and checks
8858 *
8859 * S.MG, 2017
8860 *
8861 */
8862
8863 #include <stdlib.h>
8864 #include <unistd.h>
8865 #include <assert.h>
8866
8867 #include "smg_rsa.h"
8868
8869 /****************
8870 * is_composite
8871 * Returns 1 if it finds evidence that n is composite and 0 otherwise.
8872 * NB: this is a probabilistic test and its strength is directly linked to:
8873 * - the number of witnesses AND
8874 * - the quality of the entropy source given as arguments!
8875 */
8876
8877 int is_composite( MPI n, int nwitnesses, int entropy_source) {
8878 int evidence = 0;
8879 int nlimbs = mpi_get_nlimbs(n); /* see MPI representation */
8880 unsigned int nbits = mpi_get_nbits(n); /* used bits */
8881 unsigned int noctets = (nbits + 7) / 8; /* source works on octets */
8882
8883 MPI nminus1 = mpi_alloc(nlimbs); /* n-1 value is used a LOT */
8884 MPI mpi2 = mpi_alloc_set_ui(2); /* 2 as MPI */
8885 MPI a = mpi_alloc(nlimbs); /* candidate witness */
8886 MPI y = mpi_alloc(nlimbs); /* intermediate values */
8887 MPI r = mpi_alloc(nlimbs); /* n = 1 + 2^s * r */
8888 int s; /* n = 1 + 2^s * r */
8889 int j; /* counter for loops */
8890 int nread; /* number of random octets actually read */
8891
8892 /* precondition: n > 3 */
8893 assert( nbits > 2 );
8894
8895 /* nminus1 = n - 1 as MPI */
8896 mpi_sub_ui( nminus1, n, 1);
8897
8898 /*
8899 * find r odd and s so that n = 1 + 2^s * r
8900 * n-1 = 2^s * r
8901 * s is given by the number of trailing zeros of binary n-1
8902 * r is then obtained as (n-1) / (2^s)
8903 */
8904 s = mpi_trailing_zeros( nminus1 );
8905 mpi_tdiv_q_2exp(r, nminus1, s);
8906
8907 /*
8908 * Investigate randomly chosen candidate witnesses.
8909 * Stop when either:
8910 * the specified number of witnesses (nwitnesses) have
8911 been investigated OR
8912 * a witness for compositeness of n was found
8913 */
8914 while (nwitnesses > 0 && evidence == 0) {
8915 unsigned char *p = xmalloc(noctets);
8916 do {
8917 nread = get_random_octets_from(noctets, p, entropy_source);
8918 } while (nread != noctets);
8919
8920 mpi_set_buffer(a, p, noctets, 0);
8921
8922 /* ensure that a < n-1 by making a maximum nbits-1 long:
8923 * clear all bits above nbits-2 in a
8924 * keep value of bit nbits-2 in a as it was
8925 */
8926 if (mpi_test_bit(a, nbits - 2))
8927 mpi_set_highbit(a, nbits - 2);
8928 else
8929 mpi_clear_highbit(a, nbits - 2);
8930
8931 /* ensure that 1 < a < n-1; if not, try another random number
8932 * NB: true random means a CAN end up as 0 or 1 here.
8933 */
8934 if (mpi_cmp(a, nminus1) < 0 && mpi_cmp_ui(a, 1) > 0) {
8935 /* calculate y = a^r mod n */
8936 mpi_powm(y, a, r, n);
8937 if (mpi_cmp_ui(y, 1) && mpi_cmp(y, nminus1)) {
8938 j = 1;
8939 while ( (j < s) && mpi_cmp(y, nminus1) && (evidence == 0) ) {
8940 /* calculate y = y^2 mod n */
8941 mpi_powm(y, y, mpi2, n);
8942 if (mpi_cmp_ui(y, 1) == 0)
8943 evidence = 1;
8944 j = j + 1;
8945 } /* end while */
8946 if (mpi_cmp(y, nminus1))
8947 evidence = 1;
8948 } /* end if y != 1 and y != n-1 */
8949 nwitnesses = nwitnesses - 1;
8950 } /* end if 1 < a < n-1 */
8951 xfree(p);
8952 } /* end while for investigating candidate witnesses */
8953
8954 mpi_free( nminus1 );
8955 mpi_free( mpi2 );
8956 mpi_free( a );
8957 mpi_free( y );
8958 mpi_free( r );
8959
8960 return evidence;
8961 }
8962
8963 /**
8964 * Generates a random number that has passed the Miller-Rabin test for primality (see function is_composite above).
8965 * NB: top 2 bits and bottom bit are ALWAYS 1! (i.e. a mask 11.....1 is applied)
8966 * a prime of 8*noctets long will have only 8*noctets-3 bits that are randomly chosen
8967 * NB: this method does NOT allocate space for the requested MPI; it is the caller's responsibility to allocate it!
8968 * The source of randomness is ENTROPY_SOURCE in eucrypt/smg_rsa/include/knobs.h
8969 * The number of witnesses checked by Miller-Rabin is M_R_ITERATIONS in eucrypt/smg_rsa/include/knobs.h
8970 * Preconditions:
8971 * noctets > 0 (at least one octet!)
8972 * memory allocated for noctets in output MPI
8973 * successful access to the entropy source
8974 */
8975 void gen_random_prime( unsigned int noctets, MPI output )
8976 {
8977 /* precondition: at least one octet long */
8978 assert(noctets > 0);
8979
8980 /* precondition: enough memory allocated for the limbs corresponding to noctets */
8981 unsigned int nlimbs = mpi_nlimb_hint_from_nbytes(noctets);
8982 assert(mpi_get_alloced(output) >= nlimbs);
8983
8984 /* precondition: access to the entropy source */
8985 int entropy_source = open_entropy_source(ENTROPY_SOURCE); /* source of random bits */
8986 assert(entropy_source >= 0);
8987
8988 unsigned int nbits = 8*noctets; /* length of MPI in bits */
8989
8990 /*
8991 * loop until a prime is found: get noctets of random bits, trim and apply 110...01 mask, check if prime
8992 */
8993 unsigned char *p = xmalloc( noctets );
8994 int nread;
8995 do {
8996 do {
8997 nread = get_random_octets_from( noctets, p, entropy_source );
8998 } while ( nread != noctets );
8999 mpi_set_buffer( output, p, noctets, 0); /* convert to MPI representation */
9000 mpi_set_highbit( output, nbits - 1 ); /* trim at required size and set top bit */
9001 mpi_set_bit( output, nbits - 2); /* set second top bit */
9002 mpi_set_bit( output, 0 ); /* set bottom bit to unsure odd number */
9003 } while (is_composite(output, M_R_ITERATIONS, entropy_source));
9004
9005 /* tidy up, a prime was found */
9006 xfree(p);
9007 close(entropy_source);
9008 }