1 /*****************************************************************************
2 * update_crypto.c: DSA/SHA1 related functions used for updating
3 *****************************************************************************
4 * Copyright © 2008-2009 VLC authors and VideoLAN
7 * Authors: Rafaël Carré <funman@videolanorg>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either release 2 of the License, or
12 * (at your option) any later release.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
26 * This file contains functions related to OpenPGP in VLC update management
29 /*****************************************************************************
31 *****************************************************************************/
42 #include "vlc_common.h"
43 #include <vlc_stream.h>
44 #include <vlc_strings.h>
50 /*****************************************************************************
52 *****************************************************************************/
54 #define packet_type( c ) ( ( c & 0x3c ) >> 2 ) /* 0x3C = 00111100 */
55 #define packet_header_len( c ) ( ( c & 0x03 ) + 1 ) /* number of bytes in a packet header */
58 static inline int scalar_number( uint8_t *p
, int header_len
)
60 assert( header_len
== 1 || header_len
== 2 || header_len
== 4 );
64 else if( header_len
== 2 )
65 return( (p
[0] << 8) + p
[1] );
66 else if( header_len
== 4 )
67 return( (p
[0] << 24) + (p
[1] << 16) + (p
[2] << 8) + p
[3] );
73 /* number of data bytes in a MPI */
74 #define mpi_len( mpi ) ( ( scalar_number( mpi, 2 ) + 7 ) / 8 )
76 #define READ_MPI(n, bits) do { \
77 if( i_read + 2 > i_packet_len ) \
79 int len = mpi_len( p_buf ); \
80 if( len > (bits)/8 || i_read + 2 + len > i_packet_len ) \
83 memcpy( n, p_buf, len ); \
84 p_buf += len; i_read += len; \
88 * fill a public_key_packet_t structure from public key packet data
89 * verify that it is a version 4 public key packet, using DSA
91 static int parse_public_key_packet( public_key_packet_t
*p_key
, uint8_t *p_buf
,
95 if( i_packet_len
> 418 || i_packet_len
< 6 )
100 p_key
->version
= *p_buf
++; i_read
++;
101 if( p_key
->version
!= 4 )
104 /* XXX: warn when timestamp is > date ? */
105 memcpy( p_key
->timestamp
, p_buf
, 4 ); p_buf
+= 4; i_read
+= 4;
107 p_key
->algo
= *p_buf
++; i_read
++;
108 if( p_key
->algo
!= PUBLIC_KEY_ALGO_DSA
)
111 READ_MPI(p_key
->p
, 1024);
112 READ_MPI(p_key
->q
, 160);
113 READ_MPI(p_key
->g
, 1024);
114 READ_MPI(p_key
->y
, 1024);
116 if( i_read
!= i_packet_len
) /* some extra data eh ? */
126 static size_t parse_signature_v3_packet( signature_packet_t
*p_sig
,
127 uint8_t *p_buf
, size_t i_sig_len
)
129 size_t i_read
= 1; /* we already read the version byte */
131 if( i_sig_len
< 19 ) /* signature is at least 19 bytes + the 2 MPIs */
134 p_sig
->specific
.v3
.hashed_data_len
= *p_buf
++; i_read
++;
135 if( p_sig
->specific
.v3
.hashed_data_len
!= 5 )
138 p_sig
->type
= *p_buf
++; i_read
++;
140 memcpy( p_sig
->specific
.v3
.timestamp
, p_buf
, 4 );
141 p_buf
+= 4; i_read
+= 4;
143 memcpy( p_sig
->issuer_longid
, p_buf
, 8 );
144 p_buf
+= 8; i_read
+= 8;
146 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
148 p_sig
->digest_algo
= *p_buf
++; i_read
++;
150 p_sig
->hash_verification
[0] = *p_buf
++; i_read
++;
151 p_sig
->hash_verification
[1] = *p_buf
++; i_read
++;
153 assert( i_read
== 19 );
160 * fill a signature_packet_v4_t from signature packet data
161 * verify that it was used with a DSA public key, using SHA-1 digest
163 static size_t parse_signature_v4_packet( signature_packet_t
*p_sig
,
164 uint8_t *p_buf
, size_t i_sig_len
)
166 size_t i_read
= 1; /* we already read the version byte */
168 if( i_sig_len
< 10 ) /* signature is at least 10 bytes + the 2 MPIs */
171 p_sig
->type
= *p_buf
++; i_read
++;
173 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
175 p_sig
->digest_algo
= *p_buf
++; i_read
++;
177 memcpy( p_sig
->specific
.v4
.hashed_data_len
, p_buf
, 2 );
178 p_buf
+= 2; i_read
+= 2;
180 size_t i_hashed_data_len
=
181 scalar_number( p_sig
->specific
.v4
.hashed_data_len
, 2 );
182 i_read
+= i_hashed_data_len
;
183 if( i_read
+ 4 > i_sig_len
)
186 p_sig
->specific
.v4
.hashed_data
= (uint8_t*) malloc( i_hashed_data_len
);
187 if( !p_sig
->specific
.v4
.hashed_data
)
189 memcpy( p_sig
->specific
.v4
.hashed_data
, p_buf
, i_hashed_data_len
);
190 p_buf
+= i_hashed_data_len
;
192 memcpy( p_sig
->specific
.v4
.unhashed_data_len
, p_buf
, 2 );
193 p_buf
+= 2; i_read
+= 2;
195 size_t i_unhashed_data_len
=
196 scalar_number( p_sig
->specific
.v4
.unhashed_data_len
, 2 );
197 i_read
+= i_unhashed_data_len
;
198 if( i_read
+ 2 > i_sig_len
)
201 p_sig
->specific
.v4
.unhashed_data
= (uint8_t*) malloc( i_unhashed_data_len
);
202 if( !p_sig
->specific
.v4
.unhashed_data
)
205 memcpy( p_sig
->specific
.v4
.unhashed_data
, p_buf
, i_unhashed_data_len
);
206 p_buf
+= i_unhashed_data_len
;
208 memcpy( p_sig
->hash_verification
, p_buf
, 2 );
209 p_buf
+= 2; i_read
+= 2;
211 uint8_t *p
, *max_pos
;
212 p
= p_sig
->specific
.v4
.unhashed_data
;
213 max_pos
= p
+ scalar_number( p_sig
->specific
.v4
.unhashed_data_len
, 2 );
220 size_t i_subpacket_len
;
223 if( p
+ 1 > max_pos
)
225 i_subpacket_len
= *p
++;
229 if( p
+ 2 > max_pos
)
231 i_subpacket_len
= (*p
++ - 192) << 8;
232 i_subpacket_len
+= *p
++ + 192;
236 if( p
+ 4 > max_pos
)
238 i_subpacket_len
= *++p
<< 24;
239 i_subpacket_len
+= *++p
<< 16;
240 i_subpacket_len
+= *++p
<< 8;
241 i_subpacket_len
+= *++p
;
244 if( *p
== ISSUER_SUBPACKET
)
246 if( p
+ 9 > max_pos
)
249 memcpy( &p_sig
->issuer_longid
, p
+1, 8 );
254 p
+= i_subpacket_len
;
259 static int parse_signature_packet( signature_packet_t
*p_sig
,
260 uint8_t *p_buf
, size_t i_packet_len
)
262 if( !i_packet_len
) /* 1st sanity check, we need at least the version */
265 p_sig
->version
= *p_buf
++;
268 switch( p_sig
->version
)
271 i_read
= parse_signature_v3_packet( p_sig
, p_buf
, i_packet_len
);
274 p_sig
->specific
.v4
.hashed_data
= NULL
;
275 p_sig
->specific
.v4
.unhashed_data
= NULL
;
276 i_read
= parse_signature_v4_packet( p_sig
, p_buf
, i_packet_len
);
282 if( i_read
== 0 ) /* signature packet parsing has failed */
285 if( p_sig
->public_key_algo
!= PUBLIC_KEY_ALGO_DSA
)
288 if( p_sig
->digest_algo
!= DIGEST_ALGO_SHA1
)
291 switch( p_sig
->type
)
293 case BINARY_SIGNATURE
:
295 case GENERIC_KEY_SIGNATURE
:
296 case PERSONA_KEY_SIGNATURE
:
297 case CASUAL_KEY_SIGNATURE
:
298 case POSITIVE_KEY_SIGNATURE
:
304 p_buf
--; /* rewind to the version byte */
307 READ_MPI(p_sig
->r
, 160);
308 READ_MPI(p_sig
->s
, 160);
310 assert( i_read
== i_packet_len
);
311 if( i_read
< i_packet_len
) /* some extra data, hm ? */
318 if( p_sig
->version
== 4 )
320 free( p_sig
->specific
.v4
.hashed_data
);
321 free( p_sig
->specific
.v4
.unhashed_data
);
329 * crc_octets() was lamely copied from rfc 2440
330 * Copyright (C) The Internet Society (1998). All Rights Reserved.
332 #define CRC24_INIT 0xB704CEL
333 #define CRC24_POLY 0x1864CFBL
335 static long crc_octets( uint8_t *octets
, size_t len
)
337 long crc
= CRC24_INIT
;
341 crc
^= (*octets
++) << 16;
342 for (i
= 0; i
< 8; i
++)
349 return crc
& 0xFFFFFFL
;
354 * Transform an armored document in binary format
355 * Used on public keys and signatures
357 static int pgp_unarmor( char *p_ibuf
, size_t i_ibuf_len
,
358 uint8_t *p_obuf
, size_t i_obuf_len
)
360 char *p_ipos
= p_ibuf
;
361 uint8_t *p_opos
= p_obuf
;
363 int i_header_skipped
= 0;
365 while( !i_end
&& p_ipos
< p_ibuf
+ i_ibuf_len
&& *p_ipos
!= '=' )
367 if( *p_ipos
== '\r' || *p_ipos
== '\n' )
373 size_t i_line_len
= strcspn( p_ipos
, "\r\n" );
374 if( i_line_len
== 0 )
377 if( !i_header_skipped
)
379 if( !strncmp( p_ipos
, "-----BEGIN PGP", 14 ) )
380 i_header_skipped
= 1;
382 p_ipos
+= i_line_len
+ 1;
386 if( !strncmp( p_ipos
, "Version:", 8 ) )
388 p_ipos
+= i_line_len
+ 1;
392 if( p_ipos
[i_line_len
- 1] == '=' )
395 p_ipos
[i_line_len
- 1] = '\0';
398 p_ipos
[i_line_len
] = '\0';
400 p_opos
+= vlc_b64_decode_binary_to_buffer( p_opos
,
401 p_obuf
- p_opos
+ i_obuf_len
, p_ipos
);
402 p_ipos
+= i_line_len
+ 1;
405 /* XXX: the CRC is OPTIONAL, really require it ? */
406 if( p_ipos
+ 5 > p_ibuf
+ i_ibuf_len
|| *p_ipos
++ != '=' )
410 if( vlc_b64_decode_binary_to_buffer( p_crc
, 3, p_ipos
) != 3 )
413 long l_crc
= crc_octets( p_obuf
, p_opos
- p_obuf
);
414 long l_crc2
= ( 0 << 24 ) + ( p_crc
[0] << 16 ) + ( p_crc
[1] << 8 ) + p_crc
[2];
416 return l_crc2
== l_crc
? p_opos
- p_obuf
: 0;
421 * Verify an OpenPGP signature made on some SHA-1 hash, with some DSA public key
423 int verify_signature( uint8_t *p_r
, uint8_t *p_s
, public_key_packet_t
*p_key
,
426 /* the data to be verified (a SHA-1 hash) */
427 const char *hash_sexp_s
= "(data(flags raw)(value %m))";
429 const char *key_sexp_s
= "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
431 const char *sig_sexp_s
= "(sig-val(dsa(r %m )(s %m )))";
434 gcry_mpi_t p
, q
, g
, y
, r
, s
, hash
;
435 p
= q
= g
= y
= r
= s
= hash
= NULL
;
436 gcry_sexp_t key_sexp
, hash_sexp
, sig_sexp
;
437 key_sexp
= hash_sexp
= sig_sexp
= NULL
;
439 int i_p_len
= mpi_len( p_key
->p
);
440 int i_q_len
= mpi_len( p_key
->q
);
441 int i_g_len
= mpi_len( p_key
->g
);
442 int i_y_len
= mpi_len( p_key
->y
);
443 if( gcry_mpi_scan( &p
, GCRYMPI_FMT_USG
, p_key
->p
+ 2, i_p_len
, NULL
) ||
444 gcry_mpi_scan( &q
, GCRYMPI_FMT_USG
, p_key
->q
+ 2, i_q_len
, NULL
) ||
445 gcry_mpi_scan( &g
, GCRYMPI_FMT_USG
, p_key
->g
+ 2, i_g_len
, NULL
) ||
446 gcry_mpi_scan( &y
, GCRYMPI_FMT_USG
, p_key
->y
+ 2, i_y_len
, NULL
) ||
447 gcry_sexp_build( &key_sexp
, &erroff
, key_sexp_s
, p
, q
, g
, y
) )
450 int i_r_len
= mpi_len( p_r
);
451 int i_s_len
= mpi_len( p_s
);
452 if( gcry_mpi_scan( &r
, GCRYMPI_FMT_USG
, p_r
+ 2, i_r_len
, NULL
) ||
453 gcry_mpi_scan( &s
, GCRYMPI_FMT_USG
, p_s
+ 2, i_s_len
, NULL
) ||
454 gcry_sexp_build( &sig_sexp
, &erroff
, sig_sexp_s
, r
, s
) )
458 if( gcry_mpi_scan( &hash
, GCRYMPI_FMT_USG
, p_hash
, i_hash_len
, NULL
) ||
459 gcry_sexp_build( &hash_sexp
, &erroff
, hash_sexp_s
, hash
) )
462 if( gcry_pk_verify( sig_sexp
, hash_sexp
, key_sexp
) )
468 if( p
) gcry_mpi_release( p
);
469 if( q
) gcry_mpi_release( q
);
470 if( g
) gcry_mpi_release( g
);
471 if( y
) gcry_mpi_release( y
);
472 if( r
) gcry_mpi_release( r
);
473 if( s
) gcry_mpi_release( s
);
474 if( hash
) gcry_mpi_release( hash
);
475 if( key_sexp
) gcry_sexp_release( key_sexp
);
476 if( sig_sexp
) gcry_sexp_release( sig_sexp
);
477 if( hash_sexp
) gcry_sexp_release( hash_sexp
);
483 * fill a public_key_t with public key data, including:
484 * * public key packet
485 * * signature packet issued by key which long id is p_sig_issuer
488 int parse_public_key( const uint8_t *p_key_data
, size_t i_key_len
,
489 public_key_t
*p_key
, const uint8_t *p_sig_issuer
)
491 uint8_t *pos
= (uint8_t*) p_key_data
;
492 uint8_t *max_pos
= pos
+ i_key_len
;
495 #define PUBLIC_KEY_FOUND 0x01
496 #define USER_ID_FOUND 0x02
497 #define SIGNATURE_FOUND 0X04
499 uint8_t *p_key_unarmored
= NULL
;
501 p_key
->psz_username
= NULL
;
502 p_key
->sig
.specific
.v4
.hashed_data
= NULL
;
503 p_key
->sig
.specific
.v4
.unhashed_data
= NULL
;
505 if( !( *pos
& 0x80 ) )
506 { /* first byte is ASCII, unarmoring */
507 p_key_unarmored
= (uint8_t*)malloc( i_key_len
);
508 if( !p_key_unarmored
)
510 int i_len
= pgp_unarmor( (char*)p_key_data
, i_key_len
,
511 p_key_unarmored
, i_key_len
);
516 pos
= p_key_unarmored
;
517 max_pos
= pos
+ i_len
;
520 while( pos
< max_pos
)
522 if( !(*pos
& 0x80) || *pos
& 0x40 )
525 int i_type
= packet_type( *pos
);
527 int i_header_len
= packet_header_len( *pos
++ );
528 if( pos
+ i_header_len
> max_pos
||
529 ( i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4 ) )
532 int i_packet_len
= scalar_number( pos
, i_header_len
);
535 if( pos
+ i_packet_len
> max_pos
)
540 case PUBLIC_KEY_PACKET
:
541 i_status
|= PUBLIC_KEY_FOUND
;
542 if( parse_public_key_packet( &p_key
->key
, pos
, i_packet_len
) != VLC_SUCCESS
)
546 case SIGNATURE_PACKET
: /* we accept only v4 signatures here */
547 if( i_status
& SIGNATURE_FOUND
|| !p_sig_issuer
)
549 int i_ret
= parse_signature_packet( &p_key
->sig
, pos
,
551 if( i_ret
== VLC_SUCCESS
)
553 if( p_key
->sig
.version
!= 4 )
555 if( memcmp( p_key
->sig
.issuer_longid
, p_sig_issuer
, 8 ) )
557 free( p_key
->sig
.specific
.v4
.hashed_data
);
558 free( p_key
->sig
.specific
.v4
.unhashed_data
);
559 p_key
->sig
.specific
.v4
.hashed_data
= NULL
;
560 p_key
->sig
.specific
.v4
.unhashed_data
= NULL
;
563 i_status
|= SIGNATURE_FOUND
;
568 if( p_key
->psz_username
) /* save only the first User ID */
570 i_status
|= USER_ID_FOUND
;
571 p_key
->psz_username
= (uint8_t*)malloc( i_packet_len
+ 1);
572 if( !p_key
->psz_username
)
575 memcpy( p_key
->psz_username
, pos
, i_packet_len
);
576 p_key
->psz_username
[i_packet_len
] = '\0';
584 free( p_key_unarmored
);
586 if( !( i_status
& ( PUBLIC_KEY_FOUND
| USER_ID_FOUND
) ) )
589 if( p_sig_issuer
&& !( i_status
& SIGNATURE_FOUND
) )
595 if( p_key
->sig
.version
== 4 )
597 free( p_key
->sig
.specific
.v4
.hashed_data
);
598 free( p_key
->sig
.specific
.v4
.unhashed_data
);
600 free( p_key
->psz_username
);
601 free( p_key_unarmored
);
606 /* hash a binary file */
607 static int hash_from_binary_file( const char *psz_file
, gcry_md_hd_t hd
)
609 uint8_t buffer
[4096];
612 FILE *f
= vlc_fopen( psz_file
, "r" );
616 while( ( i_read
= fread( buffer
, 1, sizeof(buffer
), f
) ) > 0 )
617 gcry_md_write( hd
, buffer
, i_read
);
625 /* final part of the hash */
626 static uint8_t *hash_finish( gcry_md_hd_t hd
, signature_packet_t
*p_sig
)
628 if( p_sig
->version
== 3 )
630 gcry_md_putc( hd
, p_sig
->type
);
631 gcry_md_write( hd
, &p_sig
->specific
.v3
.timestamp
, 4 );
633 else if( p_sig
->version
== 4 )
635 gcry_md_putc( hd
, p_sig
->version
);
636 gcry_md_putc( hd
, p_sig
->type
);
637 gcry_md_putc( hd
, p_sig
->public_key_algo
);
638 gcry_md_putc( hd
, p_sig
->digest_algo
);
639 gcry_md_write( hd
, p_sig
->specific
.v4
.hashed_data_len
, 2 );
640 size_t i_len
= scalar_number( p_sig
->specific
.v4
.hashed_data_len
, 2 );
641 gcry_md_write( hd
, p_sig
->specific
.v4
.hashed_data
, i_len
);
643 gcry_md_putc( hd
, 0x04 );
644 gcry_md_putc( hd
, 0xFF );
646 i_len
+= 6; /* hashed data + 6 bytes header */
648 gcry_md_putc( hd
, (i_len
>> 24) & 0xff );
649 gcry_md_putc( hd
, (i_len
>> 16) & 0xff );
650 gcry_md_putc( hd
, (i_len
>> 8) & 0xff );
651 gcry_md_putc( hd
, (i_len
) & 0xff );
654 { /* RFC 4880 only tells about versions 3 and 4 */
660 uint8_t *p_tmp
= (uint8_t*) gcry_md_read( hd
, GCRY_MD_SHA1
);
661 uint8_t *p_hash
= malloc( 20 );
663 memcpy( p_hash
, p_tmp
, 20 );
670 * return a sha1 hash of a text
672 uint8_t *hash_sha1_from_text( const char *psz_string
,
673 signature_packet_t
*p_sig
)
676 if( gcry_md_open( &hd
, GCRY_MD_SHA1
, 0 ) )
679 if( p_sig
->type
== TEXT_SIGNATURE
)
682 size_t i_len
= strcspn( psz_string
, "\r\n" );
686 gcry_md_write( hd
, psz_string
, i_len
);
689 gcry_md_putc( hd
, '\r' );
690 gcry_md_putc( hd
, '\n' );
692 if( *psz_string
== '\r' )
694 if( *psz_string
== '\n' )
698 gcry_md_write( hd
, psz_string
, strlen( psz_string
) );
700 return hash_finish( hd
, p_sig
);
705 * return a sha1 hash of a file
707 uint8_t *hash_sha1_from_file( const char *psz_file
, signature_packet_t
*p_sig
)
710 if( gcry_md_open( &hd
, GCRY_MD_SHA1
, 0 ) )
713 if( hash_from_binary_file( psz_file
, hd
) < 0 )
719 return hash_finish( hd
, p_sig
);
724 * Generate a SHA1 hash on a public key, to verify a signature made on that hash
725 * Note that we need the signature (v4) to compute the hash
727 uint8_t *hash_sha1_from_public_key( public_key_t
*p_pkey
)
729 if( p_pkey
->sig
.version
!= 4 )
732 if( p_pkey
->sig
.type
< GENERIC_KEY_SIGNATURE
||
733 p_pkey
->sig
.type
> POSITIVE_KEY_SIGNATURE
)
736 gcry_error_t error
= 0;
739 error
= gcry_md_open( &hd
, GCRY_MD_SHA1
, 0 );
743 gcry_md_putc( hd
, 0x99 );
745 size_t i_p_len
= mpi_len( p_pkey
->key
.p
);
746 size_t i_g_len
= mpi_len( p_pkey
->key
.g
);
747 size_t i_q_len
= mpi_len( p_pkey
->key
.q
);
748 size_t i_y_len
= mpi_len( p_pkey
->key
.y
);
750 size_t i_size
= 6 + 2*4 + i_p_len
+ i_g_len
+ i_q_len
+ i_y_len
;
752 gcry_md_putc( hd
, (i_size
>> 8) & 0xff );
753 gcry_md_putc( hd
, i_size
& 0xff );
755 gcry_md_putc( hd
, p_pkey
->key
.version
);
756 gcry_md_write( hd
, p_pkey
->key
.timestamp
, 4 );
757 gcry_md_putc( hd
, p_pkey
->key
.algo
);
759 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.p
, 2 );
760 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.p
+ 2, i_p_len
);
762 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.q
, 2 );
763 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.q
+ 2, i_q_len
);
765 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.g
, 2 );
766 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.g
+ 2, i_g_len
);
768 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.y
, 2 );
769 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.y
+ 2, i_y_len
);
771 gcry_md_putc( hd
, 0xb4 );
773 size_t i_len
= strlen((char*)p_pkey
->psz_username
);
775 gcry_md_putc( hd
, (i_len
>> 24) & 0xff );
776 gcry_md_putc( hd
, (i_len
>> 16) & 0xff );
777 gcry_md_putc( hd
, (i_len
>> 8) & 0xff );
778 gcry_md_putc( hd
, (i_len
) & 0xff );
780 gcry_md_write( hd
, p_pkey
->psz_username
, i_len
);
782 uint8_t *p_hash
= hash_finish( hd
, &p_pkey
->sig
);
784 p_hash
[0] != p_pkey
->sig
.hash_verification
[0] ||
785 p_hash
[1] != p_pkey
->sig
.hash_verification
[1] )
796 * download a public key (the last one) from videolan server, and parse it
798 public_key_t
*download_key( vlc_object_t
*p_this
,
799 const uint8_t *p_longid
, const uint8_t *p_signature_issuer
)
802 if( asprintf( &psz_url
, "http://download.videolan.org/pub/keys/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X.asc",
803 p_longid
[0], p_longid
[1], p_longid
[2], p_longid
[3],
804 p_longid
[4], p_longid
[5], p_longid
[6], p_longid
[7] ) == -1 )
807 stream_t
*p_stream
= stream_UrlNew( p_this
, psz_url
);
812 int64_t i_size
= stream_Size( p_stream
);
815 stream_Delete( p_stream
);
819 uint8_t *p_buf
= (uint8_t*)malloc( i_size
);
822 stream_Delete( p_stream
);
826 int i_read
= stream_Read( p_stream
, p_buf
, (int)i_size
);
827 stream_Delete( p_stream
);
829 if( i_read
!= (int)i_size
)
831 msg_Dbg( p_this
, "Couldn't read full GPG key" );
836 public_key_t
*p_pkey
= (public_key_t
*) malloc( sizeof( public_key_t
) );
843 memcpy( p_pkey
->longid
, p_longid
, 8 );
845 int i_error
= parse_public_key( p_buf
, i_read
, p_pkey
, p_signature_issuer
);
848 if( i_error
!= VLC_SUCCESS
)
850 msg_Dbg( p_this
, "Couldn't parse GPG key" );
860 * Download the signature associated to a document or a binary file.
861 * We're given the file's url, we just append ".asc" to it and download
863 int download_signature( vlc_object_t
*p_this
, signature_packet_t
*p_sig
,
864 const char *psz_url
)
866 char *psz_sig
= (char*) malloc( strlen( psz_url
) + 4 + 1 ); /* ".asc" + \0 */
870 strcpy( psz_sig
, psz_url
);
871 strcat( psz_sig
, ".asc" );
873 stream_t
*p_stream
= stream_UrlNew( p_this
, psz_sig
);
879 int64_t i_size
= stream_Size( p_stream
);
881 msg_Dbg( p_this
, "Downloading signature (%"PRId64
" bytes)", i_size
);
882 uint8_t *p_buf
= (uint8_t*)malloc( i_size
);
885 stream_Delete( p_stream
);
889 int i_read
= stream_Read( p_stream
, p_buf
, (int)i_size
);
891 stream_Delete( p_stream
);
893 if( i_read
!= (int)i_size
)
896 "Couldn't download full signature (only %d bytes)", i_read
);
901 if( (uint8_t)*p_buf
< 0x80 ) /* ASCII */
903 msg_Dbg( p_this
, "Unarmoring signature" );
905 uint8_t* p_unarmored
= (uint8_t*) malloc( ( i_size
* 3 ) / 4 + 1 );
912 int i_bytes
= pgp_unarmor( (char*)p_buf
, i_size
, p_unarmored
, i_size
);
921 msg_Dbg( p_this
, "Unarmoring failed : corrupted signature ?" );
926 if( packet_type( *p_buf
) != SIGNATURE_PACKET
)
929 msg_Dbg( p_this
, "Not a signature: %d", *p_buf
);
933 size_t i_header_len
= packet_header_len( *p_buf
);
934 if( ( i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4 ) ||
935 i_header_len
+ 1 > (size_t)i_size
)
938 msg_Dbg( p_this
, "Invalid signature packet header" );
942 size_t i_len
= scalar_number( p_buf
+1, i_header_len
);
943 if( i_len
+ i_header_len
+ 1 != (size_t)i_size
)
946 msg_Dbg( p_this
, "Invalid signature packet" );
950 int i_ret
= parse_signature_packet( p_sig
, p_buf
+1+i_header_len
, i_len
);
952 if( i_ret
!= VLC_SUCCESS
)
954 msg_Dbg( p_this
, "Couldn't parse signature" );
958 if( p_sig
->type
!= BINARY_SIGNATURE
&& p_sig
->type
!= TEXT_SIGNATURE
)
960 msg_Dbg( p_this
, "Invalid signature type: %d", p_sig
->type
);
961 if( p_sig
->version
== 4 )
963 free( p_sig
->specific
.v4
.hashed_data
);
964 free( p_sig
->specific
.v4
.unhashed_data
);
972 #endif /* UPDATE_CHECK */