root/openpgpsdk/trunk/src/validate.c

Revision 336 (checked in by ben, 7 years ago)

Another step closer to decryption.

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