*** empty log message ***
[gnutls.git] / libextra / opencdk / verify.c
blob600b781ab579ee9d96de70121f8b614168a5cb15
1 /* -*- Mode: C; c-file-style: "bsd" -*-
2 * verify.c - Verify signatures
3 * Copyright (C) 2001, 2002, 2003 Timo Schulz
5 * This file is part of OpenCDK.
7 * OpenCDK is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * OpenCDK is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with OpenCDK; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 #include <stdio.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "opencdk.h"
30 #include "main.h"
31 #include "filters.h"
32 #include "packet.h"
35 struct {
36 const char *name;
37 int algo;
38 } digest_table[] = {
39 {"MD5", CDK_MD_MD5},
40 {"SHA1", CDK_MD_SHA1},
41 {"RIPEMD160", CDK_MD_RMD160},
42 {"MD2", CDK_MD_MD2},
43 {"SHA256", CDK_MD_SHA256},
44 {NULL, 0}
48 static int file_verify_clearsign( cdk_ctx_t, const char *, const char * );
51 cdk_error_t
52 cdk_stream_verify( cdk_ctx_t hd, cdk_stream_t inp, cdk_stream_t out )
54 if( cdk_armor_filter_use( inp ) )
55 cdk_stream_set_armor_flag( inp, 0 );
56 return _cdk_proc_packets( hd, inp, NULL, NULL, NULL );
60 /**
61 * cdk_file_verify:
62 * @hd: the session handle
63 * @file: the input file
64 * @output: the output file
66 * Verify a signature.
67 **/
68 cdk_error_t
69 cdk_file_verify( cdk_ctx_t hd, const char * file, const char * output )
71 cdk_stream_t inp;
72 char buf[2048];
73 int rc, n;
75 if( !hd || !file )
76 return CDK_Inv_Value;
77 if( output && !hd->opt.overwrite && _cdk_check_file( output ) )
78 return CDK_Inv_Mode;
80 rc = cdk_stream_open ( file, &inp );
81 if( rc )
82 return rc;
83 if( cdk_armor_filter_use( inp ) ) {
84 n = cdk_stream_peek( inp, buf, sizeof buf-1 );
85 if( !n )
86 return CDK_EOF;
87 buf[n] = '\0';
88 if( strstr( buf, "BEGIN PGP SIGNED MESSAGE" ) ) {
89 cdk_stream_close( inp );
90 return file_verify_clearsign( hd, file, output );
92 cdk_stream_set_armor_flag( inp, 0 );
94 rc = _cdk_proc_packets( hd, inp, NULL, NULL, NULL );
95 cdk_stream_close( inp );
96 return rc;
100 void
101 _cdk_result_verify_free( _cdk_verify_result_t res )
103 if( res ) {
104 cdk_free( res->sig_data );
105 cdk_free( res->notation );
106 cdk_free( res );
111 _cdk_verify_result_t
112 _cdk_result_verify_new( void )
114 _cdk_verify_result_t res;
116 res = cdk_calloc( 1, sizeof *res );
117 if( !res )
118 return NULL;
119 return res;
124 * cdk_sig_get_ulong_attr:
125 * @hd: session handle
126 * @idx: index of the signature
127 * @what: attribute id
129 * Extract the requested attribute of the signature. The returned value
130 * is always an integer (max. 32-bit).
132 unsigned long
133 cdk_sig_get_ulong_attr( cdk_ctx_t hd, int idx, int what )
135 _cdk_verify_result_t res;
136 u32 val = 0;
138 if( !hd || !hd->result.verify )
139 return 0;
141 assert( idx == 0 );
142 res = hd->result.verify;
143 switch( what ) {
144 case CDK_ATTR_CREATED: val = res->created; break;
145 case CDK_ATTR_EXPIRE : val = res->expires; break;
146 case CDK_ATTR_KEYID : val = res->keyid[1]; break;
147 case CDK_ATTR_STATUS : val = res->sig_status; break;
148 case CDK_ATTR_ALGO_PK: val = res->pubkey_algo; break;
149 case CDK_ATTR_ALGO_MD: val = res->digest_algo; break;
150 case CDK_ATTR_VERSION: val = res->sig_ver; break;
151 case CDK_ATTR_LEN : val = res->sig_len; break;
152 case CDK_ATTR_FLAGS : val = res->sig_flags; break;
153 default : val = 0; break;
156 return val;
161 * cdk_sig_get_data_attr:
162 * @hd: session handle
163 * @idx: index of the signature
164 * @what: attribute id.
166 * Extract the requested attribute of the signature. The returned value
167 * is always a constant object to the data.
169 const void *
170 cdk_sig_get_data_attr( cdk_ctx_t hd, int idx, int what )
172 _cdk_verify_result_t res;
173 const void * val;
175 if( !hd || !hd->result.verify )
176 return NULL;
178 assert( idx == 0 );
179 res = hd->result.verify;
180 switch( what ) {
181 case CDK_ATTR_KEYID : val = res->keyid; break;
182 case CDK_ATTR_NOTATION: val = res->notation; break;
183 case CDK_ATTR_MPI : val = res->sig_data; break;
184 default : val = NULL;
187 return val;
191 static int
192 file_verify_clearsign( cdk_ctx_t hd, const char * file, const char * output )
194 cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
195 cdk_md_hd_t md = NULL;
196 char buf[512], chk[512];
197 const char * s;
198 int rc = 0;
199 int i, is_signed = 0, nbytes;
200 int digest_algo = 0;
202 if( output ) {
203 rc = cdk_stream_create( output, &out );
204 if( rc )
205 return rc;
208 rc = cdk_stream_open( file, &inp );
209 if( rc )
210 return rc;
212 s = "-----BEGIN PGP SIGNED MESSAGE-----";
213 while( !cdk_stream_eof( inp ) ) {
214 nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
215 if( !nbytes )
216 break;
217 if( !strncmp( buf, s, strlen( s ) ) ) {
218 is_signed = 1;
219 break;
222 if( cdk_stream_eof( inp ) && !is_signed ) {
223 rc = CDK_Armor_Error;
224 goto leave;
227 while( !cdk_stream_eof( inp ) ) {
228 nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
229 if( !nbytes )
230 break;
231 if( nbytes == 1 ) /* empty line */
232 break;
233 else if( !strncmp( buf, "Hash: ", 6 ) ) {
234 for( i = 0; (s = digest_table[i].name); i++ ) {
235 if( !strcmp( buf + 6, s ) ) {
236 digest_algo = digest_table[i].algo;
237 break;
243 if( digest_algo && cdk_md_test_algo( digest_algo ) ) {
244 rc = CDK_Inv_Algo;
245 goto leave;
247 if( !digest_algo )
248 digest_algo = CDK_MD_MD5;
249 md = cdk_md_open( digest_algo, 0 );
250 if( !md ) {
251 rc = CDK_Inv_Algo;
252 goto leave;
255 s = "-----BEGIN PGP SIGNATURE-----";
256 while( !cdk_stream_eof( inp ) ) {
257 nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
258 if( !nbytes )
259 break;
260 if( !strncmp( buf, s, strlen( s ) ) )
261 break;
262 else {
263 cdk_stream_peek( inp, chk, sizeof chk-1 );
264 i = strncmp( chk, s, strlen( s ) );
265 if( strlen( buf ) == 0 && i == 0 )
266 continue; /* skip last '\n' */
267 _cdk_trim_string( buf, i == 0? 0 : 1 );
268 cdk_md_write( md, buf, strlen( buf ) );
270 if( !strncmp( buf, "- ", 2 ) )
271 memmove( buf, buf + 2, nbytes - 2 );
272 if( out ) {
273 buf[strlen( buf ) - 1] = 0;
274 buf[strlen( buf ) - 1] = '\n';
275 cdk_stream_write( out, buf, strlen( buf ) );
279 tmp = cdk_stream_tmp( );
280 if( !tmp ) {
281 rc = CDK_Out_Of_Core;
282 goto leave;
285 /* xxx revamp this part of the function */
286 s = "-----BEGIN PGP SIGNATURE-----\n";
287 _cdk_stream_puts( tmp, s );
288 while( !cdk_stream_eof( inp ) ) {
289 nbytes = _cdk_stream_gets( inp, buf, sizeof buf-1 );
290 if( !nbytes )
291 break;
292 if( nbytes < (sizeof buf -3) ) {
293 buf[nbytes-1] = '\n';
294 buf[nbytes] = '\0';
296 cdk_stream_write( tmp, buf, nbytes );
298 cdk_stream_tmp_set_mode( tmp, STREAMCTL_READ );
299 cdk_stream_seek( tmp, 0 );
300 cdk_stream_set_armor_flag( tmp, 0 );
301 cdk_stream_read( tmp, NULL, 0 );
303 rc = _cdk_proc_packets( hd, tmp, NULL, NULL, md );
305 leave:
306 cdk_stream_close( out );
307 cdk_stream_close( tmp );
308 cdk_stream_close( inp );
309 return rc;