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
40 {"SHA1", CDK_MD_SHA1
},
41 {"RIPEMD160", CDK_MD_RMD160
},
43 {"SHA256", CDK_MD_SHA256
},
48 static int file_verify_clearsign( cdk_ctx_t
, const char *, const char * );
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
);
62 * @hd: the session handle
63 * @file: the input file
64 * @output: the output file
69 cdk_file_verify( cdk_ctx_t hd
, const char * file
, const char * output
)
77 if( output
&& !hd
->opt
.overwrite
&& _cdk_check_file( output
) )
80 rc
= cdk_stream_open ( file
, &inp
);
83 if( cdk_armor_filter_use( inp
) ) {
84 n
= cdk_stream_peek( inp
, buf
, sizeof buf
-1 );
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
);
101 _cdk_result_verify_free( _cdk_verify_result_t res
)
104 cdk_free( res
->sig_data
);
105 cdk_free( res
->notation
);
112 _cdk_result_verify_new( void )
114 _cdk_verify_result_t res
;
116 res
= cdk_calloc( 1, sizeof *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).
133 cdk_sig_get_ulong_attr( cdk_ctx_t hd
, int idx
, int what
)
135 _cdk_verify_result_t res
;
138 if( !hd
|| !hd
->result
.verify
)
142 res
= hd
->result
.verify
;
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;
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.
170 cdk_sig_get_data_attr( cdk_ctx_t hd
, int idx
, int what
)
172 _cdk_verify_result_t res
;
175 if( !hd
|| !hd
->result
.verify
)
179 res
= hd
->result
.verify
;
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
;
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];
199 int i
, is_signed
= 0, nbytes
;
203 rc
= cdk_stream_create( output
, &out
);
208 rc
= cdk_stream_open( file
, &inp
);
212 s
= "-----BEGIN PGP SIGNED MESSAGE-----";
213 while( !cdk_stream_eof( inp
) ) {
214 nbytes
= _cdk_stream_gets( inp
, buf
, sizeof buf
-1 );
217 if( !strncmp( buf
, s
, strlen( s
) ) ) {
222 if( cdk_stream_eof( inp
) && !is_signed
) {
223 rc
= CDK_Armor_Error
;
227 while( !cdk_stream_eof( inp
) ) {
228 nbytes
= _cdk_stream_gets( inp
, buf
, sizeof buf
-1 );
231 if( nbytes
== 1 ) /* empty line */
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
;
243 if( digest_algo
&& cdk_md_test_algo( digest_algo
) ) {
248 digest_algo
= CDK_MD_MD5
;
249 md
= cdk_md_open( digest_algo
, 0 );
255 s
= "-----BEGIN PGP SIGNATURE-----";
256 while( !cdk_stream_eof( inp
) ) {
257 nbytes
= _cdk_stream_gets( inp
, buf
, sizeof buf
-1 );
260 if( !strncmp( buf
, s
, strlen( s
) ) )
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 );
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( );
281 rc
= CDK_Out_Of_Core
;
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 );
292 if( nbytes
< (sizeof buf
-3) ) {
293 buf
[nbytes
-1] = '\n';
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
);
306 cdk_stream_close( out
);
307 cdk_stream_close( tmp
);
308 cdk_stream_close( inp
);