1 /*****************************************************************************
2  * update_crypto.c: OpenPGP related functions used for updating
3  *****************************************************************************
4  * Copyright © 2008-2009 VLC authors and VideoLAN
5  * $Id: 09479468c00337ddadd44f27e6cbee6428a28ed5 $
6  *
7  * Authors: Rafaël Carré <funman@videolanorg>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23 
24 /**
25  *   \file
26  *   This file contains functions related to OpenPGP in VLC update management
27  */
28 
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32 
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36 
37 #include <gcrypt.h>
38 #include <assert.h>
39 #include <limits.h>
40 
41 #include "vlc_common.h"
42 #include <vlc_stream.h>
43 #include <vlc_strings.h>
44 #include <vlc_fs.h>
45 
46 #include "update.h"
47 
48 
49 /*****************************************************************************
50  * OpenPGP functions
51  *****************************************************************************/
52 
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 */
55 
56 
scalar_number(const uint8_t * p,int header_len)57 static inline uint32_t scalar_number( const uint8_t *p, int header_len )
58 {
59     assert( header_len == 1 || header_len == 2 || header_len == 4 );
60 
61     if( header_len == 1 )
62         return( p[0] );
63     else if( header_len == 2 )
64         return( (p[0] << 8) + p[1] );
65     else if( header_len == 4 )
66         return( ((uint32_t)p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3] );
67     else
68         abort();
69 }
70 
71 
72 /* number of data bytes in a MPI */
mpi_len(const uint8_t * mpi)73 static uint32_t mpi_len(const uint8_t *mpi)
74 {
75     return (scalar_number(mpi, 2) + 7) / 8;
76 }
77 
read_mpi(uint8_t * dst,const uint8_t * buf,size_t buflen,size_t bits)78 static size_t read_mpi(uint8_t *dst, const uint8_t *buf, size_t buflen, size_t bits)
79 {
80     if (buflen < 2)
81         return 0;
82 
83     size_t n = mpi_len(buf);
84 
85     if (n * 8 > bits)
86         return 0;
87 
88     n += 2;
89 
90     if (buflen < n)
91         return 0;
92 
93     memcpy(dst, buf, n);
94     return n;
95 }
96 
97 #define READ_MPI(d, bits) do { \
98     size_t n = read_mpi(d, p_buf, i_packet_len - i_read, bits); \
99     if (!n) goto error; \
100     p_buf += n; \
101     i_read += n; \
102 } while(0)
103 
104 /*
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
107  */
parse_public_key_packet(public_key_packet_t * p_key,const uint8_t * p_buf,size_t i_packet_len)108 static int parse_public_key_packet( public_key_packet_t *p_key,
109                                     const uint8_t *p_buf, size_t i_packet_len )
110 {
111     if( i_packet_len < 6 )
112         return VLC_EGENERIC;
113 
114     size_t i_read = 0;
115 
116     p_key->version   = *p_buf++; i_read++;
117     if( p_key->version != 4 )
118         return VLC_EGENERIC;
119 
120     /* XXX: warn when timestamp is > date ? */
121     memcpy( p_key->timestamp, p_buf, 4 ); p_buf += 4; i_read += 4;
122 
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);
132     } else
133         return VLC_EGENERIC;
134 
135     if( i_read == i_packet_len )
136         return VLC_SUCCESS;
137 
138     /* some extra data eh ? */
139 
140 error:
141     return VLC_EGENERIC;
142 }
143 
144 
parse_signature_v3_packet(signature_packet_t * p_sig,const uint8_t * p_buf,size_t i_sig_len)145 static size_t parse_signature_v3_packet( signature_packet_t *p_sig,
146                                       const uint8_t *p_buf, size_t i_sig_len )
147 {
148     size_t i_read = 1; /* we already read the version byte */
149 
150     if( i_sig_len < 19 ) /* signature is at least 19 bytes + the 2 MPIs */
151         return 0;
152 
153     p_sig->specific.v3.hashed_data_len = *p_buf++; i_read++;
154     if( p_sig->specific.v3.hashed_data_len != 5 )
155         return 0;
156 
157     p_sig->type = *p_buf++; i_read++;
158 
159     memcpy( p_sig->specific.v3.timestamp, p_buf, 4 );
160     p_buf += 4; i_read += 4;
161 
162     memcpy( p_sig->issuer_longid, p_buf, 8 );
163     p_buf += 8; i_read += 8;
164 
165     p_sig->public_key_algo = *p_buf++; i_read++;
166 
167     p_sig->digest_algo = *p_buf++; i_read++;
168 
169     p_sig->hash_verification[0] = *p_buf++; i_read++;
170     p_sig->hash_verification[1] = *p_buf++; i_read++;
171 
172     assert( i_read == 19 );
173 
174     return i_read;
175 }
176 
177 
178 /*
179  * fill a signature_packet_v4_t from signature packet data
180  * verify that it was used with a DSA or RSA public key
181  */
parse_signature_v4_packet(signature_packet_t * p_sig,const uint8_t * p_buf,size_t i_sig_len)182 static size_t parse_signature_v4_packet( signature_packet_t *p_sig,
183                                       const uint8_t *p_buf, size_t i_sig_len )
184 {
185     size_t i_read = 1; /* we already read the version byte */
186 
187     if( i_sig_len < 10 ) /* signature is at least 10 bytes + the 2 MPIs */
188         return 0;
189 
190     p_sig->type = *p_buf++; i_read++;
191 
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 )
194             return 0;
195 
196     p_sig->digest_algo = *p_buf++; i_read++;
197 
198     memcpy( p_sig->specific.v4.hashed_data_len, p_buf, 2 );
199     p_buf += 2; i_read += 2;
200 
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 )
205         return 0;
206 
207     p_sig->specific.v4.hashed_data = (uint8_t*) malloc( i_hashed_data_len );
208     if( !p_sig->specific.v4.hashed_data )
209         return 0;
210     memcpy( p_sig->specific.v4.hashed_data, p_buf, i_hashed_data_len );
211     p_buf += i_hashed_data_len;
212 
213     memcpy( p_sig->specific.v4.unhashed_data_len, p_buf, 2 );
214     p_buf += 2; i_read += 2;
215 
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 )
220         return 0;
221 
222     p_sig->specific.v4.unhashed_data = (uint8_t*) malloc( i_unhashed_data_len );
223     if( !p_sig->specific.v4.unhashed_data )
224         return 0;
225 
226     memcpy( p_sig->specific.v4.unhashed_data, p_buf, i_unhashed_data_len );
227     p_buf += i_unhashed_data_len;
228 
229     memcpy( p_sig->hash_verification, p_buf, 2 );
230     p_buf += 2; i_read += 2;
231 
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 );
235 
236     for( ;; )
237     {
238         if( p > max_pos )
239             return 0;
240 
241         size_t i_subpacket_len;
242         if( *p < 192 )
243         {
244             if( p + 1 > max_pos )
245                 return 0;
246             i_subpacket_len = *p++;
247         }
248         else if( *p < 255 )
249         {
250             if( p + 2 > max_pos )
251                 return 0;
252             i_subpacket_len = (*p++ - 192) << 8;
253             i_subpacket_len += *p++ + 192;
254         }
255         else
256         {
257             if( ++p + 4 > max_pos )
258                 return 0;
259             i_subpacket_len = U32_AT(p);
260             p += 4;
261         }
262 
263         if( *p == ISSUER_SUBPACKET )
264         {
265             if( p + 9 > max_pos )
266                 return 0;
267 
268             memcpy( &p_sig->issuer_longid, p+1, 8 );
269 
270             return i_read;
271         }
272 
273         p += i_subpacket_len;
274     }
275 }
276 
277 
parse_signature_packet(signature_packet_t * p_sig,const uint8_t * p_buf,size_t i_packet_len)278 static int parse_signature_packet( signature_packet_t *p_sig,
279                                    const uint8_t *p_buf, size_t i_packet_len )
280 {
281     if( !i_packet_len ) /* 1st sanity check, we need at least the version */
282         return VLC_EGENERIC;
283 
284     p_sig->version = *p_buf++;
285 
286     size_t i_read;
287     switch( p_sig->version )
288     {
289         case 3:
290             i_read = parse_signature_v3_packet( p_sig, p_buf, i_packet_len );
291             break;
292         case 4:
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 );
296             break;
297         default:
298             return VLC_EGENERIC;
299     }
300 
301     if( i_read == 0 ) /* signature packet parsing has failed */
302         goto error;
303 
304     if( p_sig->public_key_algo != GCRY_PK_DSA && p_sig->public_key_algo != GCRY_PK_RSA )
305         goto error;
306 
307     switch( p_sig->type )
308     {
309         case BINARY_SIGNATURE:
310         case TEXT_SIGNATURE:
311         case GENERIC_KEY_SIGNATURE:
312         case PERSONA_KEY_SIGNATURE:
313         case CASUAL_KEY_SIGNATURE:
314         case POSITIVE_KEY_SIGNATURE:
315             break;
316         default:
317             goto error;
318     }
319 
320     p_buf--; /* rewind to the version byte */
321     p_buf += i_read;
322 
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);
328     } else
329         goto error;
330 
331     assert( i_read == i_packet_len );
332     if( i_read < i_packet_len ) /* some extra data, hm ? */
333         goto error;
334 
335     return VLC_SUCCESS;
336 
337 error:
338 
339     if( p_sig->version == 4 )
340     {
341         free( p_sig->specific.v4.hashed_data );
342         free( p_sig->specific.v4.unhashed_data );
343     }
344 
345     return VLC_EGENERIC;
346 }
347 
348 
349 /*
350  * crc_octets() was lamely copied from rfc 2440
351  * Copyright (C) The Internet Society (1998).  All Rights Reserved.
352  */
353 #define CRC24_INIT 0xB704CEL
354 #define CRC24_POLY 0x1864CFBL
355 
crc_octets(uint8_t * octets,size_t len)356 static long crc_octets( uint8_t *octets, size_t len )
357 {
358     long crc = CRC24_INIT;
359     int i;
360     while (len--)
361     {
362         crc ^= (*octets++) << 16;
363         for (i = 0; i < 8; i++)
364         {
365             crc <<= 1;
366             if (crc & 0x1000000)
367                 crc ^= CRC24_POLY;
368         }
369     }
370     return crc & 0xFFFFFFL;
371 }
372 
373 
374 /*
375  * Transform an armored document in binary format
376  * Used on public keys and signatures
377  */
pgp_unarmor(const char * p_ibuf,size_t i_ibuf_len,uint8_t * p_obuf,size_t i_obuf_len)378 static int pgp_unarmor( const char *p_ibuf, size_t i_ibuf_len,
379                         uint8_t *p_obuf, size_t i_obuf_len )
380 {
381     const char *p_ipos = p_ibuf;
382     uint8_t *p_opos = p_obuf;
383     int i_end = 0;
384     int i_header_skipped = 0;
385 
386     while( !i_end && p_ipos < p_ibuf + i_ibuf_len && *p_ipos != '=' )
387     {
388         if( *p_ipos == '\r' || *p_ipos == '\n' )
389         {
390             p_ipos++;
391             continue;
392         }
393 
394         size_t i_line_len = strcspn( p_ipos, "\r\n" );
395         if( i_line_len == 0 )
396             continue;
397 
398         if( !i_header_skipped )
399         {
400             if( !strncmp( p_ipos, "-----BEGIN PGP", 14 ) )
401                 i_header_skipped = 1;
402 
403             p_ipos += i_line_len + 1;
404             continue;
405         }
406 
407         if( !strncmp( p_ipos, "Version:", 8 ) )
408         {
409             p_ipos += i_line_len + 1;
410             continue;
411         }
412 
413         if( p_ipos[i_line_len - 1] == '=' )
414         {
415             i_end = 1;
416         }
417 
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;
421     }
422 
423     /* XXX: the CRC is OPTIONAL, really require it ? */
424     if( p_ipos + 5 > p_ibuf + i_ibuf_len || *p_ipos++ != '=' )
425         return 0;
426 
427     uint8_t p_crc[3];
428     if( vlc_b64_decode_binary_to_buffer( p_crc, 3, p_ipos ) != 3 )
429         return 0;
430 
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];
433 
434     return l_crc2 == l_crc ? p_opos - p_obuf : 0;
435 }
436 
rsa_pkcs1_encode_sig(gcry_mpi_t * r_result,size_t size,const uint8_t * hash,int algo)437 static int rsa_pkcs1_encode_sig(gcry_mpi_t *r_result, size_t size,
438                                 const uint8_t *hash, int algo)
439 {
440     uint8_t asn[100];
441     uint8_t frame[4096/8];
442 
443     size_t asnlen = sizeof(asn);
444     size_t hashlen = gcry_md_get_algo_dlen(algo);
445 
446     if (gcry_md_algo_info(algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
447         return VLC_EGENERIC;
448 
449     if (!hashlen || hashlen + asnlen + 4 > size)
450         return VLC_EGENERIC;
451 
452     frame[0] = 0;
453     frame[1] = 1; /* block type */
454     int pad = size - hashlen - asnlen - 3 ;
455     memset (&frame[2], 0xff, pad );
456     frame[2+pad] = 0;
457     memcpy(&frame[3+pad], asn, asnlen);
458     memcpy(&frame[3+pad+asnlen], hash, hashlen);
459 
460     if (gcry_mpi_scan(r_result, GCRYMPI_FMT_USG, frame, size, &size))
461         return VLC_EGENERIC;
462     return VLC_SUCCESS;
463 }
464 
465 /*
466  * Verify an OpenPGP signature made with some RSA public key
467  */
verify_signature_rsa(signature_packet_t * sign,public_key_packet_t * p_key,uint8_t * p_hash)468 static int verify_signature_rsa( signature_packet_t *sign, public_key_packet_t *p_key,
469                       uint8_t *p_hash )
470 {
471     int ret = VLC_EGENERIC;
472     /* the data to be verified (a hash) */
473     const char *hash_sexp_s = "(data(flags raw)(value %m))";
474     /* the public key */
475     const char *key_sexp_s = "(public-key(rsa(n %m)(e %m)))";
476     /* the signature */
477     const char *sig_sexp_s = "(sig-val(rsa(s%m)))";
478 
479     size_t erroff;
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;
484 
485     size_t i_e_len = mpi_len( p_key->sig.rsa.e );
486     size_t i_n_len = mpi_len( p_key->sig.rsa.n );
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 ) )
490         goto out;
491 
492     uint8_t *p_s = sign->algo_specific.rsa.s;
493     size_t 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 ) )
496         goto out;
497 
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 ) )
500         goto out;
501 
502     if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) )
503         goto out;
504 
505     ret = VLC_SUCCESS;
506 
507 out:
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 );
515     return ret;
516 }
517 
518 /*
519  * Verify an OpenPGP signature made with some DSA public key
520  */
verify_signature_dsa(signature_packet_t * sign,public_key_packet_t * p_key,uint8_t * p_hash)521 static int verify_signature_dsa( signature_packet_t *sign, public_key_packet_t *p_key,
522                       uint8_t *p_hash )
523 {
524     int ret = VLC_EGENERIC;
525 
526     /* the data to be verified (a hash) */
527     const char *hash_sexp_s = "(data(flags raw)(value %m))";
528     /* the public key */
529     const char *key_sexp_s = "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
530     /* the signature */
531     const char *sig_sexp_s = "(sig-val(dsa(r %m )(s %m )))";
532 
533     size_t erroff;
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;
538 
539     size_t i_p_len = mpi_len( p_key->sig.dsa.p );
540     size_t i_q_len = mpi_len( p_key->sig.dsa.q );
541     size_t i_g_len = mpi_len( p_key->sig.dsa.g );
542     size_t 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 ) )
548         goto out;
549 
550     uint8_t *p_r = sign->algo_specific.dsa.r;
551     uint8_t *p_s = sign->algo_specific.dsa.s;
552     size_t i_r_len = mpi_len( p_r );
553     size_t 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 ) )
557         goto out;
558 
559     unsigned 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 ) )
564         goto out;
565 
566     if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) )
567         goto out;
568 
569     ret = VLC_SUCCESS;
570 
571 out:
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 );
582 
583     return ret;
584 }
585 
586 /*
587  * Verify an OpenPGP signature made with some public key
588  */
verify_signature(signature_packet_t * sign,public_key_packet_t * p_key,uint8_t * p_hash)589 int verify_signature( signature_packet_t *sign, public_key_packet_t *p_key,
590                       uint8_t *p_hash )
591 {
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);
596     else
597         return VLC_EGENERIC;
598 }
599 
600 
601 /*
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
605  *   * user id packet
606  */
parse_public_key(const uint8_t * p_key_data,size_t i_key_len,public_key_t * p_key,const uint8_t * 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 )
609 {
610     const uint8_t *pos = p_key_data;
611     const uint8_t *max_pos = pos + i_key_len;
612 
613     int i_status = 0;
614 #define PUBLIC_KEY_FOUND    0x01
615 #define USER_ID_FOUND       0x02
616 #define SIGNATURE_FOUND     0X04
617 
618     uint8_t *p_key_unarmored = NULL;
619 
620     p_key->psz_username = NULL;
621     p_key->sig.specific.v4.hashed_data = NULL;
622     p_key->sig.specific.v4.unhashed_data = NULL;
623 
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 )
628             return VLC_ENOMEM;
629         int i_len = pgp_unarmor( (char*)p_key_data, i_key_len,
630                                  p_key_unarmored, i_key_len );
631 
632         if( i_len == 0 )
633             goto error;
634 
635         pos = p_key_unarmored;
636         max_pos = pos + i_len;
637     }
638 
639     while( pos < max_pos )
640     {
641         if( !(*pos & 0x80) || *pos & 0x40 )
642             goto error;
643 
644         int i_type = packet_type( *pos );
645 
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 ) )
649             goto error;
650 
651         size_t i_packet_len = scalar_number( pos, i_header_len );
652         pos += i_header_len;
653 
654         if( pos + i_packet_len > max_pos )
655             goto error;
656 
657         switch( i_type )
658         {
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 )
662                     goto error;
663                 break;
664 
665             case SIGNATURE_PACKET: /* we accept only v4 signatures here */
666                 if( i_status & SIGNATURE_FOUND || !p_sig_issuer )
667                     break;
668                 int i_ret = parse_signature_packet( &p_key->sig, pos,
669                                                     i_packet_len );
670                 if( i_ret == VLC_SUCCESS )
671                 {
672                     if( p_key->sig.version != 4 )
673                         break;
674                     if( memcmp( p_key->sig.issuer_longid, p_sig_issuer, 8 ) )
675                     {
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;
680                         break;
681                     }
682                     i_status |= SIGNATURE_FOUND;
683                 }
684                 break;
685 
686             case USER_ID_PACKET:
687                 if( p_key->psz_username ) /* save only the first User ID */
688                     break;
689                 i_status |= USER_ID_FOUND;
690                 p_key->psz_username = (uint8_t*)malloc( i_packet_len + 1);
691                 if( !p_key->psz_username )
692                     goto error;
693 
694                 memcpy( p_key->psz_username, pos, i_packet_len );
695                 p_key->psz_username[i_packet_len] = '\0';
696                 break;
697 
698             default:
699                 break;
700         }
701         pos += i_packet_len;
702     }
703     free( p_key_unarmored );
704 
705     if( !( i_status & ( PUBLIC_KEY_FOUND | USER_ID_FOUND ) ) )
706         return VLC_EGENERIC;
707 
708     if( p_sig_issuer && !( i_status & SIGNATURE_FOUND ) )
709         return VLC_EGENERIC;
710 
711     return VLC_SUCCESS;
712 
713 error:
714     if( p_key->sig.version == 4 )
715     {
716         free( p_key->sig.specific.v4.hashed_data );
717         free( p_key->sig.specific.v4.unhashed_data );
718     }
719     free( p_key->psz_username );
720     free( p_key_unarmored );
721     return VLC_EGENERIC;
722 }
723 
724 
725 /* hash a binary file */
hash_from_binary_file(const char * psz_file,gcry_md_hd_t hd)726 static int hash_from_binary_file( const char *psz_file, gcry_md_hd_t hd )
727 {
728     uint8_t buffer[4096];
729     size_t i_read;
730 
731     FILE *f = vlc_fopen( psz_file, "r" );
732     if( !f )
733         return -1;
734 
735     while( ( i_read = fread( buffer, 1, sizeof(buffer), f ) ) > 0 )
736         gcry_md_write( hd, buffer, i_read );
737 
738     fclose( f );
739 
740     return 0;
741 }
742 
743 
744 /* final part of the hash */
hash_finish(gcry_md_hd_t hd,signature_packet_t * p_sig)745 static uint8_t *hash_finish( gcry_md_hd_t hd, signature_packet_t *p_sig )
746 {
747     if( p_sig->version == 3 )
748     {
749         gcry_md_putc( hd, p_sig->type );
750         gcry_md_write( hd, &p_sig->specific.v3.timestamp, 4 );
751     }
752     else if( p_sig->version == 4 )
753     {
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 );
761 
762         gcry_md_putc( hd, 0x04 );
763         gcry_md_putc( hd, 0xFF );
764 
765         i_len += 6; /* hashed data + 6 bytes header */
766 
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 );
771     }
772     else
773     {   /* RFC 4880 only tells about versions 3 and 4 */
774         return NULL;
775     }
776 
777     gcry_md_final( hd );
778 
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);
782     if( p_hash )
783         memcpy(p_hash, p_tmp, hash_len);
784     gcry_md_close( hd );
785     return p_hash;
786 }
787 
788 
789 /*
790  * return a hash of a text
791  */
hash_from_text(const char * psz_string,signature_packet_t * p_sig)792 uint8_t *hash_from_text( const char *psz_string,
793         signature_packet_t *p_sig )
794 {
795     gcry_md_hd_t hd;
796     if( gcry_md_open( &hd, p_sig->digest_algo, 0 ) )
797         return NULL;
798 
799     if( p_sig->type == TEXT_SIGNATURE )
800     while( *psz_string )
801     {
802         size_t i_len = strcspn( psz_string, "\r\n" );
803 
804         if( i_len )
805         {
806             gcry_md_write( hd, psz_string, i_len );
807             psz_string += i_len;
808         }
809         gcry_md_putc( hd, '\r' );
810         gcry_md_putc( hd, '\n' );
811 
812         if( *psz_string == '\r' )
813             psz_string++;
814         if( *psz_string == '\n' )
815             psz_string++;
816     }
817     else
818         gcry_md_write( hd, psz_string, strlen( psz_string ) );
819 
820     return hash_finish( hd, p_sig );
821 }
822 
823 
824 /*
825  * return a hash of a file
826  */
hash_from_file(const char * psz_file,signature_packet_t * p_sig)827 uint8_t *hash_from_file( const char *psz_file, signature_packet_t *p_sig )
828 {
829     gcry_md_hd_t hd;
830     if( gcry_md_open( &hd, p_sig->digest_algo, 0 ) )
831         return NULL;
832 
833     if( hash_from_binary_file( psz_file, hd ) < 0 )
834     {
835         gcry_md_close( hd );
836         return NULL;
837     }
838 
839     return hash_finish( hd, p_sig );
840 }
841 
842 
843 /*
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
846  */
hash_from_public_key(public_key_t * p_pkey)847 uint8_t *hash_from_public_key( public_key_t *p_pkey )
848 {
849     const uint8_t pk_algo = p_pkey->key.algo;
850     size_t i_size;
851     size_t i_p_len, i_g_len, i_q_len, i_y_len;
852     size_t i_n_len, i_e_len;
853 
854     if( p_pkey->sig.version != 4 )
855         return NULL;
856 
857     if( p_pkey->sig.type < GENERIC_KEY_SIGNATURE ||
858         p_pkey->sig.type > POSITIVE_KEY_SIGNATURE )
859         return NULL;
860 
861     if( p_pkey->psz_username == NULL )
862         return NULL;
863 
864     gcry_error_t error = 0;
865     gcry_md_hd_t hd;
866 
867     if (pk_algo == GCRY_PK_DSA) {
868         i_p_len = mpi_len( p_pkey->key.sig.dsa.p );
869         i_g_len = mpi_len( p_pkey->key.sig.dsa.g );
870         i_q_len = mpi_len( p_pkey->key.sig.dsa.q );
871         i_y_len = mpi_len( p_pkey->key.sig.dsa.y );
872 
873         i_size = 6 + 2*4 + i_p_len + i_g_len + i_q_len + i_y_len;
874     } else if (pk_algo == GCRY_PK_RSA) {
875         i_n_len = mpi_len( p_pkey->key.sig.rsa.n );
876         i_e_len = mpi_len( p_pkey->key.sig.rsa.e );
877 
878         i_size = 6 + 2*2 + i_n_len + i_e_len;
879     } else
880         return NULL;
881 
882     error = gcry_md_open( &hd, p_pkey->sig.digest_algo, 0 );
883     if( error )
884         return NULL;
885 
886     gcry_md_putc( hd, 0x99 );
887 
888     gcry_md_putc( hd, (i_size >> 8) & 0xff );
889     gcry_md_putc( hd, i_size & 0xff );
890 
891     gcry_md_putc( hd, p_pkey->key.version );
892     gcry_md_write( hd, p_pkey->key.timestamp, 4 );
893     gcry_md_putc( hd, p_pkey->key.algo );
894 
895     if (pk_algo == GCRY_PK_DSA) {
896         gcry_md_write( hd, (uint8_t*)&p_pkey->key.sig.dsa.p, 2 + i_p_len );
897         gcry_md_write( hd, (uint8_t*)&p_pkey->key.sig.dsa.q, 2 + i_q_len );
898         gcry_md_write( hd, (uint8_t*)&p_pkey->key.sig.dsa.g, 2 + i_g_len );
899         gcry_md_write( hd, (uint8_t*)&p_pkey->key.sig.dsa.y, 2 + i_y_len );
900     } else if (pk_algo == GCRY_PK_RSA) {
901         gcry_md_write( hd, (uint8_t*)&p_pkey->key.sig.rsa.n, 2 + i_n_len );
902         gcry_md_write( hd, (uint8_t*)&p_pkey->key.sig.rsa.e, 2 + i_e_len );
903     }
904 
905     gcry_md_putc( hd, 0xb4 );
906 
907     size_t i_len = strlen((char*)p_pkey->psz_username);
908 
909     gcry_md_putc( hd, (i_len >> 24) & 0xff );
910     gcry_md_putc( hd, (i_len >> 16) & 0xff );
911     gcry_md_putc( hd, (i_len >> 8) & 0xff );
912     gcry_md_putc( hd, (i_len) & 0xff );
913 
914     gcry_md_write( hd, p_pkey->psz_username, i_len );
915 
916     uint8_t *p_hash = hash_finish( hd, &p_pkey->sig );
917     if( !p_hash ||
918         p_hash[0] != p_pkey->sig.hash_verification[0] ||
919         p_hash[1] != p_pkey->sig.hash_verification[1] )
920     {
921         free(p_hash);
922         return NULL;
923     }
924 
925     return p_hash;
926 }
927 
928 
929 /*
930  * download a public key (the last one) from videolan server, and parse it
931  */
download_key(vlc_object_t * p_this,const uint8_t * p_longid,const uint8_t * p_signature_issuer)932 public_key_t *download_key( vlc_object_t *p_this,
933                     const uint8_t *p_longid, const uint8_t *p_signature_issuer )
934 {
935     char *psz_url;
936     if( asprintf( &psz_url, "http://download.videolan.org/pub/keys/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X.asc",
937                     p_longid[0], p_longid[1], p_longid[2], p_longid[3],
938                     p_longid[4], p_longid[5], p_longid[6], p_longid[7] ) == -1 )
939         return NULL;
940 
941     stream_t *p_stream = vlc_stream_NewURL( p_this, psz_url );
942     free( psz_url );
943     if( !p_stream )
944         return NULL;
945 
946     uint64_t i_size;
947     if( vlc_stream_GetSize( p_stream, &i_size ) || i_size > INT_MAX )
948     {
949         vlc_stream_Delete( p_stream );
950         return NULL;
951     }
952 
953     uint8_t *p_buf = (uint8_t*)malloc( i_size );
954     if( !p_buf )
955     {
956         vlc_stream_Delete( p_stream );
957         return NULL;
958     }
959 
960     int i_read = vlc_stream_Read( p_stream, p_buf, (int)i_size );
961     vlc_stream_Delete( p_stream );
962 
963     if( i_read != (int)i_size )
964     {
965         msg_Dbg( p_this, "Couldn't read full GPG key" );
966         free( p_buf );
967         return NULL;
968     }
969 
970     public_key_t *p_pkey = (public_key_t*) malloc( sizeof( public_key_t ) );
971     if( !p_pkey )
972     {
973         free( p_buf );
974         return NULL;
975     }
976 
977     memcpy( p_pkey->longid, p_longid, 8 );
978 
979     int i_error = parse_public_key( p_buf, i_read, p_pkey, p_signature_issuer );
980     free( p_buf );
981 
982     if( i_error != VLC_SUCCESS )
983     {
984         msg_Dbg( p_this, "Couldn't parse GPG key" );
985         free( p_pkey );
986         return NULL;
987     }
988 
989     return p_pkey;
990 }
991 
992 
993 /*
994  * Download the signature associated to a document or a binary file.
995  * We're given the file's url, we just append ".asc" to it and download
996  */
download_signature(vlc_object_t * p_this,signature_packet_t * p_sig,const char * psz_url)997 int download_signature( vlc_object_t *p_this, signature_packet_t *p_sig,
998                         const char *psz_url )
999 {
1000     char *psz_sig = (char*) malloc( strlen( psz_url ) + 4 + 1 ); /* ".asc" + \0 */
1001     if( !psz_sig )
1002         return VLC_ENOMEM;
1003 
1004     strcpy( psz_sig, psz_url );
1005     strcat( psz_sig, ".asc" );
1006 
1007     stream_t *p_stream = vlc_stream_NewURL( p_this, psz_sig );
1008     free( psz_sig );
1009 
1010     if( !p_stream )
1011         return VLC_ENOMEM;
1012 
1013     uint64_t i_size;
1014     if( vlc_stream_GetSize( p_stream, &i_size ) || i_size > INT_MAX )
1015     {
1016         vlc_stream_Delete( p_stream );
1017         return VLC_EGENERIC;
1018     }
1019 
1020     msg_Dbg( p_this, "Downloading signature (%"PRIu64" bytes)", i_size );
1021     uint8_t *p_buf = (uint8_t*)malloc( i_size );
1022     if( !p_buf )
1023     {
1024         vlc_stream_Delete( p_stream );
1025         return VLC_ENOMEM;
1026     }
1027 
1028     int i_read = vlc_stream_Read( p_stream, p_buf, (int)i_size );
1029 
1030     vlc_stream_Delete( p_stream );
1031 
1032     if( i_read != (int)i_size )
1033     {
1034         msg_Dbg( p_this,
1035             "Couldn't download full signature (only %d bytes)", i_read );
1036         free( p_buf );
1037         return VLC_EGENERIC;
1038     }
1039 
1040     if( (uint8_t)*p_buf < 0x80 ) /* ASCII */
1041     {
1042         msg_Dbg( p_this, "Unarmoring signature" );
1043 
1044         uint8_t* p_unarmored = (uint8_t*) malloc( ( i_size * 3 ) / 4 + 1 );
1045         if( !p_unarmored )
1046         {
1047             free( p_buf );
1048             return VLC_EGENERIC;
1049         }
1050 
1051         int i_bytes = pgp_unarmor( (char*)p_buf, i_size, p_unarmored, i_size );
1052         free( p_buf );
1053 
1054         p_buf = p_unarmored;
1055         i_size = i_bytes;
1056 
1057         if( i_bytes < 2 )
1058         {
1059             free( p_buf );
1060             msg_Dbg( p_this, "Unarmoring failed : corrupted signature ?" );
1061             return VLC_EGENERIC;
1062         }
1063     }
1064 
1065     if( packet_type( *p_buf ) != SIGNATURE_PACKET )
1066     {
1067         msg_Dbg( p_this, "Not a signature: %d", *p_buf );
1068         free( p_buf );
1069         return VLC_EGENERIC;
1070     }
1071 
1072     size_t i_header_len = packet_header_len( *p_buf );
1073     if( ( i_header_len != 1 && i_header_len != 2 && i_header_len != 4 ) ||
1074         i_header_len + 1 > (size_t)i_size )
1075     {
1076         free( p_buf );
1077         msg_Dbg( p_this, "Invalid signature packet header" );
1078         return VLC_EGENERIC;
1079     }
1080 
1081     size_t i_len = scalar_number( p_buf+1, i_header_len );
1082     if( i_len + i_header_len + 1 != (size_t)i_size )
1083     {
1084         free( p_buf );
1085         msg_Dbg( p_this, "Invalid signature packet" );
1086         return VLC_EGENERIC;
1087     }
1088 
1089     int i_ret = parse_signature_packet( p_sig, p_buf+1+i_header_len, i_len );
1090     free( p_buf );
1091     if( i_ret != VLC_SUCCESS )
1092     {
1093         msg_Dbg( p_this, "Couldn't parse signature" );
1094         return i_ret;
1095     }
1096 
1097     if( p_sig->type != BINARY_SIGNATURE && p_sig->type != TEXT_SIGNATURE )
1098     {
1099         msg_Dbg( p_this, "Invalid signature type: %d", p_sig->type );
1100         if( p_sig->version == 4 )
1101         {
1102             free( p_sig->specific.v4.hashed_data );
1103             free( p_sig->specific.v4.unhashed_data );
1104         }
1105         return VLC_EGENERIC;
1106     }
1107 
1108     return VLC_SUCCESS;
1109 }
1110