raw
smg_comms_c_wrappers    1 //Wrapper methods for C implementations of RSA and MPI.
smg_comms_c_wrappers 2 //To be used / called from Ada so that the C part remains well separated.
smg_comms_c_wrappers 3 //S.MG, 2018
smg_comms_c_wrappers 4
smg_comms_c_wrappers 5 #include "c_wrappers.h"
smg_comms_c_wrappers 6 #include "mpi.h"
smg_comms_c_wrappers 7 #include "smg_rsa.h"
smg_comms_c_wrappers 8 #include <assert.h>
smg_comms_c_wrappers 9 #include <string.h> //for memmove...
smg_comms_c_wrappers 10
smg_comms_c_wrappers 11 //Wrapper for comparing the given arrays of octets as MPIs
smg_comms_c_wrappers 12 //Steps:
smg_comms_c_wrappers 13 //1. allocate space for 2 MPIs u and v
smg_comms_c_wrappers 14 //2. set buffer of u to content of a, buffer of v to content of b
smg_comms_c_wrappers 15 //3. call mpi_cmp(u,v) and store result
smg_comms_c_wrappers 16 //4. de-allocate u and v
smg_comms_c_wrappers 17 //5. return result
smg_comms_c_wrappers 18 int mpi_cmp_octets(char *a, unsigned int len_a, char *b, unsigned int len_b) {
smg_comms_c_wrappers 19 //variable to hold the final result of comparing a to b as MPIs
smg_comms_c_wrappers 20 int result;
smg_comms_c_wrappers 21
smg_comms_c_wrappers 22 //calculate how much space is needed for each MPI
smg_comms_c_wrappers 23 unsigned int nlimbs_a = mpi_nlimb_hint_from_nbytes( len_a );
smg_comms_c_wrappers 24 unsigned int nlimbs_b = mpi_nlimb_hint_from_nbytes( len_b );
smg_comms_c_wrappers 25
smg_comms_c_wrappers 26 //allocate space for the 2 MPIs
smg_comms_c_wrappers 27 MPI u = mpi_alloc(nlimbs_a);
smg_comms_c_wrappers 28 MPI v = mpi_alloc(nlimbs_b);
smg_comms_c_wrappers 29
smg_comms_shorter_e 30 //set the given octets as the values of the 2 MPIs and normalize
smg_comms_c_wrappers 31 //the sign is set to 0 (last parameter).
smg_comms_shorter_e 32 mpi_set_normalized(u, a, len_a, 0);
smg_comms_shorter_e 33 mpi_set_normalized(v, b, len_b, 0);
smg_comms_c_wrappers 34
smg_comms_c_wrappers 35 //compare the MPIs as numbers and store the result
smg_comms_c_wrappers 36 result = mpi_cmp(u, v);
smg_comms_c_wrappers 37
smg_comms_c_wrappers 38 //tidy up: free the memory allocated for the 2 MPIs
smg_comms_c_wrappers 39 mpi_free(u);
smg_comms_c_wrappers 40 mpi_free(v);
smg_comms_c_wrappers 41
smg_comms_c_wrappers 42 //return the result comparing a to b as MPIs
smg_comms_c_wrappers 43 return result;
smg_comms_c_wrappers 44 }
smg_comms_c_wrappers 45
smg_comms_c_wrappers 46 //Encryption of given input with a public RSA key: n and e given as octets too.
smg_comms_c_wrappers 47 //Steps:
smg_comms_c_wrappers 48 //1. create (allocate memory for) MPIs for out and input;
smg_comms_c_wrappers 49 //2. set the input as buffer for the corresponding MPI;
smg_comms_c_wrappers 50 //3. create and set the public key structure with n,e as contents;
smg_comms_c_wrappers 51 //4. call rsa/public_rsa and retrieve the result storing it in out;
smg_comms_c_wrappers 52 //5. free allocated memory for all the MPIs.
smg_comms_c_wrappers 53 //6. return the actual length of the encrypted result
smg_comms_c_wrappers 54 int public_rsa_octets( char *out , unsigned int len_out,
smg_comms_c_wrappers 55 char *input, unsigned int len_input,
smg_comms_c_wrappers 56 char *n , unsigned int len_n,
smg_comms_c_wrappers 57 char *e , unsigned int len_e) {
smg_comms_c_wrappers 58
smg_comms_c_wrappers 59 // precondition: output has enough memory allocated
smg_comms_c_wrappers 60 assert( len_out >= KEY_LENGTH_OCTETS );
smg_comms_c_wrappers 61
smg_comms_c_wrappers 62 //allocate memory for input and output MPIs
smg_comms_c_wrappers 63 unsigned int nlimbs_in = mpi_nlimb_hint_from_nbytes( len_input );
smg_comms_c_wrappers 64 unsigned int nlimbs_out = mpi_nlimb_hint_from_nbytes( len_out );
smg_comms_c_wrappers 65 MPI in_mpi = mpi_alloc(nlimbs_in);
smg_comms_c_wrappers 66 MPI out_mpi = mpi_alloc(nlimbs_out);
smg_comms_c_wrappers 67
smg_comms_c_wrappers 68 //set input as buffer for in_mpi
smg_comms_shorter_e 69 mpi_set_normalized(in_mpi, input, len_input, 0);
smg_comms_c_wrappers 70 //create public key structure and set its contents to given n, e
smg_comms_c_wrappers 71 RSA_public_key pk;
smg_comms_c_wrappers 72 unsigned int nlimbs_n = mpi_nlimb_hint_from_nbytes( len_n );
smg_comms_c_wrappers 73 unsigned int nlimbs_e = mpi_nlimb_hint_from_nbytes( len_e );
smg_comms_c_wrappers 74 pk.n = mpi_alloc(nlimbs_n);
smg_comms_c_wrappers 75 pk.e = mpi_alloc(nlimbs_e);
smg_comms_shorter_e 76 //NB MPI lib gets STUCK on 0-leading MPIs so set + normalize
smg_comms_shorter_e 77 mpi_set_normalized(pk.n, n, len_n, 0);
smg_comms_shorter_e 78 mpi_set_normalized(pk.e, e, len_e, 0);
smg_comms_c_wrappers 79 //call rsa public_key encryption and retrieve the result, storing it in out
smg_comms_c_wrappers 80 public_rsa( out_mpi, in_mpi, &pk);
smg_comms_c_wrappers 81 int len = len_out;
smg_comms_c_wrappers 82 mpi_to_octets( out, &len, out_mpi );
smg_comms_c_wrappers 83
smg_comms_c_wrappers 84 //tidy up: free allocated memory for ALL MPIs.
smg_comms_c_wrappers 85 mpi_free(in_mpi);
smg_comms_c_wrappers 86 mpi_free(out_mpi);
smg_comms_c_wrappers 87 mpi_free(pk.n);
smg_comms_c_wrappers 88 mpi_free(pk.e);
smg_comms_c_wrappers 89
smg_comms_c_wrappers 90 //return actual length
smg_comms_c_wrappers 91 return len;
smg_comms_c_wrappers 92 }
smg_comms_c_wrappers 93
smg_comms_c_wrappers 94 //Decryption of given input with the private key given through its components.
smg_comms_c_wrappers 95 //Steps:
smg_comms_c_wrappers 96 //1. create (allocate memory for) MPIs for out and input;
smg_comms_c_wrappers 97 //2. set the input as buffer for the corresponding MPI;
smg_comms_c_wrappers 98 //3. create and set the private key structure with n,e,d,p,q,u as contents;
smg_comms_c_wrappers 99 //4. call rsa/private_rsa and retrieve the result storing it in out;
smg_comms_c_wrappers 100 //5. free allocated memory for all the MPIs.
smg_comms_c_wrappers 101 //6. return the actual length of the result
smg_comms_c_wrappers 102 int private_rsa_octets( char *out, unsigned int len_out,
smg_comms_c_wrappers 103 char *input, unsigned int len_input,
smg_comms_c_wrappers 104 char *n , unsigned int len_n,
smg_comms_c_wrappers 105 char *e , unsigned int len_e,
smg_comms_c_wrappers 106 char *d , unsigned int len_d,
smg_comms_c_wrappers 107 char *p , unsigned int len_p,
smg_comms_c_wrappers 108 char *q , unsigned int len_q,
smg_comms_c_wrappers 109 char *u , unsigned int len_u) {
smg_comms_c_wrappers 110 // precondition: output has enough memory allocated
smg_comms_c_wrappers 111 assert( len_out >= KEY_LENGTH_OCTETS );
smg_comms_c_wrappers 112
smg_comms_c_wrappers 113 //allocate memory for input and output MPIs
smg_comms_c_wrappers 114 unsigned int nlimbs_in = mpi_nlimb_hint_from_nbytes( len_input );
smg_comms_c_wrappers 115 unsigned int nlimbs_out = mpi_nlimb_hint_from_nbytes( len_out );
smg_comms_c_wrappers 116 MPI in_mpi = mpi_alloc(nlimbs_in);
smg_comms_c_wrappers 117 MPI out_mpi = mpi_alloc(nlimbs_out);
smg_comms_c_wrappers 118
smg_comms_c_wrappers 119 //set input as buffer for in_mpi
smg_comms_shorter_e 120 mpi_set_normalized(in_mpi, input, len_input, 0);
smg_comms_c_wrappers 121
smg_comms_c_wrappers 122 //create private key structure and set its contents to given n,e,d,p,q,u
smg_comms_c_wrappers 123 RSA_secret_key sk;
smg_comms_c_wrappers 124 unsigned int nlimbs_n = mpi_nlimb_hint_from_nbytes( len_n );
smg_comms_c_wrappers 125 unsigned int nlimbs_e = mpi_nlimb_hint_from_nbytes( len_e );
smg_comms_c_wrappers 126 unsigned int nlimbs_d = mpi_nlimb_hint_from_nbytes( len_d );
smg_comms_c_wrappers 127 unsigned int nlimbs_p = mpi_nlimb_hint_from_nbytes( len_p );
smg_comms_c_wrappers 128 unsigned int nlimbs_q = mpi_nlimb_hint_from_nbytes( len_q );
smg_comms_c_wrappers 129 unsigned int nlimbs_u = mpi_nlimb_hint_from_nbytes( len_u );
smg_comms_c_wrappers 130 sk.n = mpi_alloc(nlimbs_n);
smg_comms_c_wrappers 131 sk.e = mpi_alloc(nlimbs_e);
smg_comms_c_wrappers 132 sk.d = mpi_alloc(nlimbs_d);
smg_comms_c_wrappers 133 sk.p = mpi_alloc(nlimbs_p);
smg_comms_c_wrappers 134 sk.q = mpi_alloc(nlimbs_q);
smg_comms_c_wrappers 135 sk.u = mpi_alloc(nlimbs_u);
smg_comms_shorter_e 136 //HAVE TO set AND normalize those or lib MPI gets stuck idiotically on 0-led
smg_comms_shorter_e 137 mpi_set_normalized(sk.n, n, len_n, 0);
smg_comms_shorter_e 138 mpi_set_normalized(sk.e, e, len_e, 0);
smg_comms_shorter_e 139 mpi_set_normalized(sk.d, d, len_d, 0);
smg_comms_shorter_e 140 mpi_set_normalized(sk.p, p, len_p, 0);
smg_comms_shorter_e 141 mpi_set_normalized(sk.q, q, len_q, 0);
smg_comms_shorter_e 142 mpi_set_normalized(sk.u, u, len_u, 0);
smg_comms_c_wrappers 143
smg_comms_c_wrappers 144 //call rsa secret_key encryption and retrieve the result, storing it in out
smg_comms_c_wrappers 145 secret_rsa( out_mpi, in_mpi, &sk );
smg_comms_c_wrappers 146 int len = len_out;
smg_comms_c_wrappers 147 mpi_to_octets( out, &len, out_mpi );
smg_comms_c_wrappers 148
smg_comms_c_wrappers 149 //tidy up: free memory previously allocated for MPIs
smg_comms_c_wrappers 150 mpi_free(in_mpi);
smg_comms_c_wrappers 151 mpi_free(out_mpi);
smg_comms_c_wrappers 152 mpi_free(sk.n);
smg_comms_c_wrappers 153 mpi_free(sk.e);
smg_comms_c_wrappers 154 mpi_free(sk.d);
smg_comms_c_wrappers 155 mpi_free(sk.p);
smg_comms_c_wrappers 156 mpi_free(sk.q);
smg_comms_c_wrappers 157 mpi_free(sk.u);
smg_comms_c_wrappers 158
smg_comms_c_wrappers 159 //return number of octets copied in out - real length of result
smg_comms_c_wrappers 160 return len;
smg_comms_c_wrappers 161 }
smg_comms_c_wrappers 162
smg_comms_c_wrappers 163 //Generates a new RSA key and stores its components at the specified locations.
smg_comms_c_wrappers 164 void gen_rsa_octets( char *n, unsigned int *len_n,
smg_comms_c_wrappers 165 char *e, unsigned int *len_e,
smg_comms_c_wrappers 166 char *d, unsigned int *len_d,
smg_comms_c_wrappers 167 char *p, unsigned int *len_p,
smg_comms_c_wrappers 168 char *q, unsigned int *len_q,
smg_comms_c_wrappers 169 char *u, unsigned int *len_u) {
smg_comms_c_wrappers 170 // precondition: all pointers have enough memory allocated
smg_comms_c_wrappers 171 assert( *len_n >= KEY_LENGTH_OCTETS );
smg_comms_c_wrappers 172 assert( *len_e >= KEY_LENGTH_OCTETS );
smg_comms_c_wrappers 173 assert( *len_d >= KEY_LENGTH_OCTETS );
smg_comms_c_wrappers 174 assert( *len_p >= KEY_LENGTH_OCTETS / 2);
smg_comms_c_wrappers 175 assert( *len_q >= KEY_LENGTH_OCTETS / 2);
smg_comms_c_wrappers 176 assert( *len_u >= KEY_LENGTH_OCTETS / 2);
smg_comms_c_wrappers 177
smg_comms_c_wrappers 178 //the secret key structure that will hold generated key components
smg_comms_c_wrappers 179 RSA_secret_key sk;
smg_comms_c_wrappers 180 int nlimbs = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS );
smg_comms_c_wrappers 181 int nlimbs_pq = mpi_nlimb_hint_from_nbytes( KEY_LENGTH_OCTETS / 2 );
smg_comms_c_wrappers 182
smg_comms_c_wrappers 183 sk.n = mpi_alloc(nlimbs);
smg_comms_c_wrappers 184 sk.e = mpi_alloc(nlimbs);
smg_comms_c_wrappers 185 sk.d = mpi_alloc(nlimbs);
smg_comms_c_wrappers 186 sk.p = mpi_alloc(nlimbs_pq);
smg_comms_c_wrappers 187 sk.q = mpi_alloc(nlimbs_pq);
smg_comms_c_wrappers 188 sk.u = mpi_alloc(nlimbs_pq);
smg_comms_c_wrappers 189
smg_comms_c_wrappers 190 //generate the rsa key pair - this may take a while!
smg_comms_c_wrappers 191 gen_keypair(&sk);
smg_comms_c_wrappers 192
smg_comms_c_wrappers 193 //copy components to their place
smg_comms_c_wrappers 194 mpi_to_octets( n, len_n, sk.n );
smg_comms_c_wrappers 195 mpi_to_octets( e, len_e, sk.e );
smg_comms_c_wrappers 196 mpi_to_octets( d, len_d, sk.d );
smg_comms_c_wrappers 197 mpi_to_octets( p, len_p, sk.p );
smg_comms_c_wrappers 198 mpi_to_octets( q, len_q, sk.q );
smg_comms_c_wrappers 199 mpi_to_octets( u, len_u, sk.u );
smg_comms_c_wrappers 200
smg_comms_c_wrappers 201 //tidy up: free ALL MPIs
smg_comms_c_wrappers 202 mpi_free(sk.n);
smg_comms_c_wrappers 203 mpi_free(sk.e);
smg_comms_c_wrappers 204 mpi_free(sk.d);
smg_comms_c_wrappers 205 mpi_free(sk.p);
smg_comms_c_wrappers 206 mpi_free(sk.q);
smg_comms_c_wrappers 207 mpi_free(sk.u);
smg_comms_c_wrappers 208 }
smg_comms_c_wrappers 209
smg_comms_c_wrappers 210 void mpi_to_octets( char *out, unsigned int *len_out, MPI m) {
smg_comms_c_wrappers 211 //copy the components as raw octets to the given pointers
smg_comms_c_wrappers 212 int len = 0;
smg_comms_c_wrappers 213 int sign;
smg_comms_c_wrappers 214 unsigned char * buffer = mpi_get_buffer( m, &len, &sign );
smg_comms_c_wrappers 215
smg_comms_c_wrappers 216 //check and don't copy MORE than there is allocated space in out!
smg_comms_c_wrappers 217 assert( len <= *len_out );
smg_comms_c_wrappers 218 memmove( out, buffer, len );
smg_comms_c_wrappers 219 *len_out = len; //save actual length of the component
smg_comms_c_wrappers 220
smg_comms_c_wrappers 221 xfree( buffer ); //free the buffer that was allocated by mpi_get_buffer
smg_comms_c_wrappers 222 }
smg_comms_shorter_e 223
smg_comms_shorter_e 224 void mpi_set_normalized(MPI m, const char *buffer,
smg_comms_shorter_e 225 unsigned int noctets, int sign) {
smg_comms_shorter_e 226 mpi_set_buffer( m, buffer, noctets, sign );
smg_comms_shorter_e 227 mpi_normalize( m );
smg_comms_shorter_e 228 }