root/openpgpsdk/trunk/tests/test_common.c

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

Added decompression tests.
Added arrays of valid/invalid/unknown keys to validation result.
Added example validation callback to show where to add additional tests.

Line 
1 #include <assert.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #ifndef WIN32
6 #include <unistd.h>
7 #endif
8 #include <sys/stat.h>
9
10 #include "CUnit/Basic.h"
11 #include "openpgpsdk/readerwriter.h"
12 #include "openpgpsdk/std_print.h"
13 // \todo remove the need for this
14 #include "../src/advanced/parse_local.h"
15
16 #include "tests.h"
17
18 char dir[MAXBUF+1];
19 char gpgcmd[MAXBUF+1];
20 ops_keyring_t pub_keyring;
21 ops_keyring_t sec_keyring;
22 static char* no_passphrase="";
23 ops_memory_t* mem_literal_data=NULL;
24
25 char *alpha_user_id="Alpha (RSA, no passphrase) <alpha@test.com>";
26 char *alpha_name="Alpha";
27 const ops_public_key_t *alpha_pkey;
28 const ops_secret_key_t *alpha_skey;
29 const ops_key_data_t *alpha_pub_keydata;
30 const ops_key_data_t *alpha_sec_keydata;
31 char* alpha_passphrase="";
32
33 char *bravo_user_id="Bravo (RSA, passphrase) <bravo@test.com>";
34 char *bravo_name="Bravo";
35 const ops_public_key_t *bravo_pkey;
36 const ops_secret_key_t *bravo_skey;
37 const ops_key_data_t *bravo_pub_keydata;
38 const ops_key_data_t *bravo_sec_keydata;
39 char* bravo_passphrase="hello";
40
41 const ops_key_data_t *decrypter=NULL;
42
43 static void setup_test_keys();
44
45 void setup()
46     {
47     // Create temp directory
48     if (!mktmpdir())
49         return;
50
51     assert(strlen(dir));
52     snprintf(gpgcmd,sizeof gpgcmd,"gpg --quiet --no-tty --homedir=%s --openpgp",dir);
53
54     setup_test_keys();
55     }
56
57 static void setup_test_keys()
58     {
59     char keydetails[MAXBUF+1];
60     char keyring_name[MAXBUF+1];
61     int fd=0;
62     char cmd[MAXBUF+1];
63
64     char *rsa_nopass="Key-Type: RSA\nKey-Usage: encrypt, sign\nName-Real: Alpha\nName-Comment: RSA, no passphrase\nName-Email: alpha@test.com\nKey-Length: 1024\n";
65     char *rsa_pass="Key-Type: RSA\nKey-Usage: encrypt, sign\nName-Real: Bravo\nName-Comment: RSA, passphrase\nName-Email: bravo@test.com\nPassphrase: hello\nKey-Length: 1024\n";
66
67     /*
68      * Create a RSA keypair with no passphrase
69      */
70
71     snprintf(keydetails,sizeof keydetails,"%s/%s",dir,"keydetails.alpha");
72
73 #ifdef WIN32
74     if ((fd=open(keydetails,O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))<0)
75 #else
76     if ((fd=open(keydetails,O_WRONLY | O_CREAT | O_EXCL, 0600))<0)
77 #endif
78         {
79         fprintf(stderr,"Can't create Alpha key details\n");
80         return;
81         }
82
83     write(fd,rsa_nopass,strlen(rsa_nopass));
84     close(fd);
85
86     snprintf(cmd,sizeof cmd,"%s --openpgp --gen-key --s2k-cipher-algo \"AES\" --expert --batch %s",gpgcmd,keydetails);
87     system(cmd);
88
89     /*
90      * Create a RSA keypair with passphrase
91      */
92
93     snprintf(keydetails,sizeof keydetails,"%s/%s",dir,"keydetails.bravo");
94
95 #ifdef WIN32
96     if ((fd=open(keydetails,O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))<0)
97 #else
98     if ((fd=open(keydetails,O_WRONLY | O_CREAT | O_EXCL, 0600))<0)
99 #endif
100         {
101         fprintf(stderr,"Can't create Bravo key details\n");
102         return;
103         }
104
105     write(fd,rsa_pass,strlen(rsa_pass));
106     close(fd);
107
108     snprintf(cmd,sizeof cmd,"%s --openpgp --gen-key --s2k-cipher-algo \"AES\" --expert --batch %s",gpgcmd,keydetails);
109     system(cmd);
110    
111     /*
112      * read keyrings
113      */
114
115     snprintf(keyring_name,sizeof keyring_name,"%s/pubring.gpg", dir);
116     ops_keyring_read(&pub_keyring,keyring_name);
117
118     snprintf(keyring_name,sizeof keyring_name,"%s/secring.gpg", dir);
119     ops_keyring_read(&sec_keyring,keyring_name);
120
121     /*
122      * set up key pointers
123      */
124
125     assert(pub_keyring.nkeys);
126
127     alpha_pub_keydata=ops_keyring_find_key_by_userid(&pub_keyring, alpha_user_id);
128     bravo_pub_keydata=ops_keyring_find_key_by_userid(&pub_keyring, bravo_user_id);
129     assert(alpha_pub_keydata);
130     assert(bravo_pub_keydata);
131
132     alpha_sec_keydata=ops_keyring_find_key_by_userid(&sec_keyring, alpha_user_id);
133     bravo_sec_keydata=ops_keyring_find_key_by_userid(&sec_keyring, bravo_user_id);
134     assert(alpha_sec_keydata);
135     assert(bravo_sec_keydata);
136
137     alpha_pkey=ops_get_public_key_from_data(alpha_pub_keydata);
138     alpha_skey=ops_get_secret_key_from_data(alpha_sec_keydata);
139     bravo_pkey=ops_get_public_key_from_data(bravo_pub_keydata);
140     bravo_skey=ops_decrypt_secret_key_from_data(bravo_sec_keydata,bravo_passphrase);
141
142     assert(alpha_pkey);
143     assert(alpha_skey);
144     assert(bravo_pkey);
145     assert(bravo_skey); //not yet set because of passphrase
146     }
147
148 void cleanup()
149     {
150     char cmd[MAXBUF];
151
152     return;
153
154     /* Remove test dir and files */
155     snprintf(cmd,sizeof cmd,"rm -rf %s", dir);
156     if (system(cmd))
157         {
158         perror("Can't delete test directory ");
159         return;
160         }
161     }
162
163 int mktmpdir (void)
164     {
165     int limit=10; // don't try indefinitely
166     long int rnd=0;
167
168 #ifdef WIN32
169     srand( (unsigned)time( NULL ) );
170 #endif
171     while (limit--)
172         {
173         rnd=random();
174         snprintf(dir,sizeof dir,"./testdir.%ld",rnd);
175        
176         // Try to create directory
177 #ifndef WIN32
178         if (!mkdir(dir,0700))
179 #else
180         if (!_mkdir(dir))
181 #endif
182             {
183             // success
184             return 1;
185             }
186         else
187             {
188             fprintf (stderr,"Couldn't open dir: errno=%d\n", errno);
189             perror(NULL);
190             }
191         }
192     fprintf(stderr,"Too many temp dirs: please delete them\n");
193     exit(1);
194     }
195
196 char* create_testtext(const char *text)
197     {
198     const unsigned int repeats=10;
199     unsigned int i=0;
200
201     const unsigned int maxbuf=1024;
202     char buf[maxbuf+1];
203     unsigned int sz_one=0;
204     unsigned int sz_big=0;
205     char* bigbuf=NULL;
206
207     buf[maxbuf]='\0';
208     snprintf(buf,sizeof buf,"%s : Test Text\n", text);
209
210     sz_one=strlen(buf);
211     sz_big=sz_one*repeats+1;
212
213     bigbuf=ops_mallocz(sz_big);
214
215    for (i=0; i<repeats; i++)
216         {
217         char* ptr=bigbuf+ (i*(sz_one-1));
218         snprintf(ptr,sz_one,buf);
219         }
220
221    return bigbuf;
222     }
223
224 void create_testdata(const char *text, unsigned char *buf, const int maxlen)
225     {
226     char *preamble=" : Test Data :";
227     int i=0;
228
229     snprintf((char *)buf,maxlen,"%s%s", text, preamble);
230
231 #ifdef WIN32
232     srand( (unsigned)time( NULL ) );
233 #endif
234     for (i=strlen(text)+strlen(preamble); i<maxlen; i++)
235         {
236         buf[i]=(random() & 0xFF);
237         }
238     }
239
240 void create_testfile(const char *name)
241     {
242     char filename[MAXBUF+1];
243     char* testtext=NULL;
244
245     int fd=0;
246     snprintf(filename,sizeof filename,"%s/%s",dir,name);
247 #ifdef WIN32
248     if ((fd=open(filename,O_WRONLY| O_CREAT | O_EXCL | O_BINARY, 0600))<0)
249 #else
250     if ((fd=open(filename,O_WRONLY| O_CREAT | O_EXCL, 0600))<0)
251 #endif
252         return;
253
254     testtext=create_testtext(name);
255     write(fd,testtext,strlen(testtext));
256     close(fd);
257     free(testtext);
258     }
259
260 ops_parse_cb_return_t
261 callback_general(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
262     {
263     int debug=0;
264
265     ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
266    
267     OPS_USED(cbinfo);
268    
269     //    ops_print_packet(content_);
270     
271     switch(content_->tag)
272         {
273     case OPS_PARSER_PTAG:
274         // ignore
275         break;
276        
277     case OPS_PARSER_PACKET_END:
278         // print raw packet
279
280         if (debug)
281             {
282             unsigned i=0;
283             fprintf(stderr,"***\n***Raw Packet:\n");
284             for (i=0; i<content_->content.packet.length; i++)
285                 {
286                 fprintf(stderr,"0x%02x ", content_->content.packet.raw[i]);
287                 if (!((i+1) % 16))
288                     fprintf(stderr,"\n");
289                 else if (!((i+1) % 8))
290                     fprintf(stderr,"  ");
291                 }
292             fprintf(stderr,"\n");
293             }
294         break;
295
296     case OPS_PARSER_ERROR:
297         printf("parse error: %s\n",content->error.error);
298         break;
299        
300     case OPS_PARSER_ERRCODE:
301         printf("parse error: %s\n",
302                ops_errcode(content->errcode.errcode));
303         break;
304        
305     default:
306         fprintf(stderr,"Unexpected packet tag=%d (0x%x)\n",content_->tag,
307                 content_->tag);
308         assert(0);
309         }
310    
311     return OPS_RELEASE_MEMORY;
312     }
313
314 ops_parse_cb_return_t
315 callback_cmd_get_secret_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
316     {
317     ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
318     const ops_key_data_t *keydata=NULL;
319     const ops_secret_key_t *secret;
320     char *passphrase=NULL;
321
322     OPS_USED(cbinfo);
323
324 //    ops_print_packet(content_);
325
326     switch(content_->tag)
327         {
328     case OPS_PARSER_CMD_GET_SECRET_KEY:
329         keydata=ops_keyring_find_key_by_id(&sec_keyring,content->get_secret_key.pk_session_key->key_id);
330         if (!keydata || !ops_key_is_secret(keydata))
331             return 0;
332
333         // Do we need the passphrase and not have it? If so, get it
334         passphrase=NULL;
335
336         /*
337          * Hard-coded to allow automated test
338          */
339         if (keydata==alpha_sec_keydata)
340             passphrase=alpha_passphrase;
341         else if (keydata==bravo_sec_keydata)
342             passphrase=bravo_passphrase;
343         else
344             assert(0);
345
346         /* now get the key from the data */
347         secret=ops_get_secret_key_from_data(keydata);
348         while(!secret)
349             {
350             /* then it must be encrypted */
351             secret=ops_decrypt_secret_key_from_data(keydata,passphrase);
352             }
353        
354         *content->get_secret_key.secret_key=secret;
355         break;
356
357     default:
358         return callback_general(content_,cbinfo);
359         }
360    
361     return OPS_RELEASE_MEMORY;
362     }
363
364 ops_parse_cb_return_t
365 callback_cmd_get_secret_key_passphrase(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
366     {
367     ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
368
369     OPS_USED(cbinfo);
370
371 //    ops_print_packet(content_);
372
373     switch(content_->tag)
374         {
375     case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
376         /*
377           Doing this so the test can be automated.
378         */
379         *(content->secret_key_passphrase.passphrase)=ops_malloc_passphrase(no_passphrase);
380         return OPS_KEEP_MEMORY;
381         break;
382        
383     default:
384         return callback_general(content_,cbinfo);
385         }
386    
387     return OPS_RELEASE_MEMORY;
388     }
389
390 ops_parse_cb_return_t
391 callback_literal_data(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
392     {
393     ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
394
395     OPS_USED(cbinfo);
396
397     //    ops_print_packet(content_);
398
399     // Read data from packet into static buffer
400     switch(content_->tag)
401         {
402     case OPS_PTAG_CT_LITERAL_DATA_BODY:
403         ops_memory_add(mem_literal_data,
404                        content->literal_data_body.data,
405                        content->literal_data_body.length);
406         break;
407
408     case OPS_PTAG_CT_LITERAL_DATA_HEADER:
409         // ignore
410         break;
411
412     default:
413         return callback_general(content_,cbinfo);
414         }
415
416     return OPS_RELEASE_MEMORY;
417     }
418  
419 // move definition to better location
420 ops_parse_cb_return_t
421 validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
422 ops_parse_cb_return_t
423 validate_data_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo);
424
425 ops_parse_cb_return_t
426 callback_data_signature(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
427     {
428     //    ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
429
430     OPS_USED(cbinfo);
431
432     //    ops_print_packet(content_);
433
434     switch(content_->tag)
435         {
436     case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
437     case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
438     case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
439
440     case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
441     case OPS_PTAG_CT_SIGNATURE_HEADER:
442     case OPS_PTAG_CT_SIGNATURE_FOOTER:
443
444     case OPS_PTAG_CT_LITERAL_DATA_HEADER:
445     case OPS_PTAG_CT_LITERAL_DATA_BODY:
446
447     case OPS_PTAG_CT_SIGNATURE:
448         return validate_data_cb(content_,cbinfo);
449         break;
450
451     default:
452         return callback_general(content_,cbinfo);
453         }
454
455     return OPS_RELEASE_MEMORY;
456     }
457  
458 ops_parse_cb_return_t
459 callback_verify(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
460     {
461     /*
462     int debug=0;
463
464     if (debug)
465         { ops_print_packet(content_); }
466     */
467     switch(content_->tag)
468         {
469     case OPS_PTAG_RAW_SS:
470     case OPS_PTAG_SS_CREATION_TIME:
471     case OPS_PTAG_SS_ISSUER_KEY_ID:
472         // \todo should free memory?
473         return OPS_KEEP_MEMORY;
474        
475     case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
476     case OPS_PTAG_CT_ARMOUR_HEADER:
477     case OPS_PTAG_CT_ARMOUR_TRAILER:
478         break;
479
480     case OPS_PTAG_CT_UNARMOURED_TEXT:
481         break;
482        
483     case OPS_PTAG_CT_SIGNATURE:
484     case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
485     case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
486     case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
487     case OPS_PTAG_CT_SIGNATURE_HEADER:
488     case OPS_PTAG_CT_SIGNATURE_FOOTER:
489     case OPS_PTAG_CT_LITERAL_DATA_HEADER:
490     case OPS_PTAG_CT_LITERAL_DATA_BODY:
491         return callback_data_signature(content_, cbinfo);
492
493     default:
494         return callback_general(content_,cbinfo);
495         }
496
497     return OPS_RELEASE_MEMORY;
498     }
499
500 ops_parse_cb_return_t
501 callback_verify_example(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
502     {
503     ops_parse_cb_return_t rtn;
504
505     // run standard callback
506     rtn=callback_verify(content_,cbinfo);
507
508     // do extra work here, if needed
509     switch(content_->tag)
510         {
511     case OPS_PTAG_CT_SIGNATURE_FOOTER:
512
513         // When we get this tag, we know that the signature
514         // has been parsed. The signature struct has been filled in
515         // with everything known about the signature.
516
517         // example: print out the signature creation time
518         if (content_->content.signature.creation_time_set)
519             {
520             printf("\nsignature creation time : %s",
521                    ctime(&content_->content.signature.creation_time));
522             }
523         break;
524
525     default:
526         break;
527         }
528
529     return rtn;
530         }
531
532 ops_parse_cb_return_t
533 callback_pk_session_key(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
534     {
535     ops_parser_content_union_t* content=(ops_parser_content_union_t *)&content_->content;
536    
537     OPS_USED(cbinfo);
538
539     //    ops_print_packet(content_);
540     
541     // Read data from packet into static buffer
542     switch(content_->tag)
543         {
544     case OPS_PTAG_CT_PK_SESSION_KEY:
545                 //      printf ("OPS_PTAG_CT_PK_SESSION_KEY\n");
546         if(decrypter)
547             break;
548
549         decrypter=ops_keyring_find_key_by_id(&sec_keyring,
550                                              content->pk_session_key.key_id);
551         if(!decrypter)
552             break;
553         break;
554
555     default:
556         return callback_general(content_,cbinfo);
557         }
558
559     return OPS_RELEASE_MEMORY;
560     }
561
562 void reset_vars()
563     {
564     ops_memory_init(mem_literal_data,0);
565
566     if (decrypter)
567         {
568         //        free (decrypter);
569         decrypter=NULL;
570         }
571     }
572
573 int file_compare(char* file1, char* file2)
574     {
575     FILE *fp1=NULL;
576     FILE *fp2=NULL;
577     char ch1, ch2;
578     int err=0;
579
580     // open files
581     if ((fp1=fopen(file1,"rb"))==NULL)
582         {
583         fprintf(stderr,"file_compare: cannot open file %s\n",file1);
584         return -1;
585         }
586     if ((fp2=fopen(file2,"rb"))==NULL)
587         {
588         fprintf(stderr,"file_compare: cannot open file %s\n",file2);
589         fclose(fp1);
590         return -1;
591         }
592
593     while(!feof(fp1))
594         {
595         ch1 = fgetc(fp1);
596         if (ferror(fp1))
597             {
598             fprintf(stderr,"file_compare: error reading from file %s\n",file1);
599             err = -1;
600             break;
601             }
602         ch2 = fgetc(fp2);
603         if (ferror(fp2))
604             {
605             fprintf(stderr,"file_compare: error reading from file %s\n",file2);
606             err = -1;
607             break;
608             }
609         if (ch1 != ch2)
610             {
611             printf("Files %s and %s differ\n",file1,file2);
612             err = 1;
613             break;
614             }
615         }
616     fclose(fp1);
617     fclose(fp2);
618     return err;
619     }
620
621 // EOF
622
Note: See TracBrowser for help on using the browser.