root/openpgpsdk/trunk/src/lib/adv_openssl_crypto.c

Revision 558 (checked in by rachel, 5 years ago)

Implemented basic transferable public & secret keys (binary format).
Implemented key signing.
Renamed key_data struct to keydata.
Added tests for key generation and signing.

Line 
1 /** \file
2  */
3
4 #include <openpgpsdk/configure.h>
5 #include <openpgpsdk/crypto.h>
6 #include <openpgpsdk/keyring.h>
7 #include <openpgpsdk/readerwriter.h>
8 #include "keyring_local.h"
9 #include <openpgpsdk/std_print.h>
10 #include <openssl/md5.h>
11 #include <openssl/sha.h>
12 #include <openssl/dsa.h>
13 #include <openssl/rsa.h>
14 #include <openssl/err.h>
15 #include <assert.h>
16 #include <stdlib.h>
17
18 #include <openpgpsdk/final.h>
19
20 static int debug=0;
21
22 void test_secret_key(const ops_secret_key_t *skey)
23     {
24     RSA* test=RSA_new();
25
26     test->n=BN_dup(skey->public_key.key.rsa.n);
27     test->e=BN_dup(skey->public_key.key.rsa.e);
28
29     test->d=BN_dup(skey->key.rsa.d);
30     test->p=BN_dup(skey->key.rsa.p);
31     test->q=BN_dup(skey->key.rsa.q);
32
33     assert(RSA_check_key(test)==1);
34     RSA_free(test);
35     }
36
37 static void md5_init(ops_hash_t *hash)
38     {
39     assert(!hash->data);
40     hash->data=malloc(sizeof(MD5_CTX));
41     MD5_Init(hash->data);
42     }
43
44 static void md5_add(ops_hash_t *hash,const unsigned char *data,unsigned length)
45     {
46     MD5_Update(hash->data,data,length);
47     }
48
49 static unsigned md5_finish(ops_hash_t *hash,unsigned char *out)
50     {
51     MD5_Final(out,hash->data);
52     free(hash->data);
53     hash->data=NULL;
54     return 16;
55     }
56
57 static ops_hash_t md5={OPS_HASH_MD5,MD5_DIGEST_LENGTH,"MD5",md5_init,md5_add,
58                        md5_finish,NULL};
59
60 void ops_hash_md5(ops_hash_t *hash)
61     {
62     *hash=md5;
63     }
64
65 static void sha1_init(ops_hash_t *hash)
66     {
67     if (debug)
68         {
69         fprintf(stderr,"***\n***\nsha1_init\n***\n");
70         }
71     assert(!hash->data);
72     hash->data=malloc(sizeof(SHA_CTX));
73     SHA1_Init(hash->data);
74     }
75
76 static void sha1_add(ops_hash_t *hash,const unsigned char *data,
77                      unsigned length)
78     {
79     if (debug)
80         {
81         unsigned int i=0;
82         fprintf(stderr,"adding %d to hash:\n ", length);
83         for (i=0; i<length; i++)
84             {
85             fprintf(stderr,"0x%02x ", data[i]);
86             if (!((i+1) % 16))
87                 fprintf(stderr,"\n");
88             else if (!((i+1) % 8))
89                 fprintf(stderr,"  ");
90             }
91         fprintf(stderr,"\n");
92         }
93     SHA1_Update(hash->data,data,length);
94     }
95
96 static unsigned sha1_finish(ops_hash_t *hash,unsigned char *out)
97     {
98     SHA1_Final(out,hash->data);
99     if (debug)
100         {
101         unsigned i=0;
102         fprintf(stderr,"***\n***\nsha1_finish\n***\n");
103         for (i=0; i<20; i++)
104             fprintf(stderr,"0x%02x ",out[i]);
105         fprintf(stderr,"\n");
106         }
107     free(hash->data);
108     hash->data=NULL;
109     return 20;
110     }
111
112 static ops_hash_t sha1={OPS_HASH_SHA1,SHA_DIGEST_LENGTH,"SHA1",sha1_init,
113                         sha1_add,sha1_finish,NULL};
114
115 void ops_hash_sha1(ops_hash_t *hash)
116     {
117     *hash=sha1;
118     }
119
120 ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length,
121                              const ops_dsa_signature_t *sig,
122                              const ops_dsa_public_key_t *dsa)
123     {
124     DSA_SIG *osig;
125     DSA *odsa;
126     int ret;
127
128     osig=DSA_SIG_new();
129     osig->r=sig->r;
130     osig->s=sig->s;
131
132     odsa=DSA_new();
133     odsa->p=dsa->p;
134     odsa->q=dsa->q;
135     odsa->g=dsa->g;
136     odsa->pub_key=dsa->y;
137
138     ret=DSA_do_verify(hash,hash_length,osig,odsa);
139     assert(ret >= 0);
140
141     odsa->p=odsa->q=odsa->g=odsa->pub_key=NULL;
142     DSA_free(odsa);
143  
144     osig->r=osig->s=NULL;
145     DSA_SIG_free(osig);
146
147     return ret != 0;
148     }
149
150 int ops_rsa_public_decrypt(unsigned char *out,const unsigned char *in,
151                            size_t length,const ops_rsa_public_key_t *rsa)
152     {
153     RSA *orsa;
154     int n;
155
156     orsa=RSA_new();
157     orsa->n=rsa->n;
158     orsa->e=rsa->e;
159
160     n=RSA_public_decrypt(length,in,out,orsa,RSA_NO_PADDING);
161
162     orsa->n=orsa->e=NULL;
163     RSA_free(orsa);
164
165     return n;
166     }
167
168 int ops_rsa_private_encrypt(unsigned char *out,const unsigned char *in,
169                             size_t length,const ops_rsa_secret_key_t *srsa,
170                             const ops_rsa_public_key_t *rsa)
171     {
172     RSA *orsa;
173     int n;
174
175     orsa=RSA_new();
176     orsa->n=rsa->n;     // XXX: do we need n?
177     orsa->d=srsa->d;
178     orsa->p=srsa->q;
179     orsa->q=srsa->p;
180
181     /* debug */
182     orsa->e=rsa->e;
183     assert(RSA_check_key(orsa) == 1);
184     orsa->e=NULL;
185     /* end debug */
186
187     n=RSA_private_encrypt(length,in,out,orsa,RSA_NO_PADDING);
188
189     orsa->n=orsa->d=orsa->p=orsa->q=NULL;
190     RSA_free(orsa);
191
192     return n;
193     }
194
195 int ops_rsa_private_decrypt(unsigned char *out,const unsigned char *in,
196                             size_t length,const ops_rsa_secret_key_t *srsa,
197                             const ops_rsa_public_key_t *rsa)
198     {
199     RSA *orsa;
200     int n;
201     char errbuf[1024];
202
203     orsa=RSA_new();
204     orsa->n=rsa->n;     // XXX: do we need n?
205     orsa->d=srsa->d;
206     orsa->p=srsa->q;
207     orsa->q=srsa->p;
208
209     /* debug */
210     orsa->e=rsa->e;
211     assert(RSA_check_key(orsa) == 1);
212     orsa->e=NULL;
213     /* end debug */
214
215     n=RSA_private_decrypt(length,in,out,orsa,RSA_NO_PADDING);
216
217     //    printf("ops_rsa_private_decrypt: n=%d\n",n);
218
219     errbuf[0]='\0';
220     if (n==-1)
221         {
222         unsigned long err=ERR_get_error();
223         ERR_error_string(err,&errbuf[0]);
224         fprintf(stderr,"openssl error : %s\n",errbuf);
225         }
226     orsa->n=orsa->d=orsa->p=orsa->q=NULL;
227     RSA_free(orsa);
228
229     return n;
230     }
231
232 int ops_rsa_public_encrypt(unsigned char *out,const unsigned char *in,
233                            size_t length,const ops_rsa_public_key_t *rsa)
234     {
235     RSA *orsa;
236     int n;
237
238     //    printf("ops_rsa_public_encrypt: length=%ld\n", length);
239
240     orsa=RSA_new();
241     orsa->n=rsa->n;
242     orsa->e=rsa->e;
243
244     //    printf("len: %ld\n", length);
245     //    ops_print_bn("n: ", orsa->n);
246     //    ops_print_bn("e: ", orsa->e);
247     n=RSA_public_encrypt(length,in,out,orsa,RSA_NO_PADDING);
248
249     if (n==-1)
250         {
251         BIO *out;
252         out=BIO_new_fd(fileno(stderr), BIO_NOCLOSE);
253         ERR_print_errors(out);
254         }
255
256     orsa->n=orsa->e=NULL;
257     RSA_free(orsa);
258
259     return n;
260     }
261
262 void ops_crypto_init()
263     {
264 #ifdef DMALLOC
265     CRYPTO_malloc_debug_init();
266     CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL);
267     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
268 #endif
269     }
270
271 void ops_crypto_finish()
272     {
273     CRYPTO_cleanup_all_ex_data();
274     ERR_remove_state(0);
275 #ifdef DMALLOC
276     CRYPTO_mem_leaks_fp(stderr);
277 #endif
278     }
279
280 const char *ops_text_from_hash(ops_hash_t *hash)
281     { return hash->name; }
282
283 ops_boolean_t ops_rsa_generate_keypair(const int numbits, const unsigned long e, ops_keydata_t* keydata)
284     {
285     ops_secret_key_t *skey=NULL;
286     RSA *rsa=NULL;
287     BN_CTX *ctx=BN_CTX_new();
288
289     ops_keydata_init(keydata,OPS_PTAG_CT_SECRET_KEY);
290     skey=ops_get_writable_secret_key_from_data(keydata);
291
292     // generate the key pair
293
294     rsa=RSA_generate_key(numbits,e,NULL,NULL);
295
296     // populate ops key from ssl key
297
298     skey->public_key.version=4;
299     //\todo    skey->public_key.creation_time=NULL; // \todo
300     skey->public_key.days_valid=0;
301     skey->public_key.algorithm= OPS_PKA_RSA;
302
303     skey->public_key.key.rsa.n=BN_dup(rsa->n);
304     skey->public_key.key.rsa.e=BN_dup(rsa->e);
305
306     skey->s2k_usage=OPS_S2KU_ENCRYPTED_AND_HASHED;
307     // \todo     skey->s2k_specifier_t=OPS_S2KS_SALTED;
308     skey->s2k_specifier=OPS_S2KS_SIMPLE;
309     skey->algorithm=OPS_SA_CAST5; // \todo make param
310     skey->hash_algorithm=OPS_HASH_SHA1; // \todo make param
311     skey->octet_count=0;
312     skey->checksum=0;
313
314     skey->key.rsa.d=BN_dup(rsa->d);
315     skey->key.rsa.p=BN_dup(rsa->p);
316     skey->key.rsa.q=BN_dup(rsa->q);
317     skey->key.rsa.u=BN_mod_inverse(NULL,rsa->p, rsa->q, ctx);
318     assert(skey->key.rsa.u);
319     BN_CTX_free(ctx);
320
321     RSA_free(rsa);
322
323     ops_keyid(keydata->key_id, &keydata->key.skey.public_key);
324     ops_fingerprint(&keydata->fingerprint, &keydata->key.skey.public_key);
325
326     // Generate checksum
327
328     ops_create_info_t *cinfo=NULL;
329     ops_memory_t *mem=NULL;
330
331     ops_setup_memory_write(&cinfo, &mem, 128);
332
333     ops_push_skey_checksum_writer(cinfo, skey);
334
335     switch(skey->public_key.algorithm)
336         {
337         //    case OPS_PKA_DSA:
338         //      return ops_write_mpi(key->key.dsa.x,info);
339
340     case OPS_PKA_RSA:
341     case OPS_PKA_RSA_ENCRYPT_ONLY:
342     case OPS_PKA_RSA_SIGN_ONLY:
343         if(!ops_write_mpi(skey->key.rsa.d,cinfo)
344            || !ops_write_mpi(skey->key.rsa.p,cinfo)
345            || !ops_write_mpi(skey->key.rsa.q,cinfo)
346            || !ops_write_mpi(skey->key.rsa.u,cinfo))
347             return ops_false;
348         break;
349
350         //    case OPS_PKA_ELGAMAL:
351         //      return ops_write_mpi(key->key.elgamal.x,info);
352
353     default:
354         assert(0);
355         break;
356         }
357
358     // close rather than pop, since its the only one on the stack
359     ops_writer_close(cinfo);
360     ops_teardown_memory_write(cinfo, mem);
361
362     // should now have checksum in skey struct
363
364     // test
365     if (debug)
366         test_secret_key(skey);
367
368     return ops_true;
369     }
370
371 ops_keydata_t* ops_rsa_create_selfsigned_keypair(const int numbits, const unsigned long e, ops_user_id_t * userid)
372     {
373     ops_keydata_t *keydata=NULL;
374
375     keydata=ops_keydata_new();
376
377     if (ops_rsa_generate_keypair(numbits, e, keydata) != ops_true
378         || ops_add_selfsigned_userid_to_keydata(keydata, userid) != ops_true)
379         {
380         ops_keydata_free(keydata);
381         return NULL;
382         }
383
384     return keydata;
385     }
386
387 // eof
388
Note: See TracBrowser for help on using the browser.