1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-2014 Sven Strickroth <email@cs-ware.de>
4 // Copyright (C) 2014 TortoiseGit
5 // Copyright (C) VLC project (http://videolan.org)
6 // - pgp parsing code was copied from src/misc/update(_crypto)?.c
7 // Copyright (C) The Internet Society (1998). All Rights Reserved.
8 // - crc_octets() was lamely copied from rfc 2440
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License
12 // as published by the Free Software Foundation; either version 2
13 // of the License, or (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software Foundation,
22 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "UpdateCrypto.h"
26 #include "FormatMessageWrapper.h"
28 #define NEED_SIGNING_KEY
29 #include "..\version.h"
32 #define packet_type(c) ((c & 0x3c) >> 2) /* 0x3C = 00111100 */
33 #define packet_header_len(c) ((c & 0x03) + 1) /* number of bytes in a packet header */
35 /* number of data bytes in a MPI */
36 #define mpi_len(mpi) ((scalar_number(mpi, 2) + 7) / 8)
38 #define READ_MPI(n, bits) do { \
39 if (i_read + 2 > i_packet_len) \
41 int len = mpi_len(p_buf); \
42 if (len > (bits) / 8 || i_read + 2 + len > i_packet_len) \
45 memcpy(n, p_buf, len); \
46 p_buf += len; i_read += len; \
49 static inline int scalar_number(const uint8_t *p
, int header_len
)
51 ASSERT(header_len
== 1 || header_len
== 2 || header_len
== 4);
55 else if (header_len
== 2)
56 return (p
[0] << 8) + p
[1];
57 else if (header_len
== 4)
58 return (p
[0] << 24) + (p
[1] << 16) + (p
[2] << 8) + p
[3];
64 static size_t b64_decode_binary_to_buffer(uint8_t *p_dst
, size_t i_dst
, const char *p_src
, size_t srcLen
)
67 if (!Base64Decode(p_src
, (int)srcLen
, p_dst
, &len
))
73 * crc_octets() was lamely copied from rfc 2440
74 * Copyright (C) The Internet Society (1998). All Rights Reserved.
76 #define CRC24_INIT 0xB704CEL
77 #define CRC24_POLY 0x1864CFBL
79 static long crc_octets(uint8_t *octets
, size_t len
)
81 long crc
= CRC24_INIT
;
85 crc
^= (*octets
++) << 16;
86 for (i
= 0; i
< 8; i
++)
93 return crc
& 0xFFFFFFL
;
96 static size_t parse_signature_v3_packet(signature_packet_t
*p_sig
, const uint8_t *p_buf
, size_t i_sig_len
)
98 size_t i_read
= 1; /* we already read the version byte */
100 if (i_sig_len
< 19) /* signature is at least 19 bytes + the 2 MPIs */
103 p_sig
->specific
.v3
.hashed_data_len
= *p_buf
++; i_read
++;
104 if (p_sig
->specific
.v3
.hashed_data_len
!= 5)
107 p_sig
->type
= *p_buf
++; i_read
++;
109 memcpy(p_sig
->specific
.v3
.timestamp
, p_buf
, 4);
110 p_buf
+= 4; i_read
+= 4;
112 memcpy(p_sig
->issuer_longid
, p_buf
, 8);
113 p_buf
+= 8; i_read
+= 8;
115 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
117 p_sig
->digest_algo
= *p_buf
++; i_read
++;
119 p_sig
->hash_verification
[0] = *p_buf
++; i_read
++;
120 p_sig
->hash_verification
[1] = *p_buf
++; i_read
++;
122 ASSERT(i_read
== 19);
128 * fill a signature_packet_v4_t from signature packet data
129 * verify that it was used with a DSA public key, using SHA-1 digest
131 static size_t parse_signature_v4_packet(signature_packet_t
*p_sig
, const uint8_t *p_buf
, size_t i_sig_len
)
133 size_t i_read
= 1; /* we already read the version byte */
135 if (i_sig_len
< 10) /* signature is at least 10 bytes + the 2 MPIs */
138 p_sig
->type
= *p_buf
++; i_read
++;
140 p_sig
->public_key_algo
= *p_buf
++; i_read
++;
142 p_sig
->digest_algo
= *p_buf
++; i_read
++;
144 memcpy(p_sig
->specific
.v4
.hashed_data_len
, p_buf
, 2);
145 p_buf
+= 2; i_read
+= 2;
147 size_t i_hashed_data_len
= scalar_number(p_sig
->specific
.v4
.hashed_data_len
, 2);
148 i_read
+= i_hashed_data_len
;
149 if (i_read
+ 4 > i_sig_len
)
152 p_sig
->specific
.v4
.hashed_data
= (uint8_t*) malloc(i_hashed_data_len
);
153 if (!p_sig
->specific
.v4
.hashed_data
)
155 memcpy(p_sig
->specific
.v4
.hashed_data
, p_buf
, i_hashed_data_len
);
156 p_buf
+= i_hashed_data_len
;
158 memcpy(p_sig
->specific
.v4
.unhashed_data_len
, p_buf
, 2);
159 p_buf
+= 2; i_read
+= 2;
161 size_t i_unhashed_data_len
= scalar_number(p_sig
->specific
.v4
.unhashed_data_len
, 2);
162 i_read
+= i_unhashed_data_len
;
163 if (i_read
+ 2 > i_sig_len
)
166 p_sig
->specific
.v4
.unhashed_data
= (uint8_t*) malloc(i_unhashed_data_len
);
167 if (!p_sig
->specific
.v4
.unhashed_data
)
170 memcpy(p_sig
->specific
.v4
.unhashed_data
, p_buf
, i_unhashed_data_len
);
171 p_buf
+= i_unhashed_data_len
;
173 memcpy(p_sig
->hash_verification
, p_buf
, 2);
174 p_buf
+= 2; i_read
+= 2;
176 uint8_t *p
, *max_pos
;
177 p
= p_sig
->specific
.v4
.unhashed_data
;
178 max_pos
= p
+ scalar_number(p_sig
->specific
.v4
.unhashed_data_len
, 2);
185 size_t i_subpacket_len
;
190 i_subpacket_len
= *p
++;
196 i_subpacket_len
= (*p
++ - 192) << 8;
197 i_subpacket_len
+= *p
++ + 192;
203 i_subpacket_len
= *++p
<< 24;
204 i_subpacket_len
+= *++p
<< 16;
205 i_subpacket_len
+= *++p
<< 8;
206 i_subpacket_len
+= *++p
;
209 if (*p
== ISSUER_SUBPACKET
)
214 memcpy(&p_sig
->issuer_longid
, p
+ 1, 8);
219 p
+= i_subpacket_len
;
223 static int parse_signature_packet(signature_packet_t
*p_sig
, const uint8_t *p_buf
, size_t i_packet_len
)
225 if (!i_packet_len
) /* 1st sanity check, we need at least the version */
228 p_sig
->version
= *p_buf
++;
231 switch (p_sig
->version
)
234 i_read
= parse_signature_v3_packet(p_sig
, p_buf
, i_packet_len
);
237 p_sig
->specific
.v4
.hashed_data
= nullptr;
238 p_sig
->specific
.v4
.unhashed_data
= nullptr;
239 i_read
= parse_signature_v4_packet(p_sig
, p_buf
, i_packet_len
);
245 if (i_read
== 0) /* signature packet parsing has failed */
248 if (p_sig
->public_key_algo
!= PUBLIC_KEY_ALGO_DSA
)
251 if (p_sig
->digest_algo
!= DIGEST_ALGO_SHA1
)
256 case BINARY_SIGNATURE
:
258 case GENERIC_KEY_SIGNATURE
:
259 case PERSONA_KEY_SIGNATURE
:
260 case CASUAL_KEY_SIGNATURE
:
261 case POSITIVE_KEY_SIGNATURE
:
267 p_buf
--; /* rewind to the version byte */
270 READ_MPI(p_sig
->r
, 160);
271 READ_MPI(p_sig
->s
, 160);
273 ASSERT(i_read
== i_packet_len
);
274 if (i_read
< i_packet_len
) /* some extra data, hm ? */
280 if (p_sig
->version
== 4)
282 free(p_sig
->specific
.v4
.hashed_data
);
283 free(p_sig
->specific
.v4
.unhashed_data
);
290 * Transform an armored document in binary format
291 * Used on public keys and signatures
293 static int pgp_unarmor(const char *p_ibuf
, size_t i_ibuf_len
, uint8_t *p_obuf
, size_t i_obuf_len
)
295 const char *p_ipos
= p_ibuf
;
296 uint8_t *p_opos
= p_obuf
;
298 int i_header_skipped
= 0;
300 while (!i_end
&& p_ipos
< p_ibuf
+ i_ibuf_len
&& *p_ipos
!= '=')
302 if (*p_ipos
== '\r' || *p_ipos
== '\n')
308 size_t i_line_len
= strcspn(p_ipos
, "\r\n");
312 if (!i_header_skipped
)
314 if (!strncmp(p_ipos
, "-----BEGIN PGP", 14))
315 i_header_skipped
= 1;
317 p_ipos
+= i_line_len
+ 1;
321 if (!strncmp(p_ipos
, "Version:", 8))
323 p_ipos
+= i_line_len
+ 1;
327 if (p_ipos
[i_line_len
- 1] == '=')
332 p_opos
+= b64_decode_binary_to_buffer(p_opos
, p_obuf
- p_opos
+ i_obuf_len
, p_ipos
, (int)i_line_len
);
333 p_ipos
+= i_line_len
+ 1;
336 if (p_ipos
+ 1 < p_ibuf
+ i_ibuf_len
&& (*p_ipos
== '\r' || *p_ipos
== '\n'))
339 /* XXX: the CRC is OPTIONAL, really require it ? */
340 if (p_ipos
+ 5 > p_ibuf
+ i_ibuf_len
|| *p_ipos
++ != '=')
344 if (b64_decode_binary_to_buffer(p_crc
, sizeof(p_crc
), p_ipos
, 5) != 3)
347 long l_crc
= crc_octets(p_obuf
, p_opos
- p_obuf
);
348 long l_crc2
= (0 << 24) + (p_crc
[0] << 16) + (p_crc
[1] << 8) + p_crc
[2];
350 return (int)((l_crc2
== l_crc
) ? p_opos
- p_obuf
: 0);
354 * fill a public_key_packet_t structure from public key packet data
355 * verify that it is a version 4 public key packet, using DSA
357 static int parse_public_key_packet(public_key_packet_t
*p_key
, const uint8_t *p_buf
, size_t i_packet_len
)
359 if (i_packet_len
> 418 || i_packet_len
< 6)
364 p_key
->version
= *p_buf
++; i_read
++;
365 if (p_key
->version
!= 4)
368 /* XXX: warn when timestamp is > date ? */
369 memcpy(p_key
->timestamp
, p_buf
, 4); p_buf
+= 4; i_read
+= 4;
371 p_key
->algo
= *p_buf
++; i_read
++;
372 if (p_key
->algo
!= PUBLIC_KEY_ALGO_DSA
)
375 READ_MPI(p_key
->p
, 1024);
376 READ_MPI(p_key
->q
, 160);
377 READ_MPI(p_key
->g
, 1024);
378 READ_MPI(p_key
->y
, 1024);
380 if (i_read
!= i_packet_len
) /* some extra data eh ? */
390 * fill a public_key_t with public key data, including:
391 * * public key packet
392 * * signature packet issued by key which long id is p_sig_issuer
395 static int 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
)
397 const uint8_t *pos
= p_key_data
;
398 const uint8_t *max_pos
= pos
+ i_key_len
;
401 #define PUBLIC_KEY_FOUND 0x01
402 #define USER_ID_FOUND 0x02
403 #define SIGNATURE_FOUND 0X04
405 uint8_t *p_key_unarmored
= nullptr;
407 p_key
->psz_username
= nullptr;
408 p_key
->sig
.specific
.v4
.hashed_data
= nullptr;
409 p_key
->sig
.specific
.v4
.unhashed_data
= nullptr;
412 { /* first byte is ASCII, unarmoring */
413 p_key_unarmored
= (uint8_t*)malloc(i_key_len
);
414 if (!p_key_unarmored
)
416 int i_len
= pgp_unarmor((char*)p_key_data
, i_key_len
, p_key_unarmored
, i_key_len
);
421 pos
= p_key_unarmored
;
422 max_pos
= pos
+ i_len
;
425 while (pos
< max_pos
)
427 if (!(*pos
& 0x80) || *pos
& 0x40)
430 int i_type
= packet_type(*pos
);
432 int i_header_len
= packet_header_len(*pos
++);
433 if (pos
+ i_header_len
> max_pos
|| (i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4))
436 int i_packet_len
= scalar_number(pos
, i_header_len
);
439 if (pos
+ i_packet_len
> max_pos
)
444 case PUBLIC_KEY_PACKET
:
445 i_status
|= PUBLIC_KEY_FOUND
;
446 if (parse_public_key_packet(&p_key
->key
, pos
, i_packet_len
) != 0)
450 case SIGNATURE_PACKET
: /* we accept only v4 signatures here */
451 if (i_status
& SIGNATURE_FOUND
|| !p_sig_issuer
)
453 if (parse_signature_packet(&p_key
->sig
, pos
, i_packet_len
) == 0)
455 if (p_key
->sig
.version
!= 4)
457 if (memcmp( p_key
->sig
.issuer_longid
, p_sig_issuer
, 8))
459 free(p_key
->sig
.specific
.v4
.hashed_data
);
460 free(p_key
->sig
.specific
.v4
.unhashed_data
);
461 p_key
->sig
.specific
.v4
.hashed_data
= nullptr;
462 p_key
->sig
.specific
.v4
.unhashed_data
= nullptr;
465 i_status
|= SIGNATURE_FOUND
;
470 if (p_key
->psz_username
) /* save only the first User ID */
472 i_status
|= USER_ID_FOUND
;
473 p_key
->psz_username
= (uint8_t*)malloc(i_packet_len
+ 1);
474 if (!p_key
->psz_username
)
477 memcpy(p_key
->psz_username
, pos
, i_packet_len
);
478 p_key
->psz_username
[i_packet_len
] = '\0';
486 free(p_key_unarmored
);
488 if (!(i_status
& (PUBLIC_KEY_FOUND
| USER_ID_FOUND
)))
491 if (p_sig_issuer
&& !(i_status
& SIGNATURE_FOUND
))
497 if (p_key
->sig
.version
== 4)
499 free(p_key
->sig
.specific
.v4
.hashed_data
);
500 free(p_key
->sig
.specific
.v4
.unhashed_data
);
502 free(p_key
->psz_username
);
503 free(p_key_unarmored
);
507 static int LoadSignature(const CString
&signatureFilename
, signature_packet_t
*p_sig
)
509 FILE * pFile
= _tfsopen(signatureFilename
, _T("rb"), SH_DENYWR
);
513 std::unique_ptr
<unsigned char[]> buffer(new unsigned char[size
]);
515 if ((length
= (int)fread(buffer
.get(), sizeof(char), size
, pFile
)) >= 8)
518 // is unpacking needed?
519 if ((uint8_t)buffer
[0] < 0x80)
521 std::unique_ptr
<unsigned char[]> unpacked(new unsigned char[size
]);
522 size
= pgp_unarmor((char *)buffer
.get(), length
, unpacked
.get(), length
);
527 buffer
.swap(unpacked
);
532 if (packet_type(buffer
[0]) != SIGNATURE_PACKET
)
535 DWORD i_header_len
= packet_header_len(buffer
[0]);
536 if ((i_header_len
!= 1 && i_header_len
!= 2 && i_header_len
!= 4) || i_header_len
+ 1 > (DWORD
)size
)
539 DWORD i_len
= scalar_number((uint8_t *)(buffer
.get() + 1), i_header_len
);
540 if (i_len
+ i_header_len
+ 1 != (DWORD
)size
)
543 if (parse_signature_packet(p_sig
, (uint8_t *)(buffer
.get() + 1 + i_header_len
), i_len
))
546 if (p_sig
->type
!= BINARY_SIGNATURE
&& p_sig
->type
!= TEXT_SIGNATURE
)
548 if (p_sig
->version
== 4)
550 free(p_sig
->specific
.v4
.hashed_data
);
551 free(p_sig
->specific
.v4
.unhashed_data
);
564 static void CryptHashChar(HCRYPTHASH hHash
, const int c
)
566 CryptHashData(hHash
, (BYTE
*)&c
, 1, 0);
569 /* final part of the hash */
570 static int hash_finish(HCRYPTHASH hHash
, signature_packet_t
*p_sig
)
572 if (p_sig
->version
== 3)
574 CryptHashChar(hHash
, p_sig
->type
);
575 CryptHashData(hHash
, (unsigned char*)&p_sig
->specific
.v3
.timestamp
, 4, 0);
577 else if (p_sig
->version
== 4)
579 CryptHashChar(hHash
, p_sig
->version
);
580 CryptHashChar(hHash
, p_sig
->type
);
581 CryptHashChar(hHash
, p_sig
->public_key_algo
);
582 CryptHashChar(hHash
, p_sig
->digest_algo
);
583 CryptHashData(hHash
, p_sig
->specific
.v4
.hashed_data_len
, 2, 0);
584 unsigned int i_len
= scalar_number(p_sig
->specific
.v4
.hashed_data_len
, 2);
585 CryptHashData(hHash
, p_sig
->specific
.v4
.hashed_data
, i_len
, 0);
587 CryptHashChar(hHash
, 0x04);
588 CryptHashChar(hHash
, 0xFF);
590 i_len
+= 6; /* hashed data + 6 bytes header */
592 CryptHashChar(hHash
, (i_len
>> 24) & 0xff);
593 CryptHashChar(hHash
, (i_len
>> 16) & 0xff);
594 CryptHashChar(hHash
, (i_len
>> 8) & 0xff);
595 CryptHashChar(hHash
, (i_len
) & 0xff);
598 { /* RFC 4880 only tells about versions 3 and 4 */
606 * Generate a SHA1 hash on a public key, to verify a signature made on that hash
607 * Note that we need the signature (v4) to compute the hash
609 static int hash_sha1_from_public_key(HCRYPTHASH hHash
, public_key_t
*p_pkey
)
611 if (p_pkey
->sig
.version
!= 4)
614 if (p_pkey
->sig
.type
< GENERIC_KEY_SIGNATURE
|| p_pkey
->sig
.type
> POSITIVE_KEY_SIGNATURE
)
617 CryptHashChar(hHash
, 0x99);
619 unsigned int i_p_len
= mpi_len(p_pkey
->key
.p
);
620 unsigned int i_g_len
= mpi_len(p_pkey
->key
.g
);
621 unsigned int i_q_len
= mpi_len(p_pkey
->key
.q
);
622 unsigned int i_y_len
= mpi_len(p_pkey
->key
.y
);
624 DWORD i_size
= 6 + 2*4 + i_p_len
+ i_g_len
+ i_q_len
+ i_y_len
;
626 CryptHashChar(hHash
, (i_size
>> 8) & 0xff);
627 CryptHashChar(hHash
, i_size
& 0xff);
629 CryptHashChar(hHash
, p_pkey
->key
.version
);
630 CryptHashData(hHash
, p_pkey
->key
.timestamp
, 4, 0);
631 CryptHashChar(hHash
, p_pkey
->key
.algo
);
633 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.p
, 2, 0);
634 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.p
+ 2, i_p_len
, 0);
636 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.q
, 2, 0);
637 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.q
+ 2, i_q_len
, 0);
639 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.g
, 2, 0);
640 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.g
+ 2, i_g_len
, 0);
642 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.y
, 2, 0);
643 CryptHashData(hHash
, (uint8_t*)&p_pkey
->key
.y
+ 2, i_y_len
, 0);
645 CryptHashChar(hHash
, 0xb4);
647 size_t i_len
= strlen((char *)p_pkey
->psz_username
);
649 CryptHashChar(hHash
, (i_len
>> 24) & 0xff);
650 CryptHashChar(hHash
, (i_len
>> 16) & 0xff);
651 CryptHashChar(hHash
, (i_len
>> 8) & 0xff);
652 CryptHashChar(hHash
, (i_len
) & 0xff);
654 CryptHashData(hHash
, p_pkey
->psz_username
, (DWORD
)i_len
, 0);
656 return hash_finish(hHash
, &p_pkey
->sig
);
659 static int hash_sha1_from_file(HCRYPTHASH hHash
, CString filename
, signature_packet_t
*p_sig
)
661 FILE * pFile
= _tfsopen(filename
, _T("rb"), SH_DENYWR
);
665 char buf
[4097] = { 0 };
668 while ((read
= (int)fread(buf
, sizeof(char), sizeof(buf
) - 1, pFile
)) > 0)
670 if (p_sig
->type
== TEXT_SIGNATURE
)
673 char * psz_string
= buf
;
676 if (nlHandling
== 1 && (*psz_string
== '\r' || *psz_string
== '\n'))
678 CryptHashChar(hHash
, '\r');
679 CryptHashChar(hHash
, '\n');
682 if (nlHandling
== 2 && *psz_string
== '\r')
690 if ((nlHandling
== 2 || nlHandling
== 3) && *psz_string
== '\n')
697 size_t i_len
= strcspn(psz_string
, "\r\n");
701 CryptHashData(hHash
, (BYTE
*)psz_string
, (DWORD
)i_len
, 0);
706 if (*psz_string
== '\r' || *psz_string
== '\n')
708 CryptHashChar(hHash
, '\r');
709 CryptHashChar(hHash
, '\n');
712 if (*psz_string
== '\r')
718 if (*psz_string
== '\n')
727 CryptHashData(hHash
, (BYTE
*)buf
, read
, 0);
732 return hash_finish(hHash
, p_sig
);
735 static int check_hash(HCRYPTHASH hHash
, signature_packet_t
*p_sig
)
738 unsigned char hash
[20] = { 0 };
739 CryptGetHashParam(hHash
, HP_HASHVAL
, hash
, &len
, 0);
741 if (hash
[0] != p_sig
->hash_verification
[0] || hash
[1] != p_sig
->hash_verification
[1])
747 static int verify_signature(HCRYPTPROV hCryptProv
, HCRYPTHASH hHash
, public_key_t
&p_pkey
, signature_packet_t
&p_sig
)
750 // based on http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2004-10/0040.html
752 dsakey
.blobheader
.bType
= PUBLICKEYBLOB
; // 0x06
753 dsakey
.blobheader
.bVersion
= CUR_BLOB_VERSION
+ 1; // 0x03
754 dsakey
.blobheader
.reserved
= 0;
755 dsakey
.blobheader
.aiKeyAlg
= CALG_DSS_SIGN
;
756 dsakey
.dsspubkeyver3
.magic
= 0x33535344; // ASCII of "DSS3";
757 dsakey
.dsspubkeyver3
.bitlenP
= 1024; // # of bits in prime modulus
758 dsakey
.dsspubkeyver3
.bitlenQ
= 160; // # of bits in prime q, 0 if not available
759 dsakey
.dsspubkeyver3
.bitlenJ
= 0; // # of bits in (p-1)/q, 0 if not available
760 dsakey
.dsspubkeyver3
.DSSSeed
.counter
= 0xFFFFFFFF; // not available
762 memcpy(dsakey
.p
, p_pkey
.key
.p
+ 2, sizeof(p_pkey
.key
.p
) - 2); std::reverse(dsakey
.p
, dsakey
.p
+ sizeof(dsakey
.p
));
763 memcpy(dsakey
.q
, p_pkey
.key
.q
+ 2, sizeof(p_pkey
.key
.q
) - 2); std::reverse(dsakey
.q
, dsakey
.q
+ sizeof(dsakey
.q
));
764 memcpy(dsakey
.g
, p_pkey
.key
.g
+ 2, sizeof(p_pkey
.key
.g
) - 2); std::reverse(dsakey
.g
, dsakey
.g
+ sizeof(dsakey
.g
));
765 memcpy(dsakey
.y
, p_pkey
.key
.y
+ 2, sizeof(p_pkey
.key
.y
) - 2); std::reverse(dsakey
.y
, dsakey
.y
+ sizeof(dsakey
.y
));
767 if (CryptImportKey(hCryptProv
, (BYTE
*)&dsakey
, sizeof(dsakey
), 0, 0, &hPubKey
) == 0)
770 unsigned char signature
[40] = { 0 };
771 memcpy(signature
, p_sig
.r
+ 2, 20);
772 memcpy(signature
+ 20, p_sig
.s
+ 2, 20);
773 std::reverse(signature
, signature
+ 20);
774 std::reverse(signature
+ 20, signature
+ 40);
775 if (!CryptVerifySignature(hHash
, signature
, sizeof(signature
), hPubKey
, nullptr, 0))
777 CryptDestroyKey(hPubKey
);
781 CryptDestroyKey(hPubKey
);
786 * download a public key (the last one) from TortoiseGit server, and parse it
788 static public_key_t
*download_key(const uint8_t *p_longid
, const uint8_t *p_signature_issuer
, CUpdateDownloader
*updateDownloader
)
790 ASSERT(updateDownloader
);
793 url
.Format(L
"http://download.tortoisegit.org/keys/%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X.asc", p_longid
[0], p_longid
[1], p_longid
[2], p_longid
[3], p_longid
[4], p_longid
[5], p_longid
[6], p_longid
[7]);
795 CString tempfile
= CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
796 if (updateDownloader
->DownloadFile(url
, tempfile
, false))
800 std::unique_ptr
<char[]> buffer(new char[size
]);
801 FILE * pFile
= _tfsopen(tempfile
, _T("rb"), SH_DENYWR
);
805 if ((length
= (int)fread(buffer
.get(), sizeof(char), size
, pFile
)) >= 8)
819 public_key_t
*p_pkey
= (public_key_t
*) malloc(sizeof(public_key_t
));
822 DeleteUrlCacheEntry(url
);
826 memcpy(p_pkey
->longid
, p_longid
, 8);
828 if (parse_public_key((const uint8_t *)buffer
.get(), size
, p_pkey
, p_signature_issuer
))
837 int VerifyIntegrity(const CString
&filename
, const CString
&signatureFilename
, CUpdateDownloader
*updateDownloader
)
839 ASSERT(updateDownloader
);
841 signature_packet_t p_sig
;
842 memset(&p_sig
, 0, sizeof(signature_packet_t
));
843 if (LoadSignature(signatureFilename
, &p_sig
))
847 memset(&p_pkey
, 0, sizeof(public_key_t
));
848 if (parse_public_key(tortoisegit_public_key
, sizeof(tortoisegit_public_key
), &p_pkey
, nullptr))
850 if (p_sig
.version
== 4)
852 free(p_sig
.specific
.v4
.hashed_data
);
853 free(p_sig
.specific
.v4
.unhashed_data
);
857 memcpy(p_pkey
.longid
, tortoisegit_public_key_longid
, 8);
859 HCRYPTPROV hCryptProv
;
860 if (!CryptAcquireContext(&hCryptProv
, nullptr, nullptr, PROV_DSS
, CRYPT_VERIFYCONTEXT
))
862 if (p_sig
.version
== 4)
864 free(p_sig
.specific
.v4
.hashed_data
);
865 free(p_sig
.specific
.v4
.unhashed_data
);
867 free(p_pkey
.psz_username
);
871 if (memcmp(p_sig
.issuer_longid
, p_pkey
.longid
, 8) != 0)
873 public_key_t
*p_new_pkey
= download_key(p_sig
.issuer_longid
, tortoisegit_public_key_longid
, updateDownloader
);
876 if (p_sig
.version
== 4)
878 free(p_sig
.specific
.v4
.hashed_data
);
879 free(p_sig
.specific
.v4
.unhashed_data
);
881 free(p_pkey
.psz_username
);
882 CryptReleaseContext(hCryptProv
, 0);
887 if (!CryptCreateHash(hCryptProv
, CALG_SHA1
, 0, 0, &hHash
))
889 if (p_sig
.version
== 4)
891 free(p_sig
.specific
.v4
.hashed_data
);
892 free(p_sig
.specific
.v4
.unhashed_data
);
894 free(p_pkey
.psz_username
);
895 CryptReleaseContext(hCryptProv
, 0);
896 free(p_new_pkey
->psz_username
);
897 if (p_new_pkey
->sig
.version
== 4)
899 free(p_new_pkey
->sig
.specific
.v4
.hashed_data
);
900 free(p_new_pkey
->sig
.specific
.v4
.unhashed_data
);
906 if (hash_sha1_from_public_key(hHash
, p_new_pkey
))
908 if (p_sig
.version
== 4)
910 free(p_sig
.specific
.v4
.hashed_data
);
911 free(p_sig
.specific
.v4
.unhashed_data
);
913 free(p_pkey
.psz_username
);
914 CryptReleaseContext(hCryptProv
, 0);
915 free(p_new_pkey
->psz_username
);
916 if (p_new_pkey
->sig
.version
== 4)
918 free(p_new_pkey
->sig
.specific
.v4
.hashed_data
);
919 free(p_new_pkey
->sig
.specific
.v4
.unhashed_data
);
922 CryptDestroyHash(hHash
);
926 if (check_hash(hHash
, &p_new_pkey
->sig
))
928 if (p_sig
.version
== 4)
930 free(p_sig
.specific
.v4
.hashed_data
);
931 free(p_sig
.specific
.v4
.unhashed_data
);
933 free(p_pkey
.psz_username
);
934 CryptReleaseContext(hCryptProv
, 0);
935 free(p_new_pkey
->psz_username
);
936 if (p_new_pkey
->sig
.version
== 4)
938 free(p_new_pkey
->sig
.specific
.v4
.hashed_data
);
939 free(p_new_pkey
->sig
.specific
.v4
.unhashed_data
);
942 CryptDestroyHash(hHash
);
946 if (verify_signature(hCryptProv
, hHash
, p_pkey
, p_new_pkey
->sig
))
948 if (p_sig
.version
== 4)
950 free(p_sig
.specific
.v4
.hashed_data
);
951 free(p_sig
.specific
.v4
.unhashed_data
);
953 free(p_pkey
.psz_username
);
954 CryptReleaseContext(hCryptProv
, 0);
955 free(p_new_pkey
->psz_username
);
956 if (p_new_pkey
->sig
.version
== 4)
958 free(p_new_pkey
->sig
.specific
.v4
.hashed_data
);
959 free(p_new_pkey
->sig
.specific
.v4
.unhashed_data
);
962 CryptDestroyHash(hHash
);
967 CryptDestroyHash(hHash
);
968 free(p_pkey
.psz_username
);
969 p_pkey
= *p_new_pkey
;
970 if (p_pkey
.sig
.version
== 4)
972 p_pkey
.sig
.version
= 0;
973 free(p_pkey
.sig
.specific
.v4
.hashed_data
);
974 free(p_pkey
.sig
.specific
.v4
.unhashed_data
);
983 if (!CryptCreateHash(hCryptProv
, CALG_SHA1
, 0, 0, &hHash
))
986 if (hash_sha1_from_file(hHash
, filename
, &p_sig
))
989 if (check_hash(hHash
, &p_sig
))
992 if (verify_signature(hCryptProv
, hHash
, p_pkey
, p_sig
))
998 CryptDestroyHash(hHash
);
999 CryptReleaseContext(hCryptProv
, 0);
1001 free(p_pkey
.psz_username
);
1002 if (p_sig
.version
== 4)
1004 free(p_sig
.specific
.v4
.hashed_data
);
1005 free(p_sig
.specific
.v4
.unhashed_data
);