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