1 /*****************************************************************************
2 * update_crypto.c: OpenPGP 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 *****************************************************************************/
41 #include "vlc_common.h"
42 #include <vlc_stream.h>
43 #include <vlc_strings.h>
49 /*****************************************************************************
51 *****************************************************************************/
53 #define packet_type( c ) ( ( c & 0x3c ) >> 2 ) /* 0x3C = 00111100 */
54 #define packet_header_len( c ) ( ( c & 0x03 ) + 1 ) /* number of bytes in a packet header */
57 static inline int scalar_number( const uint8_t *p
, int header_len
)
59 assert( header_len
== 1 || header_len
== 2 || header_len
== 4 );
63 else if( header_len
== 2 )
64 return( (p
[0] << 8) + p
[1] );
65 else if( header_len
== 4 )
66 return( (p
[0] << 24) + (p
[1] << 16) + (p
[2] << 8) + p
[3] );
72 /* number of data bytes in a MPI */
73 static int mpi_len(const uint8_t *mpi
)
75 return (scalar_number(mpi
, 2) + 7) / 8;
78 static size_t read_mpi(uint8_t *dst
, const uint8_t *buf
, size_t buflen
, size_t bits
)
83 size_t n
= mpi_len(buf
);
97 #define READ_MPI(d, bits) do { \
98 size_t n = read_mpi(d, p_buf, i_packet_len - i_read, bits); \
105 * fill a public_key_packet_t structure from public key packet data
106 * verify that it is a version 4 public key packet, using DSA or RSA
108 static int parse_public_key_packet( public_key_packet_t
*p_key
,
109 const uint8_t *p_buf
, size_t i_packet_len
)
111 if( i_packet_len
< 6 )
116 p_key
->version
= *p_buf
++; i_read
++;
117 if( p_key
->version
!= 4 )
120 /* XXX: warn when timestamp is > date ? */
121 memcpy( p_key
->timestamp
, p_buf
, 4 ); p_buf
+= 4; i_read
+= 4;
123 p_key
->algo
= *p_buf
++; i_read
++;
124 if( p_key
->algo
== GCRY_PK_DSA
) {
125 READ_MPI(p_key
->sig
.dsa
.p
, 3072);
126 READ_MPI(p_key
->sig
.dsa
.q
, 256);
127 READ_MPI(p_key
->sig
.dsa
.g
, 3072);
128 READ_MPI(p_key
->sig
.dsa
.y
, 3072);
129 } else if ( p_key
->algo
== GCRY_PK_RSA
) {
130 READ_MPI(p_key
->sig
.rsa
.n
, 4096);
131 READ_MPI(p_key
->sig
.rsa
.e
, 4096);
135 if( i_read
== i_packet_len
)
138 /* some extra data eh ? */
145 static size_t parse_signature_v3_packet( signature_packet_t
*p_sig
,
146 const uint8_t *p_buf
, size_t i_sig_len
)
148 size_t i_read
= 1; /* we already read the version byte */
150 if( i_sig_len
< 19 ) /* signature is at least 19 bytes + the 2 MPIs */
153 p_sig
->specific
.v3
.hashed_data_len
= *p_buf
++; i_read
++;
154 if( p_sig
->specific
.v3
.hashed_data_len
!= 5 )
157 p_sig
->type
= *p_buf
++; i_read
++;
159 memcpy( p_sig
->specific
.v3
.timestamp
, p_buf
, 4 );
160 p_buf
+= 4; i_read
+= 4;
162 memcpy( p_sig
->issuer_longid
, p_buf
, 8 );
163 p_buf
+= 8; i_read
+= 8;
165 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
167 p_sig
->digest_algo
= *p_buf
++; i_read
++;
169 p_sig
->hash_verification
[0] = *p_buf
++; i_read
++;
170 p_sig
->hash_verification
[1] = *p_buf
++; i_read
++;
172 assert( i_read
== 19 );
179 * fill a signature_packet_v4_t from signature packet data
180 * verify that it was used with a DSA or RSA public key
182 static size_t parse_signature_v4_packet( signature_packet_t
*p_sig
,
183 const uint8_t *p_buf
, size_t i_sig_len
)
185 size_t i_read
= 1; /* we already read the version byte */
187 if( i_sig_len
< 10 ) /* signature is at least 10 bytes + the 2 MPIs */
190 p_sig
->type
= *p_buf
++; i_read
++;
192 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
193 if (p_sig
->public_key_algo
!= GCRY_PK_DSA
&& p_sig
->public_key_algo
!= GCRY_PK_RSA
)
196 p_sig
->digest_algo
= *p_buf
++; i_read
++;
198 memcpy( p_sig
->specific
.v4
.hashed_data_len
, p_buf
, 2 );
199 p_buf
+= 2; i_read
+= 2;
201 size_t i_hashed_data_len
=
202 scalar_number( p_sig
->specific
.v4
.hashed_data_len
, 2 );
203 i_read
+= i_hashed_data_len
;
204 if( i_read
+ 4 > i_sig_len
)
207 p_sig
->specific
.v4
.hashed_data
= (uint8_t*) malloc( i_hashed_data_len
);
208 if( !p_sig
->specific
.v4
.hashed_data
)
210 memcpy( p_sig
->specific
.v4
.hashed_data
, p_buf
, i_hashed_data_len
);
211 p_buf
+= i_hashed_data_len
;
213 memcpy( p_sig
->specific
.v4
.unhashed_data_len
, p_buf
, 2 );
214 p_buf
+= 2; i_read
+= 2;
216 size_t i_unhashed_data_len
=
217 scalar_number( p_sig
->specific
.v4
.unhashed_data_len
, 2 );
218 i_read
+= i_unhashed_data_len
;
219 if( i_read
+ 2 > i_sig_len
)
222 p_sig
->specific
.v4
.unhashed_data
= (uint8_t*) malloc( i_unhashed_data_len
);
223 if( !p_sig
->specific
.v4
.unhashed_data
)
226 memcpy( p_sig
->specific
.v4
.unhashed_data
, p_buf
, i_unhashed_data_len
);
227 p_buf
+= i_unhashed_data_len
;
229 memcpy( p_sig
->hash_verification
, p_buf
, 2 );
230 p_buf
+= 2; i_read
+= 2;
232 uint8_t *p
, *max_pos
;
233 p
= p_sig
->specific
.v4
.unhashed_data
;
234 max_pos
= p
+ scalar_number( p_sig
->specific
.v4
.unhashed_data_len
, 2 );
241 size_t i_subpacket_len
;
244 if( p
+ 1 > max_pos
)
246 i_subpacket_len
= *p
++;
250 if( p
+ 2 > max_pos
)
252 i_subpacket_len
= (*p
++ - 192) << 8;
253 i_subpacket_len
+= *p
++ + 192;
257 if( ++p
+ 4 > max_pos
)
259 i_subpacket_len
= U32_AT(p
);
263 if( *p
== ISSUER_SUBPACKET
)
265 if( p
+ 9 > max_pos
)
268 memcpy( &p_sig
->issuer_longid
, p
+1, 8 );
273 p
+= i_subpacket_len
;
278 static int parse_signature_packet( signature_packet_t
*p_sig
,
279 const uint8_t *p_buf
, size_t i_packet_len
)
281 if( !i_packet_len
) /* 1st sanity check, we need at least the version */
284 p_sig
->version
= *p_buf
++;
287 switch( p_sig
->version
)
290 i_read
= parse_signature_v3_packet( p_sig
, p_buf
, i_packet_len
);
293 p_sig
->specific
.v4
.hashed_data
= NULL
;
294 p_sig
->specific
.v4
.unhashed_data
= NULL
;
295 i_read
= parse_signature_v4_packet( p_sig
, p_buf
, i_packet_len
);
301 if( i_read
== 0 ) /* signature packet parsing has failed */
304 if( p_sig
->public_key_algo
!= GCRY_PK_DSA
&& p_sig
->public_key_algo
!= GCRY_PK_RSA
)
307 switch( p_sig
->type
)
309 case BINARY_SIGNATURE
:
311 case GENERIC_KEY_SIGNATURE
:
312 case PERSONA_KEY_SIGNATURE
:
313 case CASUAL_KEY_SIGNATURE
:
314 case POSITIVE_KEY_SIGNATURE
:
320 p_buf
--; /* rewind to the version byte */
323 if( p_sig
->public_key_algo
== GCRY_PK_DSA
) {
324 READ_MPI(p_sig
->algo_specific
.dsa
.r
, 256);
325 READ_MPI(p_sig
->algo_specific
.dsa
.s
, 256);
326 } else if ( p_sig
->public_key_algo
== GCRY_PK_RSA
) {
327 READ_MPI(p_sig
->algo_specific
.rsa
.s
, 4096);
331 assert( i_read
== i_packet_len
);
332 if( i_read
< i_packet_len
) /* some extra data, hm ? */
339 if( p_sig
->version
== 4 )
341 free( p_sig
->specific
.v4
.hashed_data
);
342 free( p_sig
->specific
.v4
.unhashed_data
);
350 * crc_octets() was lamely copied from rfc 2440
351 * Copyright (C) The Internet Society (1998). All Rights Reserved.
353 #define CRC24_INIT 0xB704CEL
354 #define CRC24_POLY 0x1864CFBL
356 static long crc_octets( uint8_t *octets
, size_t len
)
358 long crc
= CRC24_INIT
;
362 crc
^= (*octets
++) << 16;
363 for (i
= 0; i
< 8; i
++)
370 return crc
& 0xFFFFFFL
;
375 * Transform an armored document in binary format
376 * Used on public keys and signatures
378 static int pgp_unarmor( const char *p_ibuf
, size_t i_ibuf_len
,
379 uint8_t *p_obuf
, size_t i_obuf_len
)
381 const char *p_ipos
= p_ibuf
;
382 uint8_t *p_opos
= p_obuf
;
384 int i_header_skipped
= 0;
386 while( !i_end
&& p_ipos
< p_ibuf
+ i_ibuf_len
&& *p_ipos
!= '=' )
388 if( *p_ipos
== '\r' || *p_ipos
== '\n' )
394 size_t i_line_len
= strcspn( p_ipos
, "\r\n" );
395 if( i_line_len
== 0 )
398 if( !i_header_skipped
)
400 if( !strncmp( p_ipos
, "-----BEGIN PGP", 14 ) )
401 i_header_skipped
= 1;
403 p_ipos
+= i_line_len
+ 1;
407 if( !strncmp( p_ipos
, "Version:", 8 ) )
409 p_ipos
+= i_line_len
+ 1;
413 if( p_ipos
[i_line_len
- 1] == '=' )
418 p_opos
+= vlc_b64_decode_binary_to_buffer( p_opos
,
419 p_obuf
- p_opos
+ i_obuf_len
, p_ipos
);
420 p_ipos
+= i_line_len
+ 1;
423 /* XXX: the CRC is OPTIONAL, really require it ? */
424 if( p_ipos
+ 5 > p_ibuf
+ i_ibuf_len
|| *p_ipos
++ != '=' )
428 if( vlc_b64_decode_binary_to_buffer( p_crc
, 3, p_ipos
) != 3 )
431 long l_crc
= crc_octets( p_obuf
, p_opos
- p_obuf
);
432 long l_crc2
= ( 0 << 24 ) + ( p_crc
[0] << 16 ) + ( p_crc
[1] << 8 ) + p_crc
[2];
434 return l_crc2
== l_crc
? p_opos
- p_obuf
: 0;
437 static int rsa_pkcs1_encode_sig(gcry_mpi_t
*r_result
, size_t size
,
438 const uint8_t *hash
, int algo
)
441 uint8_t frame
[4096/8];
443 size_t asnlen
= sizeof(asn
);
444 size_t hashlen
= gcry_md_get_algo_dlen(algo
);
446 if (gcry_md_algo_info(algo
, GCRYCTL_GET_ASNOID
, asn
, &asnlen
))
449 if (!hashlen
|| hashlen
+ asnlen
+ 4 > size
)
453 frame
[1] = 1; /* block type */
454 int pad
= size
- hashlen
- asnlen
- 3 ;
455 memset (&frame
[2], 0xff, pad
);
457 memcpy(&frame
[3+pad
], asn
, asnlen
);
458 memcpy(&frame
[3+pad
+asnlen
], hash
, hashlen
);
460 if (gcry_mpi_scan(r_result
, GCRYMPI_FMT_USG
, frame
, size
, &size
))
466 * Verify an OpenPGP signature made with some RSA public key
468 static int verify_signature_rsa( signature_packet_t
*sign
, public_key_packet_t
*p_key
,
471 int ret
= VLC_EGENERIC
;
472 /* the data to be verified (a hash) */
473 const char *hash_sexp_s
= "(data(flags raw)(value %m))";
475 const char *key_sexp_s
= "(public-key(rsa(n %m)(e %m)))";
477 const char *sig_sexp_s
= "(sig-val(rsa(s%m)))";
480 gcry_mpi_t n
, e
, s
, hash
;
481 n
= e
= s
= hash
= NULL
;
482 gcry_sexp_t key_sexp
, hash_sexp
, sig_sexp
;
483 key_sexp
= hash_sexp
= sig_sexp
= NULL
;
485 int i_n_len
= mpi_len( p_key
->sig
.rsa
.n
);
486 int i_e_len
= mpi_len( p_key
->sig
.rsa
.e
);
487 if( gcry_mpi_scan( &n
, GCRYMPI_FMT_USG
, p_key
->sig
.rsa
.n
+ 2, i_n_len
, NULL
) ||
488 gcry_mpi_scan( &e
, GCRYMPI_FMT_USG
, p_key
->sig
.rsa
.e
+ 2, i_e_len
, NULL
) ||
489 gcry_sexp_build( &key_sexp
, &erroff
, key_sexp_s
, n
, e
) )
492 uint8_t *p_s
= sign
->algo_specific
.rsa
.s
;
493 int i_s_len
= mpi_len( p_s
);
494 if( gcry_mpi_scan( &s
, GCRYMPI_FMT_USG
, p_s
+ 2, i_s_len
, NULL
) ||
495 gcry_sexp_build( &sig_sexp
, &erroff
, sig_sexp_s
, s
) )
498 if( rsa_pkcs1_encode_sig (&hash
, i_n_len
, p_hash
, sign
->digest_algo
) ||
499 gcry_sexp_build( &hash_sexp
, &erroff
, hash_sexp_s
, hash
) )
502 if( gcry_pk_verify( sig_sexp
, hash_sexp
, key_sexp
) )
508 if( n
) gcry_mpi_release( n
);
509 if( e
) gcry_mpi_release( e
);
510 if( s
) gcry_mpi_release( s
);
511 if( hash
) gcry_mpi_release( hash
);
512 if( key_sexp
) gcry_sexp_release( key_sexp
);
513 if( sig_sexp
) gcry_sexp_release( sig_sexp
);
514 if( hash_sexp
) gcry_sexp_release( hash_sexp
);
519 * Verify an OpenPGP signature made with some DSA public key
521 static int verify_signature_dsa( signature_packet_t
*sign
, public_key_packet_t
*p_key
,
524 int ret
= VLC_EGENERIC
;
526 /* the data to be verified (a hash) */
527 const char *hash_sexp_s
= "(data(flags raw)(value %m))";
529 const char *key_sexp_s
= "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
531 const char *sig_sexp_s
= "(sig-val(dsa(r %m )(s %m )))";
534 gcry_mpi_t p
, q
, g
, y
, r
, s
, hash
;
535 p
= q
= g
= y
= r
= s
= hash
= NULL
;
536 gcry_sexp_t key_sexp
, hash_sexp
, sig_sexp
;
537 key_sexp
= hash_sexp
= sig_sexp
= NULL
;
539 int i_p_len
= mpi_len( p_key
->sig
.dsa
.p
);
540 int i_q_len
= mpi_len( p_key
->sig
.dsa
.q
);
541 int i_g_len
= mpi_len( p_key
->sig
.dsa
.g
);
542 int i_y_len
= mpi_len( p_key
->sig
.dsa
.y
);
543 if( gcry_mpi_scan( &p
, GCRYMPI_FMT_USG
, p_key
->sig
.dsa
.p
+ 2, i_p_len
, NULL
) ||
544 gcry_mpi_scan( &q
, GCRYMPI_FMT_USG
, p_key
->sig
.dsa
.q
+ 2, i_q_len
, NULL
) ||
545 gcry_mpi_scan( &g
, GCRYMPI_FMT_USG
, p_key
->sig
.dsa
.g
+ 2, i_g_len
, NULL
) ||
546 gcry_mpi_scan( &y
, GCRYMPI_FMT_USG
, p_key
->sig
.dsa
.y
+ 2, i_y_len
, NULL
) ||
547 gcry_sexp_build( &key_sexp
, &erroff
, key_sexp_s
, p
, q
, g
, y
) )
550 uint8_t *p_r
= sign
->algo_specific
.dsa
.r
;
551 uint8_t *p_s
= sign
->algo_specific
.dsa
.s
;
552 int i_r_len
= mpi_len( p_r
);
553 int i_s_len
= mpi_len( p_s
);
554 if( gcry_mpi_scan( &r
, GCRYMPI_FMT_USG
, p_r
+ 2, i_r_len
, NULL
) ||
555 gcry_mpi_scan( &s
, GCRYMPI_FMT_USG
, p_s
+ 2, i_s_len
, NULL
) ||
556 gcry_sexp_build( &sig_sexp
, &erroff
, sig_sexp_s
, r
, s
) )
559 int i_hash_len
= gcry_md_get_algo_dlen (sign
->digest_algo
);
560 if (i_hash_len
> i_q_len
)
561 i_hash_len
= i_q_len
;
562 if( gcry_mpi_scan( &hash
, GCRYMPI_FMT_USG
, p_hash
, i_hash_len
, NULL
) ||
563 gcry_sexp_build( &hash_sexp
, &erroff
, hash_sexp_s
, hash
) )
566 if( gcry_pk_verify( sig_sexp
, hash_sexp
, key_sexp
) )
572 if( p
) gcry_mpi_release( p
);
573 if( q
) gcry_mpi_release( q
);
574 if( g
) gcry_mpi_release( g
);
575 if( y
) gcry_mpi_release( y
);
576 if( r
) gcry_mpi_release( r
);
577 if( s
) gcry_mpi_release( s
);
578 if( hash
) gcry_mpi_release( hash
);
579 if( key_sexp
) gcry_sexp_release( key_sexp
);
580 if( sig_sexp
) gcry_sexp_release( sig_sexp
);
581 if( hash_sexp
) gcry_sexp_release( hash_sexp
);
587 * Verify an OpenPGP signature made with some public key
589 int verify_signature( signature_packet_t
*sign
, public_key_packet_t
*p_key
,
592 if (sign
->public_key_algo
== GCRY_PK_DSA
)
593 return verify_signature_dsa(sign
, p_key
, p_hash
);
594 else if (sign
->public_key_algo
== GCRY_PK_RSA
)
595 return verify_signature_rsa(sign
, p_key
, p_hash
);
602 * fill a public_key_t with public key data, including:
603 * * public key packet
604 * * signature packet issued by key which long id is p_sig_issuer
607 int parse_public_key( const uint8_t *p_key_data
, size_t i_key_len
,
608 public_key_t
*p_key
, const uint8_t *p_sig_issuer
)
610 const uint8_t *pos
= p_key_data
;
611 const uint8_t *max_pos
= pos
+ i_key_len
;
614 #define PUBLIC_KEY_FOUND 0x01
615 #define USER_ID_FOUND 0x02
616 #define SIGNATURE_FOUND 0X04
618 uint8_t *p_key_unarmored
= NULL
;
620 p_key
->psz_username
= NULL
;
621 p_key
->sig
.specific
.v4
.hashed_data
= NULL
;
622 p_key
->sig
.specific
.v4
.unhashed_data
= NULL
;
624 if( !( *pos
& 0x80 ) )
625 { /* first byte is ASCII, unarmoring */
626 p_key_unarmored
= (uint8_t*)malloc( i_key_len
);
627 if( !p_key_unarmored
)
629 int i_len
= pgp_unarmor( (char*)p_key_data
, i_key_len
,
630 p_key_unarmored
, i_key_len
);
635 pos
= p_key_unarmored
;
636 max_pos
= pos
+ i_len
;
639 while( pos
< max_pos
)
641 if( !(*pos
& 0x80) || *pos
& 0x40 )
644 int i_type
= packet_type( *pos
);
646 int i_header_len
= packet_header_len( *pos
++ );
647 if( pos
+ i_header_len
> max_pos
||
648 ( i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4 ) )
651 int i_packet_len
= scalar_number( pos
, i_header_len
);
654 if( pos
+ i_packet_len
> max_pos
)
659 case PUBLIC_KEY_PACKET
:
660 i_status
|= PUBLIC_KEY_FOUND
;
661 if( parse_public_key_packet( &p_key
->key
, pos
, i_packet_len
) != VLC_SUCCESS
)
665 case SIGNATURE_PACKET
: /* we accept only v4 signatures here */
666 if( i_status
& SIGNATURE_FOUND
|| !p_sig_issuer
)
668 int i_ret
= parse_signature_packet( &p_key
->sig
, pos
,
670 if( i_ret
== VLC_SUCCESS
)
672 if( p_key
->sig
.version
!= 4 )
674 if( memcmp( p_key
->sig
.issuer_longid
, p_sig_issuer
, 8 ) )
676 free( p_key
->sig
.specific
.v4
.hashed_data
);
677 free( p_key
->sig
.specific
.v4
.unhashed_data
);
678 p_key
->sig
.specific
.v4
.hashed_data
= NULL
;
679 p_key
->sig
.specific
.v4
.unhashed_data
= NULL
;
682 i_status
|= SIGNATURE_FOUND
;
687 if( p_key
->psz_username
) /* save only the first User ID */
689 i_status
|= USER_ID_FOUND
;
690 p_key
->psz_username
= (uint8_t*)malloc( i_packet_len
+ 1);
691 if( !p_key
->psz_username
)
694 memcpy( p_key
->psz_username
, pos
, i_packet_len
);
695 p_key
->psz_username
[i_packet_len
] = '\0';
703 free( p_key_unarmored
);
705 if( !( i_status
& ( PUBLIC_KEY_FOUND
| USER_ID_FOUND
) ) )
708 if( p_sig_issuer
&& !( i_status
& SIGNATURE_FOUND
) )
714 if( p_key
->sig
.version
== 4 )
716 free( p_key
->sig
.specific
.v4
.hashed_data
);
717 free( p_key
->sig
.specific
.v4
.unhashed_data
);
719 free( p_key
->psz_username
);
720 free( p_key_unarmored
);
725 /* hash a binary file */
726 static int hash_from_binary_file( const char *psz_file
, gcry_md_hd_t hd
)
728 uint8_t buffer
[4096];
731 FILE *f
= vlc_fopen( psz_file
, "r" );
735 while( ( i_read
= fread( buffer
, 1, sizeof(buffer
), f
) ) > 0 )
736 gcry_md_write( hd
, buffer
, i_read
);
744 /* final part of the hash */
745 static uint8_t *hash_finish( gcry_md_hd_t hd
, signature_packet_t
*p_sig
)
747 if( p_sig
->version
== 3 )
749 gcry_md_putc( hd
, p_sig
->type
);
750 gcry_md_write( hd
, &p_sig
->specific
.v3
.timestamp
, 4 );
752 else if( p_sig
->version
== 4 )
754 gcry_md_putc( hd
, p_sig
->version
);
755 gcry_md_putc( hd
, p_sig
->type
);
756 gcry_md_putc( hd
, p_sig
->public_key_algo
);
757 gcry_md_putc( hd
, p_sig
->digest_algo
);
758 gcry_md_write( hd
, p_sig
->specific
.v4
.hashed_data_len
, 2 );
759 size_t i_len
= scalar_number( p_sig
->specific
.v4
.hashed_data_len
, 2 );
760 gcry_md_write( hd
, p_sig
->specific
.v4
.hashed_data
, i_len
);
762 gcry_md_putc( hd
, 0x04 );
763 gcry_md_putc( hd
, 0xFF );
765 i_len
+= 6; /* hashed data + 6 bytes header */
767 gcry_md_putc( hd
, (i_len
>> 24) & 0xff );
768 gcry_md_putc( hd
, (i_len
>> 16) & 0xff );
769 gcry_md_putc( hd
, (i_len
>> 8) & 0xff );
770 gcry_md_putc( hd
, (i_len
) & 0xff );
773 { /* RFC 4880 only tells about versions 3 and 4 */
779 uint8_t *p_tmp
= (uint8_t*) gcry_md_read( hd
, p_sig
->digest_algo
) ;
780 unsigned int hash_len
= gcry_md_get_algo_dlen (p_sig
->digest_algo
);
781 uint8_t *p_hash
= malloc(hash_len
);
783 memcpy(p_hash
, p_tmp
, hash_len
);
790 * return a hash of a text
792 uint8_t *hash_from_text( const char *psz_string
,
793 signature_packet_t
*p_sig
)
796 if( gcry_md_open( &hd
, p_sig
->digest_algo
, 0 ) )
799 if( p_sig
->type
== TEXT_SIGNATURE
)
802 size_t i_len
= strcspn( psz_string
, "\r\n" );
806 gcry_md_write( hd
, psz_string
, i_len
);
809 gcry_md_putc( hd
, '\r' );
810 gcry_md_putc( hd
, '\n' );
812 if( *psz_string
== '\r' )
814 if( *psz_string
== '\n' )
818 gcry_md_write( hd
, psz_string
, strlen( psz_string
) );
820 return hash_finish( hd
, p_sig
);
825 * return a hash of a file
827 uint8_t *hash_from_file( const char *psz_file
, signature_packet_t
*p_sig
)
830 if( gcry_md_open( &hd
, p_sig
->digest_algo
, 0 ) )
833 if( hash_from_binary_file( psz_file
, hd
) < 0 )
839 return hash_finish( hd
, p_sig
);
844 * Generate a hash on a public key, to verify a signature made on that hash
845 * Note that we need the signature (v4) to compute the hash
847 uint8_t *hash_from_public_key( public_key_t
*p_pkey
)
849 const uint8_t pk_algo
= p_pkey
->key
.algo
;
851 size_t i_p_len
, i_g_len
, i_q_len
, i_y_len
;
852 size_t i_n_len
, i_e_len
;
854 if( p_pkey
->sig
.version
!= 4 )
857 if( p_pkey
->sig
.type
< GENERIC_KEY_SIGNATURE
||
858 p_pkey
->sig
.type
> POSITIVE_KEY_SIGNATURE
)
861 gcry_error_t error
= 0;
864 if (pk_algo
== GCRY_PK_DSA
) {
865 i_p_len
= mpi_len( p_pkey
->key
.sig
.dsa
.p
);
866 i_g_len
= mpi_len( p_pkey
->key
.sig
.dsa
.g
);
867 i_q_len
= mpi_len( p_pkey
->key
.sig
.dsa
.q
);
868 i_y_len
= mpi_len( p_pkey
->key
.sig
.dsa
.y
);
870 i_size
= 6 + 2*4 + i_p_len
+ i_g_len
+ i_q_len
+ i_y_len
;
871 } else if (pk_algo
== GCRY_PK_RSA
) {
872 i_n_len
= mpi_len( p_pkey
->key
.sig
.rsa
.n
);
873 i_e_len
= mpi_len( p_pkey
->key
.sig
.rsa
.e
);
875 i_size
= 6 + 2*2 + i_n_len
+ i_e_len
;
879 error
= gcry_md_open( &hd
, p_pkey
->sig
.digest_algo
, 0 );
883 gcry_md_putc( hd
, 0x99 );
885 gcry_md_putc( hd
, (i_size
>> 8) & 0xff );
886 gcry_md_putc( hd
, i_size
& 0xff );
888 gcry_md_putc( hd
, p_pkey
->key
.version
);
889 gcry_md_write( hd
, p_pkey
->key
.timestamp
, 4 );
890 gcry_md_putc( hd
, p_pkey
->key
.algo
);
892 if (pk_algo
== GCRY_PK_DSA
) {
893 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.sig
.dsa
.p
, 2 + i_p_len
);
894 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.sig
.dsa
.q
, 2 + i_q_len
);
895 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.sig
.dsa
.g
, 2 + i_g_len
);
896 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.sig
.dsa
.y
, 2 + i_y_len
);
897 } else if (pk_algo
== GCRY_PK_RSA
) {
898 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.sig
.rsa
.n
, 2 + i_n_len
);
899 gcry_md_write( hd
, (uint8_t*)&p_pkey
->key
.sig
.rsa
.e
, 2 + i_e_len
);
902 gcry_md_putc( hd
, 0xb4 );
904 size_t i_len
= strlen((char*)p_pkey
->psz_username
);
906 gcry_md_putc( hd
, (i_len
>> 24) & 0xff );
907 gcry_md_putc( hd
, (i_len
>> 16) & 0xff );
908 gcry_md_putc( hd
, (i_len
>> 8) & 0xff );
909 gcry_md_putc( hd
, (i_len
) & 0xff );
911 gcry_md_write( hd
, p_pkey
->psz_username
, i_len
);
913 uint8_t *p_hash
= hash_finish( hd
, &p_pkey
->sig
);
915 p_hash
[0] != p_pkey
->sig
.hash_verification
[0] ||
916 p_hash
[1] != p_pkey
->sig
.hash_verification
[1] )
927 * download a public key (the last one) from videolan server, and parse it
929 public_key_t
*download_key( vlc_object_t
*p_this
,
930 const uint8_t *p_longid
, const uint8_t *p_signature_issuer
)
933 if( asprintf( &psz_url
, "http://download.videolan.org/pub/keys/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X.asc",
934 p_longid
[0], p_longid
[1], p_longid
[2], p_longid
[3],
935 p_longid
[4], p_longid
[5], p_longid
[6], p_longid
[7] ) == -1 )
938 stream_t
*p_stream
= vlc_stream_NewURL( p_this
, psz_url
);
944 if( vlc_stream_GetSize( p_stream
, &i_size
) || i_size
> INT_MAX
)
946 vlc_stream_Delete( p_stream
);
950 uint8_t *p_buf
= (uint8_t*)malloc( i_size
);
953 vlc_stream_Delete( p_stream
);
957 int i_read
= vlc_stream_Read( p_stream
, p_buf
, (int)i_size
);
958 vlc_stream_Delete( p_stream
);
960 if( i_read
!= (int)i_size
)
962 msg_Dbg( p_this
, "Couldn't read full GPG key" );
967 public_key_t
*p_pkey
= (public_key_t
*) malloc( sizeof( public_key_t
) );
974 memcpy( p_pkey
->longid
, p_longid
, 8 );
976 int i_error
= parse_public_key( p_buf
, i_read
, p_pkey
, p_signature_issuer
);
979 if( i_error
!= VLC_SUCCESS
)
981 msg_Dbg( p_this
, "Couldn't parse GPG key" );
991 * Download the signature associated to a document or a binary file.
992 * We're given the file's url, we just append ".asc" to it and download
994 int download_signature( vlc_object_t
*p_this
, signature_packet_t
*p_sig
,
995 const char *psz_url
)
997 char *psz_sig
= (char*) malloc( strlen( psz_url
) + 4 + 1 ); /* ".asc" + \0 */
1001 strcpy( psz_sig
, psz_url
);
1002 strcat( psz_sig
, ".asc" );
1004 stream_t
*p_stream
= vlc_stream_NewURL( p_this
, psz_sig
);
1011 if( vlc_stream_GetSize( p_stream
, &i_size
) || i_size
> INT_MAX
)
1013 vlc_stream_Delete( p_stream
);
1014 return VLC_EGENERIC
;
1017 msg_Dbg( p_this
, "Downloading signature (%"PRIu64
" bytes)", i_size
);
1018 uint8_t *p_buf
= (uint8_t*)malloc( i_size
);
1021 vlc_stream_Delete( p_stream
);
1025 int i_read
= vlc_stream_Read( p_stream
, p_buf
, (int)i_size
);
1027 vlc_stream_Delete( p_stream
);
1029 if( i_read
!= (int)i_size
)
1032 "Couldn't download full signature (only %d bytes)", i_read
);
1034 return VLC_EGENERIC
;
1037 if( (uint8_t)*p_buf
< 0x80 ) /* ASCII */
1039 msg_Dbg( p_this
, "Unarmoring signature" );
1041 uint8_t* p_unarmored
= (uint8_t*) malloc( ( i_size
* 3 ) / 4 + 1 );
1045 return VLC_EGENERIC
;
1048 int i_bytes
= pgp_unarmor( (char*)p_buf
, i_size
, p_unarmored
, i_size
);
1051 p_buf
= p_unarmored
;
1057 msg_Dbg( p_this
, "Unarmoring failed : corrupted signature ?" );
1058 return VLC_EGENERIC
;
1062 if( packet_type( *p_buf
) != SIGNATURE_PACKET
)
1064 msg_Dbg( p_this
, "Not a signature: %d", *p_buf
);
1066 return VLC_EGENERIC
;
1069 size_t i_header_len
= packet_header_len( *p_buf
);
1070 if( ( i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4 ) ||
1071 i_header_len
+ 1 > (size_t)i_size
)
1074 msg_Dbg( p_this
, "Invalid signature packet header" );
1075 return VLC_EGENERIC
;
1078 size_t i_len
= scalar_number( p_buf
+1, i_header_len
);
1079 if( i_len
+ i_header_len
+ 1 != (size_t)i_size
)
1082 msg_Dbg( p_this
, "Invalid signature packet" );
1083 return VLC_EGENERIC
;
1086 int i_ret
= parse_signature_packet( p_sig
, p_buf
+1+i_header_len
, i_len
);
1088 if( i_ret
!= VLC_SUCCESS
)
1090 msg_Dbg( p_this
, "Couldn't parse signature" );
1094 if( p_sig
->type
!= BINARY_SIGNATURE
&& p_sig
->type
!= TEXT_SIGNATURE
)
1096 msg_Dbg( p_this
, "Invalid signature type: %d", p_sig
->type
);
1097 if( p_sig
->version
== 4 )
1099 free( p_sig
->specific
.v4
.hashed_data
);
1100 free( p_sig
->specific
.v4
.unhashed_data
);
1102 return VLC_EGENERIC
;