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

Revision 666 (checked in by ben, 4 years ago)

Ignore trust packets.

Line 
1 /*
2  * Copyright (c) 2005-2008 Nominet UK (www.nic.uk)
3  * All rights reserved.
4  * Contributors: Ben Laurie, Rachel Willmer. The Contributors have asserted
5  * their moral rights under the UK Copyright Design and Patents Act 1988 to
6  * be recorded as the authors of this copyright work.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
9  * use this file except in compliance with the License.
10  *
11  * You may obtain a copy of the License at
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21
22 #include <openpgpsdk/packet-parse.h>
23 #include <openpgpsdk/packet-show.h>
24 #include <openpgpsdk/keyring.h>
25 #include "keyring_local.h"
26 #include "parse_local.h"
27 #include <openpgpsdk/util.h>
28 #include <openpgpsdk/armour.h>
29 #include <openpgpsdk/signature.h>
30 #include <openpgpsdk/memory.h>
31 #include <openpgpsdk/validate.h>
32 #include <openpgpsdk/readerwriter.h>
33 #include <assert.h>
34 #include <string.h>
35
36 #include <openpgpsdk/final.h>
37
38 static int debug=0;
39
40 static ops_boolean_t check_binary_signature(const unsigned len,
41                                             const unsigned char *data,
42                                             const ops_signature_t *sig,
43                                             const ops_public_key_t *signer __attribute__((unused)))
44     {
45     // Does the signed hash match the given hash?
46
47     int n=0;
48     ops_hash_t hash;
49     unsigned char hashout[OPS_MAX_HASH_SIZE];
50     unsigned char trailer[6];
51     unsigned int hashedlen;
52
53     //common_init_signature(&hash,sig);
54     ops_hash_any(&hash,sig->info.hash_algorithm);
55     hash.init(&hash);
56     hash.add(&hash,data,len);
57     switch (sig->info.version)
58         {
59     case OPS_V3:
60         trailer[0]=sig->info.type;
61         trailer[1]=sig->info.creation_time >> 24;
62         trailer[2]=sig->info.creation_time >> 16;
63         trailer[3]=sig->info.creation_time >> 8;
64         trailer[4]=sig->info.creation_time;
65         hash.add(&hash,&trailer[0],5);
66         break;
67
68     case OPS_V4:
69         hash.add(&hash,sig->info.v4_hashed_data,sig->info.v4_hashed_data_length);
70
71         trailer[0]=0x04; // version
72         trailer[1]=0xFF;
73         hashedlen=sig->info.v4_hashed_data_length;
74         trailer[2]=hashedlen >> 24;
75         trailer[3]=hashedlen >> 16;
76         trailer[4]=hashedlen >> 8;
77         trailer[5]=hashedlen;
78         hash.add(&hash,&trailer[0],6);
79        
80         break;
81
82     default:
83         fprintf(stderr,"Invalid signature version %d\n", sig->info.version);
84         return ops_false;
85         }
86
87     n=hash.finish(&hash,hashout);
88
89     //    return ops_false;
90     return ops_check_signature(hashout,n,sig,signer);
91     }
92
93 static int keydata_reader(void *dest,size_t length,ops_error_t **errors,
94                            ops_reader_info_t *rinfo,
95                            ops_parse_cb_info_t *cbinfo)
96     {
97     validate_reader_arg_t *arg=ops_reader_get_arg(rinfo);
98
99     OPS_USED(errors);
100     OPS_USED(cbinfo);
101     if(arg->offset == arg->key->packets[arg->packet].length)
102         {
103         ++arg->packet;
104         arg->offset=0;
105         }
106
107     if(arg->packet == arg->key->npackets)
108         return 0;
109
110     // we should never be asked to cross a packet boundary in a single read
111     assert(arg->key->packets[arg->packet].length >= arg->offset+length);
112
113     memcpy(dest,&arg->key->packets[arg->packet].raw[arg->offset],length);
114     arg->offset+=length;
115
116     return length;
117     }
118
119 static void free_signature_info(ops_signature_info_t *sig)
120     {
121     free (sig->v4_hashed_data);
122     free (sig);
123     }
124
125 static void copy_signature_info(ops_signature_info_t* dst, const ops_signature_info_t* src)
126     {
127     memcpy(dst,src,sizeof *src);
128     dst->v4_hashed_data=ops_mallocz(src->v4_hashed_data_length);
129     memcpy(dst->v4_hashed_data,src->v4_hashed_data,src->v4_hashed_data_length);
130     }
131
132 static void add_sig_to_valid_list(ops_validate_result_t * result, const ops_signature_info_t* sig)
133     {
134     size_t newsize;
135     size_t start;
136
137     // increment count
138     ++result->valid_count;
139
140     // increase size of array
141     newsize=(sizeof *sig) * result->valid_count;
142     if (!result->valid_sigs)
143         result->valid_sigs=malloc(newsize);
144     else
145         result->valid_sigs=realloc(result->valid_sigs, newsize);
146
147     // copy key ptr to array
148     start=(sizeof *sig) * (result->valid_count-1);
149     copy_signature_info(result->valid_sigs+start,sig);
150     }
151
152 static void add_sig_to_invalid_list(ops_validate_result_t * result, const ops_signature_info_t *sig)
153     {
154     size_t newsize;
155     size_t start;
156
157     // increment count
158     ++result->invalid_count;
159
160     // increase size of array
161     newsize=(sizeof *sig) * result->invalid_count;
162     if (!result->invalid_sigs)
163         result->invalid_sigs=malloc(newsize);
164     else
165         result->invalid_sigs=realloc(result->invalid_sigs, newsize);
166
167     // copy key ptr to array
168     start=(sizeof *sig) * (result->invalid_count-1);
169     copy_signature_info(result->invalid_sigs+start, sig);
170     }
171
172 static void add_sig_to_unknown_list(ops_validate_result_t * result, const ops_signature_info_t *sig)
173     {
174     size_t newsize;
175     size_t start;
176
177     // increment count
178     ++result->unknown_signer_count;
179
180     // increase size of array
181     newsize=(sizeof *sig) * result->unknown_signer_count;
182     if (!result->unknown_sigs)
183         result->unknown_sigs=malloc(newsize);
184     else
185         result->unknown_sigs=realloc(result->unknown_sigs, newsize);
186
187     // copy key id to array
188     start=OPS_KEY_ID_SIZE * (result->unknown_signer_count-1);
189     copy_signature_info(result->unknown_sigs+start, sig);
190     }
191
192 ops_parse_cb_return_t
193 ops_validate_key_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
194     {
195     const ops_parser_content_union_t *content=&content_->content;
196     validate_key_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
197     ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
198     const ops_keydata_t *signer;
199     ops_boolean_t valid=ops_false;
200
201     if (debug)
202         printf("%s\n",ops_show_packet_tag(content_->tag));
203
204     switch(content_->tag)
205         {
206     case OPS_PTAG_CT_PUBLIC_KEY:
207         assert(arg->pkey.version == 0);
208         arg->pkey=content->public_key;
209         return OPS_KEEP_MEMORY;
210        
211     case OPS_PTAG_CT_PUBLIC_SUBKEY:
212         if(arg->subkey.version)
213             ops_public_key_free(&arg->subkey);
214         arg->subkey=content->public_key;
215         return OPS_KEEP_MEMORY;
216        
217     case OPS_PTAG_CT_SECRET_KEY:
218         arg->skey=content->secret_key;
219         arg->pkey=arg->skey.public_key;
220         return OPS_KEEP_MEMORY;
221
222     case OPS_PTAG_CT_USER_ID:
223         if(arg->user_id.user_id)
224             ops_user_id_free(&arg->user_id);
225         arg->user_id=content->user_id;
226         arg->last_seen=ID;
227         return OPS_KEEP_MEMORY;
228
229     case OPS_PTAG_CT_USER_ATTRIBUTE:
230         assert(content->user_attribute.data.len);
231         printf("user attribute, length=%d\n",(int)content->user_attribute.data.len);
232         if(arg->user_attribute.data.len)
233             ops_user_attribute_free(&arg->user_attribute);
234         arg->user_attribute=content->user_attribute;
235         arg->last_seen=ATTRIBUTE;
236         return OPS_KEEP_MEMORY;
237
238     case OPS_PTAG_CT_SIGNATURE: // V3 sigs
239     case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs
240         /*
241         printf("  type=%02x signer_id=",content->signature.type);
242         hexdump(content->signature.signer_id,
243                 sizeof content->signature.signer_id);
244         */
245
246         signer=ops_keyring_find_key_by_id(arg->keyring,
247                                            content->signature.info.signer_id);
248         if(!signer)
249             {
250         add_sig_to_unknown_list(arg->result, &content->signature.info);
251             break;
252             }
253
254         switch(content->signature.info.type)
255             {
256         case OPS_CERT_GENERIC:
257         case OPS_CERT_PERSONA:
258         case OPS_CERT_CASUAL:
259         case OPS_CERT_POSITIVE:
260         case OPS_SIG_REV_CERT:
261             if(arg->last_seen == ID)
262                 valid=ops_check_user_id_certification_signature(&arg->pkey,
263                                                                 &arg->user_id,
264                                                                 &content->signature,
265                                                                 ops_get_public_key_from_data(signer),
266                                                                 arg->rarg->key->packets[arg->rarg->packet].raw);
267             else
268                 valid=ops_check_user_attribute_certification_signature(&arg->pkey,
269                                                                        &arg->user_attribute,
270                                                                        &content->signature,
271                                                                        ops_get_public_key_from_data(signer),
272                                                                        arg->rarg->key->packets[arg->rarg->packet].raw);
273                
274             break;
275
276         case OPS_SIG_SUBKEY:
277             // XXX: we should also check that the signer is the key we are validating, I think.
278             valid=ops_check_subkey_signature(&arg->pkey,&arg->subkey,
279                     &content->signature,
280                     ops_get_public_key_from_data(signer),
281                     arg->rarg->key->packets[arg->rarg->packet].raw);
282             break;
283
284         case OPS_SIG_DIRECT:
285             valid=ops_check_direct_signature(&arg->pkey,&content->signature,
286                     ops_get_public_key_from_data(signer),
287                     arg->rarg->key->packets[arg->rarg->packet].raw);
288             break;
289
290     case OPS_SIG_STANDALONE:
291     case OPS_SIG_PRIMARY:
292     case OPS_SIG_REV_KEY:
293     case OPS_SIG_REV_SUBKEY:
294     case OPS_SIG_TIMESTAMP:
295     case OPS_SIG_3RD_PARTY:
296         OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
297                     "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type);
298                     break;
299
300         default:
301             OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
302                     "Unexpected signature type 0x%02x\n", content->signature.info.type);
303             }
304
305         if(valid)
306             {
307         //          printf(" validated\n");
308             //++arg->result->valid_count;
309         add_sig_to_valid_list(arg->result, &content->signature.info);
310             }
311         else
312             {
313         OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature");
314         //          printf(" BAD SIGNATURE\n");
315         //          ++arg->result->invalid_count;
316         add_sig_to_invalid_list(arg->result, &content->signature.info);
317             }
318         break;
319
320         // ignore these
321     case OPS_PARSER_PTAG:
322     case OPS_PTAG_CT_SIGNATURE_HEADER:
323     case OPS_PARSER_PACKET_END:
324     case OPS_PTAG_CT_TRUST:
325         break;
326
327  case OPS_PARSER_CMD_GET_SK_PASSPHRASE:
328      if (arg->cb_get_passphrase)
329          {
330          return arg->cb_get_passphrase(content_,cbinfo);
331          }
332      break;
333
334     default:
335         fprintf(stderr,"unexpected tag=0x%x\n",content_->tag);
336         assert(0);
337         break;
338         }
339     return OPS_RELEASE_MEMORY;
340     }
341
342 ops_parse_cb_return_t
343 validate_data_cb(const ops_parser_content_t *content_,ops_parse_cb_info_t *cbinfo)
344     {
345     const ops_parser_content_union_t *content=&content_->content;
346     validate_data_cb_arg_t *arg=ops_parse_cb_get_arg(cbinfo);
347     ops_error_t **errors=ops_parse_cb_get_errors(cbinfo);
348     const ops_keydata_t *signer;
349     ops_boolean_t valid=ops_false;
350     ops_memory_t* mem=NULL;
351
352     if (debug)
353         printf("%s\n",ops_show_packet_tag(content_->tag));
354
355     switch(content_->tag)
356         {
357     case OPS_PTAG_CT_SIGNED_CLEARTEXT_HEADER:
358         // ignore - this gives us the "Armor Header" line "Hash: SHA1" or similar
359         break;
360
361     case OPS_PTAG_CT_LITERAL_DATA_HEADER:
362         // ignore
363         break;
364
365     case OPS_PTAG_CT_LITERAL_DATA_BODY:
366         arg->data.literal_data_body=content->literal_data_body;
367         arg->use=LITERAL_DATA;
368         return OPS_KEEP_MEMORY;
369         break;
370
371     case OPS_PTAG_CT_SIGNED_CLEARTEXT_BODY:
372         arg->data.signed_cleartext_body=content->signed_cleartext_body;
373         arg->use=SIGNED_CLEARTEXT;
374         return OPS_KEEP_MEMORY;
375         break;
376
377     case OPS_PTAG_CT_SIGNED_CLEARTEXT_TRAILER:
378         // this gives us an ops_hash_t struct
379         break;
380
381     case OPS_PTAG_CT_SIGNATURE: // V3 sigs
382     case OPS_PTAG_CT_SIGNATURE_FOOTER: // V4 sigs
383         
384         if (debug)
385             {
386             printf("\n*** hashed data:\n");
387             unsigned int zzz=0;
388             for (zzz=0; zzz<content->signature.info.v4_hashed_data_length; zzz++)
389                 printf("0x%02x ", content->signature.info.v4_hashed_data[zzz]);
390             printf("\n");
391             printf("  type=%02x signer_id=",content->signature.info.type);
392             hexdump(content->signature.info.signer_id,
393                     sizeof content->signature.info.signer_id);
394             }
395
396         signer=ops_keyring_find_key_by_id(arg->keyring,
397                                           content->signature.info.signer_id);
398         if(!signer)
399             {
400             OPS_ERROR(errors,OPS_E_V_UNKNOWN_SIGNER,"Unknown Signer");
401             add_sig_to_unknown_list(arg->result, &content->signature.info);
402             break;
403             }
404        
405         mem=ops_memory_new();
406         ops_memory_init(mem,128);
407        
408         switch(content->signature.info.type)
409             {
410         case OPS_SIG_BINARY:
411         case OPS_SIG_TEXT:
412             switch(arg->use)
413                 {
414             case LITERAL_DATA:
415                 ops_memory_add(mem,
416                                arg->data.literal_data_body.data,
417                                arg->data.literal_data_body.length);
418                 break;
419                
420             case SIGNED_CLEARTEXT:
421                 ops_memory_add(mem,
422                                arg->data.signed_cleartext_body.data,
423                                arg->data.signed_cleartext_body.length);
424                 break;
425                
426             default:
427                 OPS_ERROR_1(errors,OPS_E_UNIMPLEMENTED,"Unimplemented Sig Use %d", arg->use);
428                 printf(" Unimplemented Sig Use %d\n", arg->use);
429                 break;
430                 }
431            
432             valid=check_binary_signature(ops_memory_get_length(mem),
433                                          ops_memory_get_data(mem),
434                                          &content->signature,
435                                          ops_get_public_key_from_data(signer));
436             break;
437
438         default:
439             OPS_ERROR_1(errors, OPS_E_UNIMPLEMENTED,
440                         "Verification of signature type 0x%02x not yet implemented\n", content->signature.info.type);
441             break;
442            
443             }
444     ops_memory_free(mem);
445
446         if(valid)
447             {
448         add_sig_to_valid_list(arg->result, &content->signature.info);
449             }
450         else
451             {
452         OPS_ERROR(errors,OPS_E_V_BAD_SIGNATURE,"Bad Signature");
453         add_sig_to_invalid_list(arg->result, &content->signature.info);
454             }
455         break;
456
457         // ignore these
458  case OPS_PARSER_PTAG:
459  case OPS_PTAG_CT_SIGNATURE_HEADER:
460  case OPS_PTAG_CT_ARMOUR_HEADER:
461  case OPS_PTAG_CT_ARMOUR_TRAILER:
462  case OPS_PTAG_CT_ONE_PASS_SIGNATURE:
463  case OPS_PARSER_PACKET_END:
464         break;
465
466     default:
467         fprintf(stderr,"unexpected tag=0x%x\n",content_->tag);
468         assert(0);
469         break;
470         }
471     return OPS_RELEASE_MEMORY;
472     }
473
474 static void keydata_destroyer(ops_reader_info_t *rinfo)
475     { free(ops_reader_get_arg(rinfo)); }
476
477 void ops_keydata_reader_set(ops_parse_info_t *pinfo,const ops_keydata_t *key)
478     {
479     validate_reader_arg_t *arg=malloc(sizeof *arg);
480
481     memset(arg,'\0',sizeof *arg);
482
483     arg->key=key;
484     arg->packet=0;
485     arg->offset=0;
486
487     ops_reader_set(pinfo,keydata_reader,keydata_destroyer,arg);
488     }
489
490 /**
491  * \ingroup HighLevel_Verify
492  * \brief Indicicates whether any errors were found
493  * \param result Validation result to check
494  * \return ops_false if any invalid signatures or unknown signers or no valid signatures; else ops_true
495  */
496 ops_boolean_t validate_result_status(ops_validate_result_t* result)
497     {
498     if (result->invalid_count || result->unknown_signer_count || !result->valid_count)
499         return ops_false;
500     else
501         return ops_true;
502     }
503
504 /**
505  * \ingroup HighLevel_Verify
506  * \brief Validate all signatures on a single key against the given keyring
507  * \param result Where to put the result
508  * \param key Key to validate
509  * \param keyring Keyring to use for validation
510  * \param cb_get_passphrase Callback to use to get passphrase
511  * \return ops_true if all signatures OK; else ops_false
512  * \note It is the caller's responsiblity to free result after use.
513  * \sa ops_validate_result_free()
514  
515  Example Code:
516 \code
517 void example(const ops_keydata_t* key, const ops_keyring_t *keyring)
518 {
519   ops_validate_result_t *result=NULL;
520   if (ops_validate_key_signatures(result, key, keyring, callback_cmd_get_passphrase_from_cmdline)==ops_true)
521     printf("OK");
522   else
523     printf("ERR");
524   printf("valid=%d, invalid=%d, unknown=%d\n",
525          result->valid_count,
526          result->invalid_count,
527          result->unknown_signer_count);
528   ops_validate_result_free(result);
529 }
530
531 \endcode
532  */
533 ops_boolean_t ops_validate_key_signatures(ops_validate_result_t *result,const ops_keydata_t *key,
534                                  const ops_keyring_t *keyring,
535                                  ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *)
536                                  )
537     {
538     ops_parse_info_t *pinfo;
539     validate_key_cb_arg_t carg;
540
541     memset(&carg,'\0',sizeof carg);
542     carg.result=result;
543     carg.cb_get_passphrase=cb_get_passphrase;
544
545     pinfo=ops_parse_info_new();
546     //    ops_parse_options(&opt,OPS_PTAG_CT_SIGNATURE,OPS_PARSE_PARSED);
547
548     carg.keyring=keyring;
549
550     ops_parse_cb_set(pinfo,ops_validate_key_cb,&carg);
551     pinfo->rinfo.accumulate=ops_true;
552     ops_keydata_reader_set(pinfo,key);
553
554     // Note: Coverity incorrectly reports an error that carg.rarg
555     // is never used.
556     carg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
557
558     ops_parse(pinfo);
559
560     ops_public_key_free(&carg.pkey);
561     if(carg.subkey.version)
562         ops_public_key_free(&carg.subkey);
563     ops_user_id_free(&carg.user_id);
564     ops_user_attribute_free(&carg.user_attribute);
565
566     ops_parse_info_delete(pinfo);
567
568     if (result->invalid_count || result->unknown_signer_count || !result->valid_count)
569         return ops_false;
570     else
571         return ops_true;
572     }
573
574 /**
575    \ingroup HighLevel_Verify
576    \param result Where to put the result
577    \param ring Keyring to use
578    \param cb_get_passphrase Callback to use to get passphrase
579    \note It is the caller's responsibility to free result after use.
580    \sa ops_validate_result_free()
581 */
582 ops_boolean_t ops_validate_all_signatures(ops_validate_result_t *result,
583                                  const ops_keyring_t *ring,
584                                  ops_parse_cb_return_t cb_get_passphrase (const ops_parser_content_t *, ops_parse_cb_info_t *)
585                                  )
586     {
587     int n;
588
589     memset(result,'\0',sizeof *result);
590     for(n=0 ; n < ring->nkeys ; ++n)
591         ops_validate_key_signatures(result,&ring->keys[n],ring, cb_get_passphrase);
592     return validate_result_status(result);
593     }
594
595 /**
596    \ingroup HighLevel_Verify
597    \brief Frees validation result and associated memory
598    \param result Struct to be freed
599    \note Must be called after validation functions
600 */
601 void ops_validate_result_free(ops_validate_result_t *result)
602     {
603     if (!result)
604         return;
605
606     if (result->valid_sigs)
607         free_signature_info(result->valid_sigs);
608     if (result->invalid_sigs)
609         free_signature_info(result->invalid_sigs);
610     if (result->unknown_sigs)
611         free_signature_info(result->unknown_sigs);
612
613     free(result);
614     result=NULL;
615     }
616
617 /**
618    \ingroup HighLevel_Verify
619    \brief Verifies the signatures in a signed file
620    \param result Where to put the result
621    \param filename Name of file to be validated
622    \param armoured Treat file as armoured, if set
623    \param keyring Keyring to use
624    \return ops_true if signatures validate successfully; ops_false if signatures fail or there are no signatures
625    \note After verification, result holds the details of all keys which
626    have passed, failed and not been recognised.
627    \note It is the caller's responsiblity to call ops_validate_result_free(result) after use.
628
629 Example code:
630 \code
631 void example(const char* filename, const int armoured, const ops_keyring_t* keyring)
632 {
633   ops_validate_result_t* result=ops_mallocz(sizeof *result);
634  
635   if (ops_validate_file(result, filename, armoured, keyring)==ops_true)
636   {
637     printf("OK");
638     // look at result for details of keys with good signatures
639   }
640   else
641   {
642     printf("ERR");
643     // look at result for details of failed signatures or unknown signers
644   }
645
646   ops_validate_result_free(result);
647 }
648 \endcode
649 */
650 ops_boolean_t ops_validate_file(ops_validate_result_t *result, const char* filename, const int armoured, const ops_keyring_t* keyring)
651     {
652     ops_parse_info_t *pinfo=NULL;
653     validate_data_cb_arg_t validate_arg;
654
655     int fd=0;
656
657     //
658     fd=ops_setup_file_read(&pinfo, filename, &validate_arg, validate_data_cb, ops_true);
659     if (fd < 0)
660         return ops_false;
661
662     // Set verification reader and handling options
663
664     memset(&validate_arg,'\0',sizeof validate_arg);
665     validate_arg.result=result;
666     validate_arg.keyring=keyring;
667     // Note: Coverity incorrectly reports an error that carg.rarg
668     // is never used.
669     validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
670
671     if (armoured)
672         ops_reader_push_dearmour(pinfo);
673    
674     // Do the verification
675
676     ops_parse(pinfo);
677
678     if (debug)
679         {
680         printf("valid=%d, invalid=%d, unknown=%d\n",
681                result->valid_count,
682                result->invalid_count,
683                result->unknown_signer_count);
684         }
685
686     // Tidy up
687     if (armoured)
688         ops_reader_pop_dearmour(pinfo);
689     ops_teardown_file_read(pinfo, fd);
690
691     return validate_result_status(result);
692     }
693
694 /**
695    \ingroup HighLevel_Verify
696    \brief Verifies the signatures in a ops_memory_t struct
697    \param result Where to put the result
698    \param mem Memory to be validated
699    \param armoured Treat data as armoured, if set
700    \param keyring Keyring to use
701    \return ops_true if signature validates successfully; ops_false if not
702    \note After verification, result holds the details of all keys which
703    have passed, failed and not been recognised.
704    \note It is the caller's responsiblity to call ops_validate_result_free(result) after use.
705 */
706
707 ops_boolean_t ops_validate_mem(ops_validate_result_t *result, ops_memory_t* mem, const int armoured, const ops_keyring_t* keyring)
708     {
709     ops_parse_info_t *pinfo=NULL;
710     validate_data_cb_arg_t validate_arg;
711
712     //
713     ops_setup_memory_read(&pinfo, mem, &validate_arg, validate_data_cb, ops_true);
714
715     // Set verification reader and handling options
716
717     memset(&validate_arg,'\0',sizeof validate_arg);
718     validate_arg.result=result;
719     validate_arg.keyring=keyring;
720     // Note: Coverity incorrectly reports an error that carg.rarg
721     // is never used.
722     validate_arg.rarg=ops_reader_get_arg_from_pinfo(pinfo);
723
724     if (armoured)
725         ops_reader_push_dearmour(pinfo);
726    
727     // Do the verification
728
729     ops_parse(pinfo);
730
731     if (debug)
732         {
733         printf("valid=%d, invalid=%d, unknown=%d\n",
734                result->valid_count,
735                result->invalid_count,
736                result->unknown_signer_count);
737         }
738
739     // Tidy up
740     if (armoured)
741         ops_reader_pop_dearmour(pinfo);
742     ops_teardown_memory_read(pinfo, mem);
743
744     return validate_result_status(result);
745     }
746
747 // eof
748
Note: See TracBrowser for help on using the browser.