1 /*****************************************************************************
2 * update_crypto.c: DSA/SHA1 related functions used for updating
3 *****************************************************************************
4 * Copyright © 2008-2009 the VideoLAN team
7 * Authors: Rafaël Carré <funman@videolanorg>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU 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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, 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>
45 #include <vlc_charset.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 )
78 * fill a public_key_packet_t structure from public key packet data
79 * verify that it is a version 4 public key packet, using DSA
81 static int parse_public_key_packet( public_key_packet_t
*p_key
, uint8_t *p_buf
,
85 if( i_packet_len
> 418 || i_packet_len
< 6 )
90 p_key
->version
= *p_buf
++; i_read
++;
91 if( p_key
->version
!= 4 )
94 /* XXX: warn when timestamp is > date ? */
95 memcpy( p_key
->timestamp
, p_buf
, 4 ); p_buf
+= 4; i_read
+= 4;
97 p_key
->algo
= *p_buf
++; i_read
++;
98 if( p_key
->algo
!= PUBLIC_KEY_ALGO_DSA
)
102 if( i_read
+ 2 > i_packet_len
)
105 int i_p_len
= mpi_len( p_buf
);
107 if( i_p_len
> 128 || i_read
+ 2 + i_p_len
> i_packet_len
)
110 memcpy( p_key
->p
, p_buf
, 2+i_p_len
);
111 p_buf
+= 2+i_p_len
; i_read
+= 2+i_p_len
;
114 if( i_read
+ 2 > i_packet_len
)
117 int i_q_len
= mpi_len( p_buf
);
119 if( i_q_len
> 20 || i_read
+2+i_q_len
> i_packet_len
)
122 memcpy( p_key
->q
, p_buf
, 2+i_q_len
);
123 p_buf
+= 2+i_q_len
; i_read
+= 2+i_q_len
;
126 if( i_read
+ 2 > i_packet_len
)
129 int i_g_len
= mpi_len( p_buf
);
131 if( i_g_len
> 128 || i_read
+2+i_g_len
> i_packet_len
)
134 memcpy( p_key
->g
, p_buf
, 2+i_g_len
);
135 p_buf
+= 2+i_g_len
; i_read
+= 2+i_g_len
;
138 if( i_read
+ 2 > i_packet_len
)
141 int i_y_len
= mpi_len( p_buf
);
144 if( i_y_len
> 128 || i_read
+2+i_y_len
> i_packet_len
)
147 memcpy( p_key
->y
, p_buf
, 2+i_y_len
);
150 if( i_read
!= i_packet_len
) /* some extra data eh ? */
157 static size_t parse_signature_v3_packet( signature_packet_t
*p_sig
,
158 uint8_t *p_buf
, size_t i_sig_len
)
160 size_t i_read
= 1; /* we already read the version byte */
162 if( i_sig_len
< 19 ) /* signature is at least 19 bytes + the 2 MPIs */
165 p_sig
->specific
.v3
.hashed_data_len
= *p_buf
++; i_read
++;
166 if( p_sig
->specific
.v3
.hashed_data_len
!= 5 )
169 p_sig
->type
= *p_buf
++; i_read
++;
171 memcpy( p_sig
->specific
.v3
.timestamp
, p_buf
, 4 );
172 p_buf
+= 4; i_read
+= 4;
174 memcpy( p_sig
->issuer_longid
, p_buf
, 8 );
175 p_buf
+= 8; i_read
+= 8;
177 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
179 p_sig
->digest_algo
= *p_buf
++; i_read
++;
181 p_sig
->hash_verification
[0] = *p_buf
++; i_read
++;
182 p_sig
->hash_verification
[1] = *p_buf
++; i_read
++;
184 assert( i_read
== 19 );
191 * fill a signature_packet_v4_t from signature packet data
192 * verify that it was used with a DSA public key, using SHA-1 digest
194 static size_t parse_signature_v4_packet( signature_packet_t
*p_sig
,
195 uint8_t *p_buf
, size_t i_sig_len
)
197 size_t i_read
= 1; /* we already read the version byte */
199 if( i_sig_len
< 10 ) /* signature is at least 10 bytes + the 2 MPIs */
202 p_sig
->type
= *p_buf
++; i_read
++;
204 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
206 p_sig
->digest_algo
= *p_buf
++; i_read
++;
208 memcpy( p_sig
->specific
.v4
.hashed_data_len
, p_buf
, 2 );
209 p_buf
+= 2; i_read
+= 2;
211 size_t i_hashed_data_len
=
212 scalar_number( p_sig
->specific
.v4
.hashed_data_len
, 2 );
213 i_read
+= i_hashed_data_len
;
214 if( i_read
+ 4 > i_sig_len
)
217 p_sig
->specific
.v4
.hashed_data
= (uint8_t*) malloc( i_hashed_data_len
);
218 if( !p_sig
->specific
.v4
.hashed_data
)
220 memcpy( p_sig
->specific
.v4
.hashed_data
, p_buf
, i_hashed_data_len
);
221 p_buf
+= i_hashed_data_len
;
223 memcpy( p_sig
->specific
.v4
.unhashed_data_len
, p_buf
, 2 );
224 p_buf
+= 2; i_read
+= 2;
226 size_t i_unhashed_data_len
=
227 scalar_number( p_sig
->specific
.v4
.unhashed_data_len
, 2 );
228 i_read
+= i_unhashed_data_len
;
229 if( i_read
+ 2 > i_sig_len
)
232 p_sig
->specific
.v4
.unhashed_data
= (uint8_t*) malloc( i_unhashed_data_len
);
233 if( !p_sig
->specific
.v4
.unhashed_data
)
236 memcpy( p_sig
->specific
.v4
.unhashed_data
, p_buf
, i_unhashed_data_len
);
237 p_buf
+= i_unhashed_data_len
;
239 memcpy( p_sig
->hash_verification
, p_buf
, 2 );
240 p_buf
+= 2; i_read
+= 2;
242 uint8_t *p
, *max_pos
;
243 p
= p_sig
->specific
.v4
.unhashed_data
;
244 max_pos
= p
+ scalar_number( p_sig
->specific
.v4
.unhashed_data_len
, 2 );
251 size_t i_subpacket_len
;
254 if( p
+ 1 > max_pos
)
256 i_subpacket_len
= *p
++;
260 if( p
+ 2 > max_pos
)
262 i_subpacket_len
= (*p
++ - 192) << 8;
263 i_subpacket_len
+= *p
++ + 192;
267 if( p
+ 4 > max_pos
)
269 i_subpacket_len
= *++p
<< 24;
270 i_subpacket_len
+= *++p
<< 16;
271 i_subpacket_len
+= *++p
<< 8;
272 i_subpacket_len
+= *++p
;
275 if( *p
== ISSUER_SUBPACKET
)
277 if( p
+ 9 > max_pos
)
280 memcpy( &p_sig
->issuer_longid
, p
+1, 8 );
285 p
+= i_subpacket_len
;
290 static int parse_signature_packet( signature_packet_t
*p_sig
,
291 uint8_t *p_buf
, size_t i_sig_len
)
293 if( !i_sig_len
) /* 1st sanity check, we need at least the version */
296 p_sig
->version
= *p_buf
++;
299 switch( p_sig
->version
)
302 i_read
= parse_signature_v3_packet( p_sig
, p_buf
, i_sig_len
);
305 p_sig
->specific
.v4
.hashed_data
= NULL
;
306 p_sig
->specific
.v4
.unhashed_data
= NULL
;
307 i_read
= parse_signature_v4_packet( p_sig
, p_buf
, i_sig_len
);
313 if( i_read
== 0 ) /* signature packet parsing has failed */
316 if( p_sig
->public_key_algo
!= PUBLIC_KEY_ALGO_DSA
)
319 if( p_sig
->digest_algo
!= DIGEST_ALGO_SHA1
)
322 switch( p_sig
->type
)
324 case BINARY_SIGNATURE
:
326 case GENERIC_KEY_SIGNATURE
:
327 case PERSONA_KEY_SIGNATURE
:
328 case CASUAL_KEY_SIGNATURE
:
329 case POSITIVE_KEY_SIGNATURE
:
335 p_buf
--; /* rewind to the version byte */
338 if( i_read
+ 2 > i_sig_len
)
341 size_t i_r_len
= mpi_len( p_buf
); i_read
+= 2;
342 if( i_read
+ i_r_len
> i_sig_len
|| i_r_len
> 20 )
345 memcpy( p_sig
->r
, p_buf
, 2 + i_r_len
);
346 p_buf
+= 2 + i_r_len
;
349 if( i_read
+ 2 > i_sig_len
)
352 size_t i_s_len
= mpi_len( p_buf
); i_read
+= 2;
353 if( i_read
+ i_s_len
> i_sig_len
|| i_s_len
> 20 )
356 memcpy( p_sig
->s
, p_buf
, 2 + i_s_len
);
357 p_buf
+= 2 + i_s_len
;
360 assert( i_read
== i_sig_len
);
361 if( i_read
< i_sig_len
) /* some extra data, hm ? */
368 if( p_sig
->version
== 4 )
370 free( p_sig
->specific
.v4
.hashed_data
);
371 free( p_sig
->specific
.v4
.unhashed_data
);
379 * crc_octets() was lamely copied from rfc 2440
380 * Copyright (C) The Internet Society (1998). All Rights Reserved.
382 #define CRC24_INIT 0xB704CEL
383 #define CRC24_POLY 0x1864CFBL
385 static long crc_octets( uint8_t *octets
, size_t len
)
387 long crc
= CRC24_INIT
;
391 crc
^= (*octets
++) << 16;
392 for (i
= 0; i
< 8; i
++)
399 return crc
& 0xFFFFFFL
;
404 * Transform an armored document in binary format
405 * Used on public keys and signatures
407 static int pgp_unarmor( char *p_ibuf
, size_t i_ibuf_len
,
408 uint8_t *p_obuf
, size_t i_obuf_len
)
410 char *p_ipos
= p_ibuf
;
411 uint8_t *p_opos
= p_obuf
;
413 int i_header_skipped
= 0;
415 while( !i_end
&& p_ipos
< p_ibuf
+ i_ibuf_len
&& *p_ipos
!= '=' )
417 if( *p_ipos
== '\r' || *p_ipos
== '\n' )
423 size_t i_line_len
= strcspn( p_ipos
, "\r\n" );
424 if( i_line_len
== 0 )
427 if( !i_header_skipped
)
429 if( !strncmp( p_ipos
, "-----BEGIN PGP", 14 ) )
430 i_header_skipped
= 1;
432 p_ipos
+= i_line_len
+ 1;
436 if( !strncmp( p_ipos
, "Version:", 8 ) )
438 p_ipos
+= i_line_len
+ 1;
442 if( p_ipos
[i_line_len
- 1] == '=' )
445 p_ipos
[i_line_len
- 1] = '\0';
448 p_ipos
[i_line_len
] = '\0';
450 p_opos
+= vlc_b64_decode_binary_to_buffer( p_opos
,
451 p_obuf
- p_opos
+ i_obuf_len
, p_ipos
);
452 p_ipos
+= i_line_len
+ 1;
455 /* XXX: the CRC is OPTIONAL, really require it ? */
456 if( p_ipos
+ 5 > p_ibuf
+ i_ibuf_len
|| *p_ipos
++ != '=' )
460 if( vlc_b64_decode_binary_to_buffer( p_crc
, 3, p_ipos
) != 3 )
463 long l_crc
= crc_octets( p_obuf
, p_opos
- p_obuf
);
464 long l_crc2
= ( 0 << 24 ) + ( p_crc
[0] << 16 ) + ( p_crc
[1] << 8 ) + p_crc
[2];
466 return l_crc2
== l_crc
? p_opos
- p_obuf
: 0;
471 * Verify an OpenPGP signature made on some SHA-1 hash, with some DSA public key
473 int verify_signature( uint8_t *p_r
, uint8_t *p_s
, public_key_packet_t
*p_key
,
476 /* the data to be verified (a SHA-1 hash) */
477 const char *hash_sexp_s
= "(data(flags raw)(value %m))";
479 const char *key_sexp_s
= "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
481 const char *sig_sexp_s
= "(sig-val(dsa(r %m )(s %m )))";
484 gcry_mpi_t p
, q
, g
, y
, r
, s
, hash
;
485 p
= q
= g
= y
= r
= s
= hash
= NULL
;
486 gcry_sexp_t key_sexp
, hash_sexp
, sig_sexp
;
487 key_sexp
= hash_sexp
= sig_sexp
= NULL
;
489 int i_p_len
= mpi_len( p_key
->p
);
490 int i_q_len
= mpi_len( p_key
->q
);
491 int i_g_len
= mpi_len( p_key
->g
);
492 int i_y_len
= mpi_len( p_key
->y
);
493 if( gcry_mpi_scan( &p
, GCRYMPI_FMT_USG
, p_key
->p
+ 2, i_p_len
, NULL
) ||
494 gcry_mpi_scan( &q
, GCRYMPI_FMT_USG
, p_key
->q
+ 2, i_q_len
, NULL
) ||
495 gcry_mpi_scan( &g
, GCRYMPI_FMT_USG
, p_key
->g
+ 2, i_g_len
, NULL
) ||
496 gcry_mpi_scan( &y
, GCRYMPI_FMT_USG
, p_key
->y
+ 2, i_y_len
, NULL
) ||
497 gcry_sexp_build( &key_sexp
, &erroff
, key_sexp_s
, p
, q
, g
, y
) )
500 int i_r_len
= mpi_len( p_r
);
501 int i_s_len
= mpi_len( p_s
);
502 if( gcry_mpi_scan( &r
, GCRYMPI_FMT_USG
, p_r
+ 2, i_r_len
, NULL
) ||
503 gcry_mpi_scan( &s
, GCRYMPI_FMT_USG
, p_s
+ 2, i_s_len
, NULL
) ||
504 gcry_sexp_build( &sig_sexp
, &erroff
, sig_sexp_s
, r
, s
) )
508 if( gcry_mpi_scan( &hash
, GCRYMPI_FMT_USG
, p_hash
, i_hash_len
, NULL
) ||
509 gcry_sexp_build( &hash_sexp
, &erroff
, hash_sexp_s
, hash
) )
512 if( gcry_pk_verify( sig_sexp
, hash_sexp
, key_sexp
) )
518 if( p
) gcry_mpi_release( p
);
519 if( q
) gcry_mpi_release( q
);
520 if( g
) gcry_mpi_release( g
);
521 if( y
) gcry_mpi_release( y
);
522 if( r
) gcry_mpi_release( r
);
523 if( s
) gcry_mpi_release( s
);
524 if( hash
) gcry_mpi_release( hash
);
525 if( key_sexp
) gcry_sexp_release( key_sexp
);
526 if( sig_sexp
) gcry_sexp_release( sig_sexp
);
527 if( hash_sexp
) gcry_sexp_release( hash_sexp
);
533 * fill a public_key_t with public key data, including:
534 * * public key packet
535 * * signature packet issued by key which long id is p_sig_issuer
538 int parse_public_key( const uint8_t *p_key_data
, size_t i_key_len
,
539 public_key_t
*p_key
, const uint8_t *p_sig_issuer
)
541 uint8_t *pos
= (uint8_t*) p_key_data
;
542 uint8_t *max_pos
= pos
+ i_key_len
;
545 #define PUBLIC_KEY_FOUND 0x01
546 #define USER_ID_FOUND 0x02
547 #define SIGNATURE_FOUND 0X04
549 uint8_t *p_key_unarmored
= NULL
;
551 p_key
->psz_username
= NULL
;
552 p_key
->sig
.specific
.v4
.hashed_data
= NULL
;
553 p_key
->sig
.specific
.v4
.unhashed_data
= NULL
;
555 if( !( *pos
& 0x80 ) )
556 { /* first byte is ASCII, unarmoring */
557 p_key_unarmored
= (uint8_t*)malloc( i_key_len
);
558 if( !p_key_unarmored
)
560 int i_len
= pgp_unarmor( (char*)p_key_data
, i_key_len
,
561 p_key_unarmored
, i_key_len
);
566 pos
= p_key_unarmored
;
567 max_pos
= pos
+ i_len
;
570 while( pos
< max_pos
)
572 if( !(*pos
& 0x80) || *pos
& 0x40 )
575 int i_type
= packet_type( *pos
);
577 int i_header_len
= packet_header_len( *pos
++ );
578 if( pos
+ i_header_len
> max_pos
||
579 ( i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4 ) )
582 int i_packet_len
= scalar_number( pos
, i_header_len
);
585 if( pos
+ i_packet_len
> max_pos
)
590 case PUBLIC_KEY_PACKET
:
591 i_status
|= PUBLIC_KEY_FOUND
;
592 if( parse_public_key_packet( &p_key
->key
, pos
, i_packet_len
) != VLC_SUCCESS
)
596 case SIGNATURE_PACKET
: /* we accept only v4 signatures here */
597 if( i_status
& SIGNATURE_FOUND
|| !p_sig_issuer
)
599 int i_ret
= parse_signature_packet( &p_key
->sig
, pos
,
601 if( i_ret
== VLC_SUCCESS
)
603 if( p_key
->sig
.version
!= 4 )
605 if( memcmp( p_key
->sig
.issuer_longid
, p_sig_issuer
, 8 ) )
607 free( p_key
->sig
.specific
.v4
.hashed_data
);
608 free( p_key
->sig
.specific
.v4
.unhashed_data
);
609 p_key
->sig
.specific
.v4
.hashed_data
= NULL
;
610 p_key
->sig
.specific
.v4
.unhashed_data
= NULL
;
613 i_status
|= SIGNATURE_FOUND
;
618 if( p_key
->psz_username
) /* save only the first User ID */
620 i_status
|= USER_ID_FOUND
;
621 p_key
->psz_username
= (uint8_t*)malloc( i_packet_len
+ 1);
622 if( !p_key
->psz_username
)
625 memcpy( p_key
->psz_username
, pos
, i_packet_len
);
626 p_key
->psz_username
[i_packet_len
] = '\0';
634 free( p_key_unarmored
);
636 if( !( i_status
& ( PUBLIC_KEY_FOUND
| USER_ID_FOUND
) ) )
639 if( p_sig_issuer
&& !( i_status
& SIGNATURE_FOUND
) )
645 if( p_key
->sig
.version
== 4 )
647 free( p_key
->sig
.specific
.v4
.hashed_data
);
648 free( p_key
->sig
.specific
.v4
.unhashed_data
);
650 free( p_key
->psz_username
);
651 free( p_key_unarmored
);
656 /* hash a binary file */
657 static int hash_from_binary_file( const char *psz_file
, gcry_md_hd_t hd
)
659 uint8_t buffer
[4096];
662 FILE *f
= utf8_fopen( psz_file
, "r" );
666 while( ( i_read
= fread( buffer
, 1, sizeof(buffer
), f
) ) > 0 )
667 gcry_md_write( hd
, buffer
, i_read
);
675 /* final part of the hash */
676 static uint8_t *hash_finish( gcry_md_hd_t hd
, signature_packet_t
*p_sig
)
678 if( p_sig
->version
== 3 )
680 gcry_md_putc( hd
, p_sig
->type
);
681 gcry_md_write( hd
, &p_sig
->specific
.v3
.timestamp
, 4 );
683 else if( p_sig
->version
== 4 )
685 gcry_md_putc( hd
, p_sig
->version
);
686 gcry_md_putc( hd
, p_sig
->type
);
687 gcry_md_putc( hd
, p_sig
->public_key_algo
);
688 gcry_md_putc( hd
, p_sig
->digest_algo
);
689 gcry_md_write( hd
, p_sig
->specific
.v4
.hashed_data_len
, 2 );
690 size_t i_len
= scalar_number( p_sig
->specific
.v4
.hashed_data_len
, 2 );
691 gcry_md_write( hd
, p_sig
->specific
.v4
.hashed_data
, i_len
);
693 gcry_md_putc( hd
, 0x04 );
694 gcry_md_putc( hd
, 0xFF );
696 i_len
+= 6; /* hashed data + 6 bytes header */
698 gcry_md_putc( hd
, (i_len
>> 24) & 0xff );
699 gcry_md_putc( hd
, (i_len
>> 16) & 0xff );
700 gcry_md_putc( hd
, (i_len
>> 8) & 0xff );
701 gcry_md_putc( hd
, (i_len
) & 0xff );
704 { /* RFC 4880 only tells about versions 3 and 4 */
710 uint8_t *p_tmp
= (uint8_t*) gcry_md_read( hd
, GCRY_MD_SHA1
);
711 uint8_t *p_hash
= malloc( 20 );
713 memcpy( p_hash
, p_tmp
, 20 );
720 * return a sha1 hash of a text
722 uint8_t *hash_sha1_from_text( const char *psz_string
,
723 signature_packet_t
*p_sig
)
726 if( gcry_md_open( &hd
, GCRY_MD_SHA1
, 0 ) )
729 if( p_sig
->type
== TEXT_SIGNATURE
)
732 size_t i_len
= strcspn( psz_string
, "\r\n" );
736 gcry_md_write( hd
, psz_string
, i_len
);
737 gcry_md_putc( hd
, '\r' );
738 gcry_md_putc( hd
, '\n' );
741 while( *psz_string
== '\r' || *psz_string
== '\n' )
745 gcry_md_write( hd
, psz_string
, strlen( psz_string
) );
747 return hash_finish( hd
, p_sig
);
752 * return a sha1 hash of a file
754 uint8_t *hash_sha1_from_file( const char *psz_file
, signature_packet_t
*p_sig
)
757 if( gcry_md_open( &hd
, GCRY_MD_SHA1
, 0 ) )
760 if( hash_from_binary_file( psz_file
, hd
) < 0 )
766 return hash_finish( hd
, p_sig
);
771 * Generate a SHA1 hash on a public key, to verify a signature made on that hash
772 * Note that we need the signature (v4) to compute the hash
774 uint8_t *hash_sha1_from_public_key( public_key_t
*p_pkey
)
776 if( p_pkey
->sig
.version
!= 4 )
779 if( p_pkey
->sig
.type
< GENERIC_KEY_SIGNATURE
||
780 p_pkey
->sig
.type
> POSITIVE_KEY_SIGNATURE
)
783 gcry_error_t error
= 0;
786 error
= gcry_md_open( &hd
, GCRY_MD_SHA1
, 0 );
790 gcry_md_putc( hd
, 0x99 );
792 size_t i_p_len
= mpi_len( p_pkey
->key
.p
);
793 size_t i_g_len
= mpi_len( p_pkey
->key
.g
);
794 size_t i_q_len
= mpi_len( p_pkey
->key
.q
);
795 size_t i_y_len
= mpi_len( p_pkey
->key
.y
);
797 size_t i_size
= 6 + 2*4 + i_p_len
+ i_g_len
+ i_q_len
+ i_y_len
;
799 gcry_md_putc( hd
, (i_size
>> 8) & 0xff );
800 gcry_md_putc( hd
, i_size
& 0xff );
802 gcry_md_putc( hd
, p_pkey
->key
.version
);
803 gcry_md_write( hd
, p_pkey
->key
.timestamp
, 4 );
804 gcry_md_putc( hd
, p_pkey
->key
.algo
);
806 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.p
, 2 );
807 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.p
+ 2, i_p_len
);
809 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.q
, 2 );
810 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.q
+ 2, i_q_len
);
812 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.g
, 2 );
813 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.g
+ 2, i_g_len
);
815 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.y
, 2 );
816 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.y
+ 2, i_y_len
);
818 gcry_md_putc( hd
, 0xb4 );
820 size_t i_len
= strlen((char*)p_pkey
->psz_username
);
822 gcry_md_putc( hd
, (i_len
>> 24) & 0xff );
823 gcry_md_putc( hd
, (i_len
>> 16) & 0xff );
824 gcry_md_putc( hd
, (i_len
>> 8) & 0xff );
825 gcry_md_putc( hd
, (i_len
) & 0xff );
827 gcry_md_write( hd
, p_pkey
->psz_username
, i_len
);
829 uint8_t *p_hash
= hash_finish( hd
, &p_pkey
->sig
);
831 p_hash
[0] != p_pkey
->sig
.hash_verification
[0] ||
832 p_hash
[1] != p_pkey
->sig
.hash_verification
[1] )
842 * download a public key (the last one) from videolan server, and parse it
844 public_key_t
*download_key( vlc_object_t
*p_this
,
845 const uint8_t *p_longid
, const uint8_t *p_signature_issuer
)
848 if( asprintf( &psz_url
, "http://download.videolan.org/pub/keys/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X.asc",
849 p_longid
[0], p_longid
[1], p_longid
[2], p_longid
[3],
850 p_longid
[4], p_longid
[5], p_longid
[6], p_longid
[7] ) == -1 )
853 stream_t
*p_stream
= stream_UrlNew( p_this
, psz_url
);
858 int64_t i_size
= stream_Size( p_stream
);
861 stream_Delete( p_stream
);
865 uint8_t *p_buf
= (uint8_t*)malloc( i_size
);
868 stream_Delete( p_stream
);
872 int i_read
= stream_Read( p_stream
, p_buf
, (int)i_size
);
873 stream_Delete( p_stream
);
875 if( i_read
!= (int)i_size
)
877 msg_Dbg( p_this
, "Couldn't read full GPG key" );
882 public_key_t
*p_pkey
= (public_key_t
*) malloc( sizeof( public_key_t
) );
889 memcpy( p_pkey
->longid
, p_longid
, 8 );
891 int i_error
= parse_public_key( p_buf
, i_read
, p_pkey
, p_signature_issuer
);
894 if( i_error
!= VLC_SUCCESS
)
896 msg_Dbg( p_this
, "Couldn't parse GPG key" );
906 * Download the signature associated to a document or a binary file.
907 * We're given the file's url, we just append ".asc" to it and download
909 int download_signature( vlc_object_t
*p_this
, signature_packet_t
*p_sig
,
910 const char *psz_url
)
912 char *psz_sig
= (char*) malloc( strlen( psz_url
) + 4 + 1 ); /* ".asc" + \0 */
916 strcpy( psz_sig
, psz_url
);
917 strcat( psz_sig
, ".asc" );
919 stream_t
*p_stream
= stream_UrlNew( p_this
, psz_sig
);
925 int64_t i_size
= stream_Size( p_stream
);
927 msg_Dbg( p_this
, "Downloading signature (%"PRId64
" bytes)", i_size
);
928 uint8_t *p_buf
= (uint8_t*)malloc( i_size
);
931 stream_Delete( p_stream
);
935 int i_read
= stream_Read( p_stream
, p_buf
, (int)i_size
);
937 stream_Delete( p_stream
);
939 if( i_read
!= (int)i_size
)
942 "Couldn't download full signature (only %d bytes)", i_read
);
947 if( (uint8_t)*p_buf
< 0x80 ) /* ASCII */
949 msg_Dbg( p_this
, "Unarmoring signature" );
951 uint8_t* p_unarmored
= (uint8_t*) malloc( ( i_size
* 3 ) / 4 + 1 );
958 int i_bytes
= pgp_unarmor( (char*)p_buf
, i_size
, p_unarmored
, i_size
);
967 msg_Dbg( p_this
, "Unarmoring failed : corrupted signature ?" );
972 if( packet_type( *p_buf
) != SIGNATURE_PACKET
)
975 msg_Dbg( p_this
, "Not a signature: %d", *p_buf
);
979 size_t i_header_len
= packet_header_len( *p_buf
);
980 if( ( i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4 ) ||
981 i_header_len
+ 1 > (size_t)i_size
)
984 msg_Dbg( p_this
, "Invalid signature packet header" );
988 size_t i_len
= scalar_number( p_buf
+1, i_header_len
);
989 if( i_len
+ i_header_len
+ 1 != (size_t)i_size
)
992 msg_Dbg( p_this
, "Invalid signature packet" );
996 int i_ret
= parse_signature_packet( p_sig
, p_buf
+1+i_header_len
, i_len
);
998 if( i_ret
!= VLC_SUCCESS
)
1000 msg_Dbg( p_this
, "Couldn't parse signature" );
1004 if( p_sig
->type
!= BINARY_SIGNATURE
&& p_sig
->type
!= TEXT_SIGNATURE
)
1006 msg_Dbg( p_this
, "Invalid signature type: %d", p_sig
->type
);
1007 if( p_sig
->version
== 4 )
1009 free( p_sig
->specific
.v4
.hashed_data
);
1010 free( p_sig
->specific
.v4
.unhashed_data
);
1012 return VLC_EGENERIC
;
1018 #endif /* UPDATE_CHECK */