raw
smg_comms_c_wrappers    1 /* smg_rsa.h
smg_comms_c_wrappers 2 * S.MG, 2017
smg_comms_c_wrappers 3 */
smg_comms_c_wrappers 4
smg_comms_c_wrappers 5 #ifndef SMG_RSA_H
smg_comms_c_wrappers 6 #define SMG_RSA_H
smg_comms_c_wrappers 7
smg_comms_c_wrappers 8 #include "mpi.h"
smg_comms_c_wrappers 9 #include "knobs.h"
smg_comms_c_wrappers 10
smg_comms_c_wrappers 11 /* A way to determine endianness at runtime.
smg_comms_c_wrappers 12 * Required for diddling a float's mantissa for instance.
smg_comms_c_wrappers 13 */
smg_comms_c_wrappers 14 static const int onect = 1;
smg_comms_c_wrappers 15 #define is_bigendian() ( (*(char*)&onect) == 0 )
smg_comms_c_wrappers 16
smg_comms_c_wrappers 17 /*
smg_comms_c_wrappers 18 * These are constants as per Eulora's protocol specification, NOT knobs!
smg_comms_c_wrappers 19 * Eulora uses RSA keys of 3920 bits (490 octets);
smg_comms_c_wrappers 20 * The above key length means 2 primes of 1960 bits (245 octets) each.
smg_comms_c_wrappers 21 * NB: if you choose here an odd key length in octets you might end up with a smaller actual key, read the code.
smg_comms_c_wrappers 22 */
smg_comms_c_wrappers 23 static const int KEY_LENGTH_OCTETS = 490;
smg_comms_c_wrappers 24
smg_comms_c_wrappers 25 typedef struct {
smg_comms_c_wrappers 26 MPI n; /* modulus */
smg_comms_c_wrappers 27 MPI e; /* public exponent */
smg_comms_c_wrappers 28 } RSA_public_key;
smg_comms_c_wrappers 29
smg_comms_c_wrappers 30 typedef struct {
smg_comms_c_wrappers 31 MPI n; /* public modulus */
smg_comms_c_wrappers 32 MPI e; /* public exponent */
smg_comms_c_wrappers 33 MPI d; /* private exponent: e*d=1 mod phi */
smg_comms_c_wrappers 34 MPI p; /* prime p */
smg_comms_c_wrappers 35 MPI q; /* prime q */
smg_comms_c_wrappers 36 MPI u; /* inverse of p mod q */
smg_comms_c_wrappers 37 } RSA_secret_key;
smg_comms_c_wrappers 38
smg_comms_c_wrappers 39
smg_comms_c_wrappers 40 /*********truerandom.c*********/
smg_comms_c_wrappers 41
smg_comms_c_wrappers 42 /*
smg_comms_c_wrappers 43 * Opens and configures (as per FG requirements) the specified entropy source (e.g. "/dev/ttyUSB0")
smg_comms_c_wrappers 44 * @param source_name the name of the file to open (e.g. "/dev/ttyUSB0")
smg_comms_c_wrappers 45 * @return the descriptor of the open file when successful; negative value otherwise
smg_comms_c_wrappers 46 */
smg_comms_c_wrappers 47 int open_entropy_source(char* source_name);
smg_comms_c_wrappers 48
smg_comms_c_wrappers 49
smg_comms_c_wrappers 50 /*
smg_comms_c_wrappers 51 * Returns noctets random octets (i.e. 8*noctets bits in total) as obtained from EuCrypt's preferred source.
smg_comms_c_wrappers 52 * Preferred source is defined in knobs.h as ENTROPY_SOURCE and should be a TRNG (e.g. Fuckgoats).
smg_comms_c_wrappers 53 * @param nboctets the length of desired random sequence, in octets
smg_comms_c_wrappers 54 * @param out pointer to allocated memory space for the requested random noctets; NB: this method does NOT allocate space!
smg_comms_c_wrappers 55 * @return the actual number of octets that were obtained from the currently configured entropy source (this is equal to noctets on successful read of required noctets)
smg_comms_c_wrappers 56 */
smg_comms_c_wrappers 57 int get_random_octets(int noctets, unsigned char *out);
smg_comms_c_wrappers 58
smg_comms_c_wrappers 59 /* Returns noctets random octets as obtained from the specified "from" source;
smg_comms_c_wrappers 60 * NB: the "from" source is considered to be the handle of an already opened stream;
smg_comms_c_wrappers 61 * This method will simply attempt to read from the source as needed!
smg_comms_c_wrappers 62 *
smg_comms_c_wrappers 63 * @param noctets the length of desired random sequence, in octets
smg_comms_c_wrappers 64 * @param out pointer to allocated memory space for the requested random octets;
smg_comms_c_wrappers 65 * NB: this method does NOT allocate space!
smg_comms_c_wrappers 66 * @param from handle of an already opened entropy source - this method will just READ from it as needed
smg_comms_c_wrappers 67 * @return the actual number of octets that were obtained
smg_comms_c_wrappers 68 */
smg_comms_c_wrappers 69 int get_random_octets_from(int noctets, unsigned char *out, int from);
smg_comms_c_wrappers 70
smg_comms_c_wrappers 71 /* Returns (in parameter *n) a *potentially biased* random float between 0 and 1
smg_comms_c_wrappers 72 * Uses bits from ENTROPY_SOURCE but it rounds when converting to float
smg_comms_c_wrappers 73 * NB: This function rounds impredictably.
smg_comms_c_wrappers 74 Use it ONLY if LSB normalization is insignificant to you!
smg_comms_c_wrappers 75 * This function uses rng_uint64 below.
smg_comms_c_wrappers 76 *
smg_comms_c_wrappers 77 * @param n - a float value (LSB rounded) between 0 and 1, obtained using
smg_comms_c_wrappers 78 * a 64-bit random integer (64 bits from ENTROPY_SOURCE)
smg_comms_c_wrappers 79 * @return - a positive value on success and a negative value in case of error
smg_comms_c_wrappers 80 * main possible cause for error: failure to open ENTROPY_SOURCE.
smg_comms_c_wrappers 81 * NB: a non-responsive/malconfigured source can result in blocking
smg_comms_c_wrappers 82 */
smg_comms_c_wrappers 83 int rng_dirty_float(float *n);
smg_comms_c_wrappers 84
smg_comms_c_wrappers 85
smg_comms_c_wrappers 86 /* Returns (in parameter *n) a randomly generated float between 1 and 2 using:
smg_comms_c_wrappers 87 * - the IEEE 754/1985 format for single float representation
smg_comms_c_wrappers 88 * - ENTROPY_SOURCE to obtain bits that are *directly* used as mantissa
smg_comms_c_wrappers 89 * NB: this value is between 1 and 2 due to the normalised format that includes
smg_comms_c_wrappers 90 * an implicit 1 ( i.e. value is (-1)^sign * 2^(e-127) * (1.mantissa) )
smg_comms_c_wrappers 91 *
smg_comms_c_wrappers 92 * From IEEE 754/1985, a description of the single float format:
smg_comms_c_wrappers 93 * msb means most significant bit
smg_comms_c_wrappers 94 * lsb means least significant bit
smg_comms_c_wrappers 95 * 1 8 23 ... widths
smg_comms_c_wrappers 96 * +-+-------+-----------------------+
smg_comms_c_wrappers 97 * |s| e | f |
smg_comms_c_wrappers 98 * +-+-------+-----------------------+
smg_comms_c_wrappers 99 * msb lsb msb lsb ... order
smg_comms_c_wrappers 100
smg_comms_c_wrappers 101 * A 32-bit single format number X is divided as shown in the figure above. The
smg_comms_c_wrappers 102 * value v of X is inferred from its constituent fields thus:
smg_comms_c_wrappers 103 * 1. If e = 255 and f != 0 , then v is NaN regardless of s
smg_comms_c_wrappers 104 * 2. If e = 255 and f = 0 , then v = (-1)^s INFINITY
smg_comms_c_wrappers 105 * 3. If 0 < e < 255 , then v = (-1)^s * 2^(e-127) * ( 1.f )
smg_comms_c_wrappers 106 * 4. If e = 0 and f != 0 , then v = (-1)^s * 2^(-126) * ( 0.f ) (denormalized
smg_comms_c_wrappers 107 * numbers)
smg_comms_c_wrappers 108 * 5. If e = 0 and f = 0 , then v = ( -1 )^s * 0 (zero)
smg_comms_c_wrappers 109 *
smg_comms_c_wrappers 110 * @param n - the address of an IEEE 754/1985 float: its mantissa will be set to
smg_comms_c_wrappers 111 * random bits obtained from ENTROPY_SOURCE; its sign will be set
smg_comms_c_wrappers 112 * to 0; its exponent will be set to 127 (the bias value so
smg_comms_c_wrappers 113 * that the actual exponent is 0).
smg_comms_c_wrappers 114 * @return - a positive value on success and a negative value in case of error
smg_comms_c_wrappers 115 * main possible cause for error: failure to open ENTROPY_SOURCE.
smg_comms_c_wrappers 116 * NB: a non-responsive/malconfigured source can result in blocking
smg_comms_c_wrappers 117 */
smg_comms_c_wrappers 118 int rng_float_754_1985(float *n);
smg_comms_c_wrappers 119
smg_comms_c_wrappers 120 /* Returns (in parameter *n) a random unsigned integer value on 32 bits.
smg_comms_c_wrappers 121 * Uses random bits from ENTROPY_SOURCE that are directly interpreted as int
smg_comms_c_wrappers 122 *
smg_comms_c_wrappers 123 * @param n - it will contain the random integer obtained by interpreting 32
smg_comms_c_wrappers 124 * bits from ENTROPY_SOURCE as an unsigned int value on 32 bits.
smg_comms_c_wrappers 125 * @return - a positive value on success and a negative value in case of error
smg_comms_c_wrappers 126 */
smg_comms_c_wrappers 127 int rng_uint32( uint32_t *n );
smg_comms_c_wrappers 128
smg_comms_c_wrappers 129 /* Returns (in parameter *n) a random unsigned integer value on 64 bits.
smg_comms_c_wrappers 130 * Uses random bits from ENTROPY_SOURCE that are directly interpreted as int
smg_comms_c_wrappers 131 *
smg_comms_c_wrappers 132 * @param n - it will contain the random integer obtained by interpreting 64
smg_comms_c_wrappers 133 * bits from ENTROPY_SOURCE as an unsigned int value on 64 bits.
smg_comms_c_wrappers 134 * @return - a positive value on success and a negative value in case of error
smg_comms_c_wrappers 135 */
smg_comms_c_wrappers 136 int rng_uint64( uint64_t *n );
smg_comms_c_wrappers 137
smg_comms_c_wrappers 138 /*********primegen.c*********/
smg_comms_c_wrappers 139
smg_comms_c_wrappers 140 /*
smg_comms_c_wrappers 141 * This is an implementation of the Miller-Rabin probabilistic primality test:
smg_comms_c_wrappers 142 * checking the specified number of randomly-chosen candidate witnesses
smg_comms_c_wrappers 143 * (i.e. with an outer bound of (1/4)^nwitnesses).
smg_comms_c_wrappers 144 * NB: a 1 result from this test means that the given n is indeed composite (non-prime)
smg_comms_c_wrappers 145 but a 0 result does not fully guarantee that n is prime!
smg_comms_c_wrappers 146 If this doesn't make sense to you, read more on probabilistic primality tests.
smg_comms_c_wrappers 147 * @param n the candidate prime number;
smg_comms_c_wrappers 148 the function will investigate whether this number is composite or *likely* to be prime.
smg_comms_c_wrappers 149 How likely? It depends on the number of witnesses checked, see next parameter.
smg_comms_c_wrappers 150 * @param nwitnesses this is the number of randomly chosen candidate witnesses to the compositeness of n
smg_comms_c_wrappers 151 that will be checked; the outer bound of the algorithm depends on this.
smg_comms_c_wrappers 152 * @param entropy_source the source of entropy (ready to read from) that will be used
smg_comms_c_wrappers 153 to choose candidate witnesses to the compositeness of n.
smg_comms_c_wrappers 154 * @return 1 if at least one witness to the compositeness of n has been found
smg_comms_c_wrappers 155 (i.e. n is certainly composite);
smg_comms_c_wrappers 156 0 if no witness to the compositeness of n was found (i.e. it is likely that n is prime)
smg_comms_c_wrappers 157 * NB: the probability that n is *not* prime although this function returned 0 is
smg_comms_c_wrappers 158 less than (1/4)^nwitnesses, but it is NOT zero.
smg_comms_c_wrappers 159 */
smg_comms_c_wrappers 160 int is_composite( MPI n, int nwitnesses, int entropy_source);
smg_comms_c_wrappers 161
smg_comms_c_wrappers 162 /**
smg_comms_c_wrappers 163 * Generates a random number that has passed the Miller-Rabin test for primality (see function is_composite above).
smg_comms_c_wrappers 164 * NB: top 2 bits and bottom bit are ALWAYS 1! (i.e. a mask 110....01 is applied to the random bits)
smg_comms_c_wrappers 165 * a prime of 8*noctets long will have only (8*noctets-3) bits that are randomly chosen!
smg_comms_c_wrappers 166 * NB: this method does NOT allocate space for the requested MPI; it is the caller's responsibility to allocate it!
smg_comms_c_wrappers 167 * The source of randomness is ENTROPY_SOURCE in eucrypt/smg_rsa/include/knobs.h
smg_comms_c_wrappers 168 * The number of witnesses checked by Miller-Rabin is M_R_ITERATIONS in eucrypt/smg_rsa/include/knobs.h
smg_comms_c_wrappers 169 * Preconditions:
smg_comms_c_wrappers 170 * noctets > 0 (at least one octet!)
smg_comms_c_wrappers 171 * output has known allocated memory for at least nlimbs(noctets)
smg_comms_c_wrappers 172 * successful access to the entropy source
smg_comms_c_wrappers 173 * @param noctets the length of the desired prime number, in octets
smg_comms_c_wrappers 174 * @param output an MPI with sufficient memory allocated for a number that is noctets long
smg_comms_c_wrappers 175 */
smg_comms_c_wrappers 176 void gen_random_prime( unsigned int noctets, MPI output);
smg_comms_c_wrappers 177
smg_comms_c_wrappers 178 /*********rsa.c*********/
smg_comms_c_wrappers 179 /*
smg_comms_c_wrappers 180 * Generates a pair of public+private RSA keys using directly the entropy source
smg_comms_c_wrappers 181 * specified in include/knobs.h
smg_comms_c_wrappers 182 *
smg_comms_c_wrappers 183 * ALL RSA keys are 8*KEY_LENGTH_OCTETS bits out of
smg_comms_c_wrappers 184 * 2 8*KEY_LENGTH_OCTETS/2 bits primes, as per TMSR spec.
smg_comms_c_wrappers 185 *
smg_comms_c_wrappers 186 * @param sk a fully-allocated structure to hold the generated keypair (secret
smg_comms_c_wrappers 187 key structure holds all the elements anyway, public key is a subset of this)
smg_comms_c_wrappers 188 *
smg_comms_c_wrappers 189 * NB: this procedure does NOT allocate memory for components in sk!
smg_comms_c_wrappers 190 * caller should ALLOCATE enough memory for all the MPIs in sk
smg_comms_c_wrappers 191 * Precondition:
smg_comms_c_wrappers 192 * MPIs in sk have known allocated memory for the nlimbs fitting their TMSR size
smg_comms_c_wrappers 193 */
smg_comms_c_wrappers 194 void gen_keypair( RSA_secret_key *sk );
smg_comms_c_wrappers 195
smg_comms_c_wrappers 196 /****************
smg_comms_c_wrappers 197 * Public key operation. Encrypt input with pk and store result into output.
smg_comms_c_wrappers 198 *
smg_comms_c_wrappers 199 * output = input^e mod n , where e,n are elements of pkey.
smg_comms_c_wrappers 200 * NB: caller should allocate *sufficient* memory for output to hold the result.
smg_comms_c_wrappers 201 * NB: NO checks are made on input!
smg_comms_c_wrappers 202 *
smg_comms_c_wrappers 203 * @param output MPI with enough allocated memory to hold result of encryption
smg_comms_c_wrappers 204 * @param input MPI containing content to encrypt; it *has to be* different from
smg_comms_c_wrappers 205 output!
smg_comms_c_wrappers 206 * @param pk the public key that will be used to encrypt input
smg_comms_c_wrappers 207 *
smg_comms_c_wrappers 208 * Precondition:
smg_comms_c_wrappers 209 * output != input
smg_comms_c_wrappers 210 * Output and input have to be two distinct MPIs because of the sorry state of
smg_comms_c_wrappers 211 the underlying mpi lib that can't handle properly the case when those are the
smg_comms_c_wrappers 212 same.
smg_comms_c_wrappers 213 */
smg_comms_c_wrappers 214 void public_rsa( MPI output, MPI input, RSA_public_key *pk );
smg_comms_c_wrappers 215
smg_comms_c_wrappers 216
smg_comms_c_wrappers 217 /****************
smg_comms_c_wrappers 218 * Secret key operation. Decrypt input with sk and store result in output.
smg_comms_c_wrappers 219 *
smg_comms_c_wrappers 220 * output = input^d mod n , where d, n are elements of skey.
smg_comms_c_wrappers 221 *
smg_comms_c_wrappers 222 * This implementation uses the Chinese Remainder Theorem (CRT):
smg_comms_c_wrappers 223 *
smg_comms_c_wrappers 224 * out1 = input ^ (d mod (p-1)) mod p
smg_comms_c_wrappers 225 * out2 = input ^ (d mod (q-1)) mod q
smg_comms_c_wrappers 226 * h = u * (out2 - out1) mod q
smg_comms_c_wrappers 227 * output = out1 + h * p
smg_comms_c_wrappers 228 *
smg_comms_c_wrappers 229 * where out1, out2 and h are intermediate values, d,n,p,q,u are elements of
smg_comms_c_wrappers 230 skey. By using CRT, encryption is *faster*. Decide for yourself if this fits
smg_comms_c_wrappers 231 your needs though!
smg_comms_c_wrappers 232 * NB: it is the caller's responsibility to allocate memory for output!
smg_comms_c_wrappers 233 * NB: NO checks are made on input!
smg_comms_c_wrappers 234 *
smg_comms_c_wrappers 235 * @param output MPI with enough allocated memory to hold result of decryption
smg_comms_c_wrappers 236 * @param input MPI containing content to decrypt
smg_comms_c_wrappers 237 * @param sk the secret key that will be used to decrypt input
smg_comms_c_wrappers 238 */
smg_comms_c_wrappers 239 void secret_rsa( MPI output, MPI input, RSA_secret_key *sk );
smg_comms_c_wrappers 240
smg_comms_c_wrappers 241 #endif /*SMG_RSA*/
smg_comms_c_wrappers 242