root/openpgpsdk/trunk/src/advanced/adv_validate.c

Revision 452 (checked in by ben, 6 years ago)

Improve workingness of tests.

Line 
1 #include <openpgpsdk/packet-parse.h>
2 #include <openpgpsdk/keyring.h>
3 #include "keyring_local.h"
4 #include <openpgpsdk/util.h>
5 #include <openpgpsdk/signature.h>
6 #include <openpgpsdk/validate.h>
7 #include <assert.h>
8 #include <string.h>
9
10 #include <openpgpsdk/final.h>
11
12 typedef struct
13     {
14     const ops_key_data_t *key;
15     unsigned packet;
16     unsigned offset;
17     } validate_reader_arg_t;
18
19 typedef struct
20     {
21     ops_public_key_t pkey;
22     ops_public_key_t subkey;
23     ops_user_id_t user_id;
24     const ops_keyring_t *keyring;
25     validate_reader_arg_t *rarg;
26     } validate_cb_arg_t;
27
28 static int key_data_reader(void *dest,size_t length,ops_error_t **errors,
29                            ops_reader_info_t *rinfo,
30                            ops_parse_cb_info_t *cbinfo)
31     {
32     validate_reader_arg_t *arg=ops_reader_get_arg(rinfo);
33
34     OPS_USED(errors);
35     OPS_USED(cbinfo);
36     if(arg->offset == arg->key->packets[arg->packet].length)
37         {
38         ++arg->packet;
39         arg->offset=0;
40         }
41
42     if(arg->packet == arg->key->npackets)
43         return 0;
44
45     // we should never be asked to cross a packet boundary in a single read
46     assert(arg->key->packets[arg->packet].length >= arg->offset+length);
47
48     memcpy(dest,&arg->key->packets[arg->packet].raw[arg->offset],length);
49     arg->offset+=length;
50
51     return length;
52     }
53
54 /**
55  * \ingroup Callbacks
56  */
57
58 static ops_parse_cb_return_t
59 validate_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
60     {
61     const ops_parser_content_union_t *content=&content_->content;
62     validate_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
63     const ops_key_data_t *signer;
64     ops_boolean_t valid;
65
66     switch(content_->tag)
67         {
68     case OPS_PTAG_CT_PUBLIC_KEY:
69         assert(arg->pkey.version == 0);
70         arg->pkey=content->public_key;
71         return OPS_KEEP_MEMORY;
72
73     case OPS_PTAG_CT_PUBLIC_SUBKEY:
74         if(arg->subkey.version)
75             ops_public_key_free(&arg->subkey);
76         arg->subkey=content->public_key;
77         return OPS_KEEP_MEMORY;
78
79     case OPS_PTAG_CT_USER_ID:
80         printf("user id=%s\n",content->user_id.user_id);
81         if(arg->user_id.user_id)
82             ops_user_id_free(&arg->user_id);
83         arg->user_id=content->user_id;
84         return OPS_KEEP_MEMORY;
85
86     case OPS_PTAG_CT_SIGNATURE_FOOTER:
87         printf("  type=%02x signer_id=",content->signature.type);
88         hexdump(content->signature.signer_id,
89                 sizeof content->signature.signer_id);
90
91         signer=ops_keyring_find_key_by_id(arg->keyring,
92                                            content->signature.signer_id);
93         if(!signer)
94             {
95             printf(" UNKNOWN SIGNER\n");
96             break;
97             }
98
99         switch(content->signature.type)
100             {
101         case OPS_CERT_GENERIC:
102         case OPS_CERT_PERSONA:
103         case OPS_CERT_CASUAL:
104         case OPS_CERT_POSITIVE:
105         case OPS_SIG_REV_CERT:
106             valid=ops_check_certification_signature(&arg->pkey,&arg->user_id,
107                     &content->signature,ops_get_public_key_from_data(signer),
108                     arg->rarg->key->packets[arg->rarg->packet].raw);
109             break;
110
111         case OPS_SIG_SUBKEY:
112             // XXX: we should also check that the signer is the key we are validating, I think.
113             valid=ops_check_subkey_signature(&arg->pkey,&arg->subkey,
114                     &content->signature,
115                     ops_get_public_key_from_data(signer),
116                     arg->rarg->key->packets[arg->rarg->packet].raw);
117             break;
118
119         case OPS_SIG_DIRECT:
120             valid=ops_check_direct_signature(&arg->pkey,&content->signature,
121                     ops_get_public_key_from_data(signer),
122                     arg->rarg->key->packets[arg->rarg->packet].raw);
123             break;
124
125         default:
126             fprintf(stderr,"Unexpected signature type=0x%02x\n",
127                     content->signature.type);
128             exit(1);
129             }
130         if(valid)
131             printf(" validated\n");
132         else
133             printf(" BAD SIGNATURE\n");
134         break;
135
136     default:
137         // XXX: reinstate when we can make packets optional
138         //      fprintf(stderr,"unexpected tag=%d\n",content_->tag);
139         break;
140         }
141     return OPS_RELEASE_MEMORY;
142     }
143
144 void ops_key_data_reader_set(ops_parse_info_t *pinfo,const ops_key_data_t *key)
145     {
146     validate_reader_arg_t *arg=malloc(sizeof *arg);
147
148     memset(arg,'\0',sizeof *arg);
149
150     arg->key=key;
151     arg->packet=0;
152     arg->offset=0;
153
154     ops_reader_set(pinfo,key_data_reader,arg);
155     }
156
157 static void validate_key_signatures(const ops_key_data_t *key,
158                                     const ops_keyring_t *keyring)
159     {
160     ops_parse_info_t *pinfo;
161     validate_cb_arg_t carg;
162
163     memset(&carg,'\0',sizeof carg);
164
165     pinfo=ops_parse_info_new();
166     //    ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED);
167
168     carg.keyring=keyring;
169
170     ops_parse_cb_set(pinfo,validate_cb,&carg);
171     ops_key_data_reader_set(pinfo,key);
172
173     carg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
174
175     ops_parse(pinfo);
176
177     ops_public_key_free(&carg.pkey);
178     if(carg.subkey.version)
179         ops_public_key_free(&carg.subkey);
180     ops_user_id_free(&carg.user_id);
181     }
182
183 void ops_validate_all_signatures(const ops_keyring_t *ring)
184     {
185     int n;
186
187     for(n=0 ; n < ring->nkeys ; ++n)
188         validate_key_signatures(&ring->keys[n],ring);
189     }
Note: See TracBrowser for help on using the browser.