Add support for "project" config level
[TortoiseGit.git] / src / TortoiseProc / UpdateCrypto.cpp
blobd2796769400704dc6b6b596ff8b3ad0d8cae850a
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013 Sven Strickroth <email@cs-ware.de>
4 // Copyright (C) VLC project (http://videolan.org)
5 // - pgp parsing code was copied from src/misc/update(_crypto)?.c
6 // Copyright (C) The Internet Society (1998). All Rights Reserved.
7 // - crc_octets() was lamely copied from rfc 2440
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
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 Foundation,
21 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "stdafx.h"
24 #include "UpdateCrypto.h"
25 #include "FormatMessageWrapper.h"
26 #include <atlenc.h>
27 #define NEED_SIGNING_KEY
28 #include "..\version.h"
29 #include "TempFile.h"
31 #define packet_type(c) ((c & 0x3c) >> 2) /* 0x3C = 00111100 */
32 #define packet_header_len(c) ((c & 0x03) + 1) /* number of bytes in a packet header */
34 /* number of data bytes in a MPI */
35 #define mpi_len(mpi) ((scalar_number(mpi, 2) + 7) / 8)
37 #define READ_MPI(n, bits) do { \
38 if (i_read + 2 > i_packet_len) \
39 goto error; \
40 int len = mpi_len(p_buf); \
41 if (len > (bits) / 8 || i_read + 2 + len > i_packet_len) \
42 goto error; \
43 len += 2; \
44 memcpy(n, p_buf, len); \
45 p_buf += len; i_read += len; \
46 } while(0)
48 static inline int scalar_number(const uint8_t *p, int header_len)
50 ASSERT(header_len == 1 || header_len == 2 || header_len == 4);
52 if (header_len == 1)
53 return p[0];
54 else if (header_len == 2)
55 return (p[0] << 8) + p[1];
56 else if (header_len == 4)
57 return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
58 else
59 abort();
62 /* Base64 decoding */
63 static size_t b64_decode_binary_to_buffer(uint8_t *p_dst, size_t i_dst, const char *p_src, size_t srcLen)
65 int len = (int)i_dst;
66 if (!Base64Decode(p_src, (int)srcLen, p_dst, &len))
67 return 0;
68 return len;
72 * crc_octets() was lamely copied from rfc 2440
73 * Copyright (C) The Internet Society (1998). All Rights Reserved.
75 #define CRC24_INIT 0xB704CEL
76 #define CRC24_POLY 0x1864CFBL
78 static long crc_octets(uint8_t *octets, size_t len)
80 long crc = CRC24_INIT;
81 int i;
82 while (len--)
84 crc ^= (*octets++) << 16;
85 for (i = 0; i < 8; i++)
87 crc <<= 1;
88 if (crc & 0x1000000)
89 crc ^= CRC24_POLY;
92 return crc & 0xFFFFFFL;
95 static size_t parse_signature_v3_packet(signature_packet_t *p_sig, const uint8_t *p_buf, size_t i_sig_len)
97 size_t i_read = 1; /* we already read the version byte */
99 if (i_sig_len < 19) /* signature is at least 19 bytes + the 2 MPIs */
100 return 0;
102 p_sig->specific.v3.hashed_data_len = *p_buf++; i_read++;
103 if (p_sig->specific.v3.hashed_data_len != 5)
104 return 0;
106 p_sig->type = *p_buf++; i_read++;
108 memcpy(p_sig->specific.v3.timestamp, p_buf, 4);
109 p_buf += 4; i_read += 4;
111 memcpy(p_sig->issuer_longid, p_buf, 8);
112 p_buf += 8; i_read += 8;
114 p_sig->public_key_algo = *p_buf++; i_read++;
116 p_sig->digest_algo = *p_buf++; i_read++;
118 p_sig->hash_verification[0] = *p_buf++; i_read++;
119 p_sig->hash_verification[1] = *p_buf++; i_read++;
121 ASSERT(i_read == 19);
123 return i_read;
127 * fill a signature_packet_v4_t from signature packet data
128 * verify that it was used with a DSA public key, using SHA-1 digest
130 static size_t parse_signature_v4_packet(signature_packet_t *p_sig, const uint8_t *p_buf, size_t i_sig_len)
132 size_t i_read = 1; /* we already read the version byte */
134 if (i_sig_len < 10) /* signature is at least 10 bytes + the 2 MPIs */
135 return 0;
137 p_sig->type = *p_buf++; i_read++;
139 p_sig->public_key_algo = *p_buf++; i_read++;
141 p_sig->digest_algo = *p_buf++; i_read++;
143 memcpy(p_sig->specific.v4.hashed_data_len, p_buf, 2);
144 p_buf += 2; i_read += 2;
146 size_t i_hashed_data_len = scalar_number(p_sig->specific.v4.hashed_data_len, 2);
147 i_read += i_hashed_data_len;
148 if (i_read + 4 > i_sig_len)
149 return 0;
151 p_sig->specific.v4.hashed_data = (uint8_t*) malloc(i_hashed_data_len);
152 if (!p_sig->specific.v4.hashed_data)
153 return 0;
154 memcpy(p_sig->specific.v4.hashed_data, p_buf, i_hashed_data_len);
155 p_buf += i_hashed_data_len;
157 memcpy(p_sig->specific.v4.unhashed_data_len, p_buf, 2);
158 p_buf += 2; i_read += 2;
160 size_t i_unhashed_data_len = scalar_number(p_sig->specific.v4.unhashed_data_len, 2);
161 i_read += i_unhashed_data_len;
162 if (i_read + 2 > i_sig_len)
163 return 0;
165 p_sig->specific.v4.unhashed_data = (uint8_t*) malloc(i_unhashed_data_len);
166 if (!p_sig->specific.v4.unhashed_data)
167 return 0;
169 memcpy(p_sig->specific.v4.unhashed_data, p_buf, i_unhashed_data_len);
170 p_buf += i_unhashed_data_len;
172 memcpy(p_sig->hash_verification, p_buf, 2);
173 p_buf += 2; i_read += 2;
175 uint8_t *p, *max_pos;
176 p = p_sig->specific.v4.unhashed_data;
177 max_pos = p + scalar_number(p_sig->specific.v4.unhashed_data_len, 2);
179 for (;;)
181 if (p > max_pos)
182 return 0;
184 size_t i_subpacket_len;
185 if (*p < 192)
187 if (p + 1 > max_pos)
188 return 0;
189 i_subpacket_len = *p++;
191 else if (*p < 255)
193 if (p + 2 > max_pos)
194 return 0;
195 i_subpacket_len = (*p++ - 192) << 8;
196 i_subpacket_len += *p++ + 192;
198 else
200 if (p + 4 > max_pos)
201 return 0;
202 i_subpacket_len = *++p << 24;
203 i_subpacket_len += *++p << 16;
204 i_subpacket_len += *++p << 8;
205 i_subpacket_len += *++p;
208 if (*p == ISSUER_SUBPACKET)
210 if (p + 9 > max_pos)
211 return 0;
213 memcpy(&p_sig->issuer_longid, p + 1, 8);
215 return i_read;
218 p += i_subpacket_len;
222 static int parse_signature_packet(signature_packet_t *p_sig, const uint8_t *p_buf, size_t i_packet_len)
224 if (!i_packet_len) /* 1st sanity check, we need at least the version */
225 return -1;
227 p_sig->version = *p_buf++;
229 size_t i_read;
230 switch (p_sig->version)
232 case 3:
233 i_read = parse_signature_v3_packet(p_sig, p_buf, i_packet_len);
234 break;
235 case 4:
236 p_sig->specific.v4.hashed_data = nullptr;
237 p_sig->specific.v4.unhashed_data = nullptr;
238 i_read = parse_signature_v4_packet(p_sig, p_buf, i_packet_len);
239 break;
240 default:
241 return -1;
244 if (i_read == 0) /* signature packet parsing has failed */
245 goto error;
247 if (p_sig->public_key_algo != PUBLIC_KEY_ALGO_DSA)
248 goto error;
250 if (p_sig->digest_algo != DIGEST_ALGO_SHA1)
251 goto error;
253 switch (p_sig->type)
255 case BINARY_SIGNATURE:
256 case TEXT_SIGNATURE:
257 case GENERIC_KEY_SIGNATURE:
258 case PERSONA_KEY_SIGNATURE:
259 case CASUAL_KEY_SIGNATURE:
260 case POSITIVE_KEY_SIGNATURE:
261 break;
262 default:
263 goto error;
266 p_buf--; /* rewind to the version byte */
267 p_buf += i_read;
269 READ_MPI(p_sig->r, 160);
270 READ_MPI(p_sig->s, 160);
272 ASSERT(i_read == i_packet_len);
273 if (i_read < i_packet_len) /* some extra data, hm ? */
274 goto error;
276 return 0;
278 error:
279 if (p_sig->version == 4)
281 free(p_sig->specific.v4.hashed_data);
282 free(p_sig->specific.v4.unhashed_data);
285 return -1;
289 * Transform an armored document in binary format
290 * Used on public keys and signatures
292 static int pgp_unarmor(const char *p_ibuf, size_t i_ibuf_len, uint8_t *p_obuf, size_t i_obuf_len)
294 const char *p_ipos = p_ibuf;
295 uint8_t *p_opos = p_obuf;
296 int i_end = 0;
297 int i_header_skipped = 0;
299 while (!i_end && p_ipos < p_ibuf + i_ibuf_len && *p_ipos != '=')
301 if (*p_ipos == '\r' || *p_ipos == '\n')
303 p_ipos++;
304 continue;
307 size_t i_line_len = strcspn(p_ipos, "\r\n");
308 if (i_line_len == 0)
309 continue;
311 if (!i_header_skipped)
313 if (!strncmp(p_ipos, "-----BEGIN PGP", 14))
314 i_header_skipped = 1;
316 p_ipos += i_line_len + 1;
317 continue;
320 if (!strncmp(p_ipos, "Version:", 8))
322 p_ipos += i_line_len + 1;
323 continue;
326 if (p_ipos[i_line_len - 1] == '=')
328 i_end = 1;
331 p_opos += b64_decode_binary_to_buffer(p_opos, p_obuf - p_opos + i_obuf_len, p_ipos, (int)i_line_len);
332 p_ipos += i_line_len + 1;
335 if (p_ipos + 1 < p_ibuf + i_ibuf_len && (*p_ipos == '\r' || *p_ipos == '\n'))
336 p_ipos++;
338 /* XXX: the CRC is OPTIONAL, really require it ? */
339 if (p_ipos + 5 > p_ibuf + i_ibuf_len || *p_ipos++ != '=')
340 return 0;
342 uint8_t p_crc[3];
343 if (b64_decode_binary_to_buffer(p_crc, sizeof(p_crc), p_ipos, 5) != 3)
344 return 0;
346 long l_crc = crc_octets(p_obuf, p_opos - p_obuf);
347 long l_crc2 = (0 << 24) + (p_crc[0] << 16) + (p_crc[1] << 8) + p_crc[2];
349 return (int)((l_crc2 == l_crc) ? p_opos - p_obuf : 0);
353 * fill a public_key_packet_t structure from public key packet data
354 * verify that it is a version 4 public key packet, using DSA
356 static int parse_public_key_packet(public_key_packet_t *p_key, const uint8_t *p_buf, size_t i_packet_len)
358 if (i_packet_len > 418 || i_packet_len < 6)
359 return -1;
361 size_t i_read = 0;
363 p_key->version = *p_buf++; i_read++;
364 if (p_key->version != 4)
365 return -1;
367 /* XXX: warn when timestamp is > date ? */
368 memcpy(p_key->timestamp, p_buf, 4); p_buf += 4; i_read += 4;
370 p_key->algo = *p_buf++; i_read++;
371 if (p_key->algo != PUBLIC_KEY_ALGO_DSA)
372 return -1;
374 READ_MPI(p_key->p, 1024);
375 READ_MPI(p_key->q, 160);
376 READ_MPI(p_key->g, 1024);
377 READ_MPI(p_key->y, 1024);
379 if (i_read != i_packet_len) /* some extra data eh ? */
380 return -1;
382 return 0;
384 error:
385 return -1;
389 * fill a public_key_t with public key data, including:
390 * * public key packet
391 * * signature packet issued by key which long id is p_sig_issuer
392 * * user id packet
394 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)
396 const uint8_t *pos = p_key_data;
397 const uint8_t *max_pos = pos + i_key_len;
399 int i_status = 0;
400 #define PUBLIC_KEY_FOUND 0x01
401 #define USER_ID_FOUND 0x02
402 #define SIGNATURE_FOUND 0X04
404 uint8_t *p_key_unarmored = nullptr;
406 p_key->psz_username = nullptr;
407 p_key->sig.specific.v4.hashed_data = nullptr;
408 p_key->sig.specific.v4.unhashed_data = nullptr;
410 if (!(*pos & 0x80))
411 { /* first byte is ASCII, unarmoring */
412 p_key_unarmored = (uint8_t*)malloc(i_key_len);
413 if (!p_key_unarmored)
414 return -1;
415 int i_len = pgp_unarmor((char*)p_key_data, i_key_len, p_key_unarmored, i_key_len);
417 if (i_len == 0)
418 goto error;
420 pos = p_key_unarmored;
421 max_pos = pos + i_len;
424 while (pos < max_pos)
426 if (!(*pos & 0x80) || *pos & 0x40)
427 goto error;
429 int i_type = packet_type(*pos);
431 int i_header_len = packet_header_len(*pos++);
432 if (pos + i_header_len > max_pos || (i_header_len != 1 && i_header_len != 2 && i_header_len != 4))
433 goto error;
435 int i_packet_len = scalar_number(pos, i_header_len);
436 pos += i_header_len;
438 if (pos + i_packet_len > max_pos)
439 goto error;
441 switch (i_type)
443 case PUBLIC_KEY_PACKET:
444 i_status |= PUBLIC_KEY_FOUND;
445 if (parse_public_key_packet(&p_key->key, pos, i_packet_len) != 0)
446 goto error;
447 break;
449 case SIGNATURE_PACKET: /* we accept only v4 signatures here */
450 if (i_status & SIGNATURE_FOUND || !p_sig_issuer)
451 break;
452 if (parse_signature_packet(&p_key->sig, pos, i_packet_len) == 0)
454 if (p_key->sig.version != 4)
455 break;
456 if (memcmp( p_key->sig.issuer_longid, p_sig_issuer, 8))
458 free(p_key->sig.specific.v4.hashed_data);
459 free(p_key->sig.specific.v4.unhashed_data);
460 p_key->sig.specific.v4.hashed_data = nullptr;
461 p_key->sig.specific.v4.unhashed_data = nullptr;
462 break;
464 i_status |= SIGNATURE_FOUND;
466 break;
468 case USER_ID_PACKET:
469 if (p_key->psz_username) /* save only the first User ID */
470 break;
471 i_status |= USER_ID_FOUND;
472 p_key->psz_username = (uint8_t*)malloc(i_packet_len + 1);
473 if (!p_key->psz_username)
474 goto error;
476 memcpy(p_key->psz_username, pos, i_packet_len);
477 p_key->psz_username[i_packet_len] = '\0';
478 break;
480 default:
481 break;
483 pos += i_packet_len;
485 free(p_key_unarmored);
487 if (!(i_status & (PUBLIC_KEY_FOUND | USER_ID_FOUND)))
488 return -1;
490 if (p_sig_issuer && !(i_status & SIGNATURE_FOUND))
491 return -1;
493 return 0;
495 error:
496 if (p_key->sig.version == 4)
498 free(p_key->sig.specific.v4.hashed_data);
499 free(p_key->sig.specific.v4.unhashed_data);
501 free(p_key->psz_username);
502 free(p_key_unarmored);
503 return -1;
506 static int LoadSignature(const CString &signatureFilename, signature_packet_t *p_sig)
508 FILE * pFile = _tfsopen(signatureFilename, _T("rb"), SH_DENYWR);
509 if (pFile)
511 int size = 65536;
512 std::unique_ptr<unsigned char[]> buffer(new unsigned char[size]);
513 int length = 0;
514 if ((length = (int)fread(buffer.get(), sizeof(char), size, pFile)) >= 8)
516 fclose(pFile);
517 // is unpacking needed?
518 if ((uint8_t)buffer[0] < 0x80)
520 std::unique_ptr<unsigned char[]> unpacked(new unsigned char[size]);
521 size = pgp_unarmor((char *)buffer.get(), length, unpacked.get(), length);
523 if (size < 2)
524 return -1;
526 buffer.swap(unpacked);
528 else
529 size = length;
531 if (packet_type(buffer[0]) != SIGNATURE_PACKET)
532 return -1;
534 DWORD i_header_len = packet_header_len(buffer[0]);
535 if ((i_header_len != 1 && i_header_len != 2 && i_header_len != 4) || i_header_len + 1 > (DWORD)size)
536 return -1;
538 DWORD i_len = scalar_number((uint8_t *)(buffer.get() + 1), i_header_len);
539 if (i_len + i_header_len + 1 != (DWORD)size)
540 return -1;
542 if (parse_signature_packet(p_sig, (uint8_t *)(buffer.get() + 1 + i_header_len), i_len))
543 return -1;
545 if (p_sig->type != BINARY_SIGNATURE && p_sig->type != TEXT_SIGNATURE)
547 if (p_sig->version == 4)
549 free(p_sig->specific.v4.hashed_data);
550 free(p_sig->specific.v4.unhashed_data);
552 return -1;
555 return 0;
557 else
558 fclose(pFile);
560 return -1;
563 static void CryptHashChar(HCRYPTHASH hHash, const int c)
565 CryptHashData(hHash, (BYTE *)&c, 1, 0);
568 /* final part of the hash */
569 static int hash_finish(HCRYPTHASH hHash, signature_packet_t *p_sig)
571 if (p_sig->version == 3)
573 CryptHashChar(hHash, p_sig->type);
574 CryptHashData(hHash, (unsigned char*)&p_sig->specific.v3.timestamp, 4, 0);
576 else if (p_sig->version == 4)
578 CryptHashChar(hHash, p_sig->version);
579 CryptHashChar(hHash, p_sig->type);
580 CryptHashChar(hHash, p_sig->public_key_algo);
581 CryptHashChar(hHash, p_sig->digest_algo);
582 CryptHashData(hHash, p_sig->specific.v4.hashed_data_len, 2, 0);
583 unsigned int i_len = scalar_number(p_sig->specific.v4.hashed_data_len, 2);
584 CryptHashData(hHash, p_sig->specific.v4.hashed_data, i_len, 0);
586 CryptHashChar(hHash, 0x04);
587 CryptHashChar(hHash, 0xFF);
589 i_len += 6; /* hashed data + 6 bytes header */
591 CryptHashChar(hHash, (i_len >> 24) & 0xff);
592 CryptHashChar(hHash, (i_len >> 16) & 0xff);
593 CryptHashChar(hHash, (i_len >> 8) & 0xff);
594 CryptHashChar(hHash, (i_len) & 0xff);
596 else
597 { /* RFC 4880 only tells about versions 3 and 4 */
598 return -1;
601 return 0;
605 * Generate a SHA1 hash on a public key, to verify a signature made on that hash
606 * Note that we need the signature (v4) to compute the hash
608 static int hash_sha1_from_public_key(HCRYPTHASH hHash, public_key_t *p_pkey)
610 if (p_pkey->sig.version != 4)
611 return -1;
613 if (p_pkey->sig.type < GENERIC_KEY_SIGNATURE || p_pkey->sig.type > POSITIVE_KEY_SIGNATURE)
614 return -1;
616 CryptHashChar(hHash, 0x99);
618 unsigned int i_p_len = mpi_len(p_pkey->key.p);
619 unsigned int i_g_len = mpi_len(p_pkey->key.g);
620 unsigned int i_q_len = mpi_len(p_pkey->key.q);
621 unsigned int i_y_len = mpi_len(p_pkey->key.y);
623 DWORD i_size = 6 + 2*4 + i_p_len + i_g_len + i_q_len + i_y_len;
625 CryptHashChar(hHash, (i_size >> 8) & 0xff);
626 CryptHashChar(hHash, i_size & 0xff);
628 CryptHashChar(hHash, p_pkey->key.version);
629 CryptHashData(hHash, p_pkey->key.timestamp, 4, 0);
630 CryptHashChar(hHash, p_pkey->key.algo);
632 CryptHashData(hHash, (uint8_t*)&p_pkey->key.p, 2, 0);
633 CryptHashData(hHash, (uint8_t*)&p_pkey->key.p + 2, i_p_len, 0);
635 CryptHashData(hHash, (uint8_t*)&p_pkey->key.q, 2, 0);
636 CryptHashData(hHash, (uint8_t*)&p_pkey->key.q + 2, i_q_len, 0);
638 CryptHashData(hHash, (uint8_t*)&p_pkey->key.g, 2, 0);
639 CryptHashData(hHash, (uint8_t*)&p_pkey->key.g + 2, i_g_len, 0);
641 CryptHashData(hHash, (uint8_t*)&p_pkey->key.y, 2, 0);
642 CryptHashData(hHash, (uint8_t*)&p_pkey->key.y + 2, i_y_len, 0);
644 CryptHashChar(hHash, 0xb4);
646 size_t i_len = strlen((char *)p_pkey->psz_username);
648 CryptHashChar(hHash, (i_len >> 24) & 0xff);
649 CryptHashChar(hHash, (i_len >> 16) & 0xff);
650 CryptHashChar(hHash, (i_len >> 8) & 0xff);
651 CryptHashChar(hHash, (i_len) & 0xff);
653 CryptHashData(hHash, p_pkey->psz_username, (DWORD)i_len, 0);
655 return hash_finish(hHash, &p_pkey->sig);
658 static int hash_sha1_from_file(HCRYPTHASH hHash, CString filename, signature_packet_t *p_sig)
660 FILE * pFile = _tfsopen(filename, _T("rb"), SH_DENYWR);
661 if (!pFile)
662 return -1;
664 char buf[4097];
665 int read = 0;
666 int nlHandling = 0;
667 while ((read = (int)fread(buf, sizeof(char), sizeof(buf) - 1, pFile)) > 0)
669 if (p_sig->type == TEXT_SIGNATURE)
671 buf[read] = 0;
672 char * psz_string = buf;
673 while (*psz_string)
675 if (nlHandling == 1 && (*psz_string == '\r' || *psz_string == '\n'))
677 CryptHashChar(hHash, '\r');
678 CryptHashChar(hHash, '\n');
679 nlHandling = 2;
681 if (nlHandling == 2 && *psz_string == '\r')
683 psz_string++;
684 nlHandling = 2;
685 if (!*psz_string)
686 break;
689 if ((nlHandling == 2 || nlHandling == 3) && *psz_string == '\n')
691 psz_string++;
692 if (!*psz_string)
693 break;
696 size_t i_len = strcspn(psz_string, "\r\n");
698 if (i_len)
700 CryptHashData(hHash, (BYTE *)psz_string, (DWORD)i_len, 0);
701 psz_string += i_len;
704 nlHandling = 1;
705 if (*psz_string == '\r' || *psz_string == '\n')
707 CryptHashChar(hHash, '\r');
708 CryptHashChar(hHash, '\n');
709 nlHandling = 2;
711 if (*psz_string == '\r')
713 psz_string++;
714 nlHandling = 3;
717 if (*psz_string == '\n')
719 psz_string++;
720 nlHandling = 0;
725 else
726 CryptHashData(hHash, (BYTE *)buf, read, 0);
729 fclose(pFile);
731 return hash_finish(hHash, p_sig);
734 static int check_hash(HCRYPTHASH hHash, signature_packet_t *p_sig)
736 DWORD len = 20;
737 unsigned char hash[20];
738 CryptGetHashParam(hHash, HP_HASHVAL, hash, &len, 0);
740 if (hash[0] != p_sig->hash_verification[0] || hash[1] != p_sig->hash_verification[1])
741 return -1;
743 return 0;
746 static int verify_signature(HCRYPTPROV hCryptProv, HCRYPTHASH hHash, public_key_t &p_pkey, signature_packet_t &p_sig)
748 HCRYPTKEY hPubKey;
749 // based on http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2004-10/0040.html
750 DSAKEY dsakey;
751 dsakey.blobheader.bType = PUBLICKEYBLOB; // 0x06
752 dsakey.blobheader.bVersion = CUR_BLOB_VERSION + 1; // 0x03
753 dsakey.blobheader.reserved = 0;
754 dsakey.blobheader.aiKeyAlg = CALG_DSS_SIGN;
755 dsakey.dsspubkeyver3.magic = 0x33535344; // ASCII of "DSS3";
756 dsakey.dsspubkeyver3.bitlenP = 1024; // # of bits in prime modulus
757 dsakey.dsspubkeyver3.bitlenQ = 160; // # of bits in prime q, 0 if not available
758 dsakey.dsspubkeyver3.bitlenJ = 0; // # of bits in (p-1)/q, 0 if not available
759 dsakey.dsspubkeyver3.DSSSeed.counter = 0xFFFFFFFF; // not available
761 memcpy(dsakey.p, p_pkey.key.p + 2, sizeof(p_pkey.key.p) - 2); std::reverse(dsakey.p, dsakey.p + sizeof(dsakey.p));
762 memcpy(dsakey.q, p_pkey.key.q + 2, sizeof(p_pkey.key.q) - 2); std::reverse(dsakey.q, dsakey.q + sizeof(dsakey.q));
763 memcpy(dsakey.g, p_pkey.key.g + 2, sizeof(p_pkey.key.g) - 2); std::reverse(dsakey.g, dsakey.g + sizeof(dsakey.g));
764 memcpy(dsakey.y, p_pkey.key.y + 2, sizeof(p_pkey.key.y) - 2); std::reverse(dsakey.y, dsakey.y + sizeof(dsakey.y));
766 if (CryptImportKey(hCryptProv, (BYTE*)&dsakey, sizeof(dsakey), 0, 0, &hPubKey) == 0)
767 return -1;
769 unsigned char signature[40];
770 memcpy(signature, p_sig.r + 2, 20);
771 memcpy(signature + 20, p_sig.s + 2, 20);
772 std::reverse(signature, signature + 20);
773 std::reverse(signature + 20, signature + 40);
774 if (!CryptVerifySignature(hHash, signature, sizeof(signature), hPubKey, nullptr, 0))
776 CryptDestroyKey(hPubKey);
777 return -1;
780 CryptDestroyKey(hPubKey);
781 return 0;
785 * download a public key (the last one) from TortoiseGit server, and parse it
787 static public_key_t *download_key(const uint8_t *p_longid, const uint8_t *p_signature_issuer)
789 CString url;
790 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]);
792 CString tempfile = CTempFiles::Instance().GetTempFilePath(true).GetWinPathString();
793 if (URLDownloadToFile(nullptr, url, tempfile, 0, nullptr) != S_OK)
794 return nullptr;
796 int size = 65536;
797 std::unique_ptr<char[]> buffer(new char[size]);
798 FILE * pFile = _tfsopen(tempfile, _T("rb"), SH_DENYWR);
799 if (pFile)
801 int length = 0;
802 if ((length = (int)fread(buffer.get(), sizeof(char), size, pFile)) >= 8)
804 fclose(pFile);
805 size = length;
807 else
809 fclose(pFile);
810 return nullptr;
813 else
814 return nullptr;
816 public_key_t *p_pkey = (public_key_t*) malloc(sizeof(public_key_t));
817 if (!p_pkey)
819 DeleteUrlCacheEntry(url);
820 return nullptr;
823 memcpy(p_pkey->longid, p_longid, 8);
825 if (parse_public_key((const uint8_t *)buffer.get(), size, p_pkey, p_signature_issuer))
827 free(p_pkey);
828 return nullptr;
831 return p_pkey;
834 int VerifyIntegrity(const CString &filename, const CString &signatureFilename)
836 signature_packet_t p_sig;
837 memset(&p_sig, 0, sizeof(signature_packet_t));
838 if (LoadSignature(signatureFilename, &p_sig))
839 return -1;
841 public_key_t p_pkey;
842 memset(&p_pkey, 0, sizeof(public_key_t));
843 if (parse_public_key(tortoisegit_public_key, sizeof(tortoisegit_public_key), &p_pkey, nullptr))
845 if (p_sig.version == 4)
847 free(p_sig.specific.v4.hashed_data);
848 free(p_sig.specific.v4.unhashed_data);
850 return -1;
852 memcpy(p_pkey.longid, tortoisegit_public_key_longid, 8);
854 HCRYPTPROV hCryptProv;
855 if (!CryptAcquireContext(&hCryptProv, nullptr, nullptr, PROV_DSS, CRYPT_VERIFYCONTEXT))
857 if (p_sig.version == 4)
859 free(p_sig.specific.v4.hashed_data);
860 free(p_sig.specific.v4.unhashed_data);
862 free(p_pkey.psz_username);
863 return -1;
866 if (memcmp(p_sig.issuer_longid, p_pkey.longid, 8) != 0)
868 public_key_t *p_new_pkey = download_key(p_sig.issuer_longid, tortoisegit_public_key_longid);
869 if (!p_new_pkey)
871 if (p_sig.version == 4)
873 free(p_sig.specific.v4.hashed_data);
874 free(p_sig.specific.v4.unhashed_data);
876 free(p_pkey.psz_username);
877 CryptReleaseContext(hCryptProv, 0);
878 return -1;
881 HCRYPTHASH hHash;
882 if (!CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash))
884 if (p_sig.version == 4)
886 free(p_sig.specific.v4.hashed_data);
887 free(p_sig.specific.v4.unhashed_data);
889 free(p_pkey.psz_username);
890 CryptReleaseContext(hCryptProv, 0);
891 free(p_new_pkey->psz_username);
892 if (p_new_pkey->sig.version == 4)
894 free(p_new_pkey->sig.specific.v4.hashed_data);
895 free(p_new_pkey->sig.specific.v4.unhashed_data);
897 free(p_new_pkey);
898 return -1;
901 if (hash_sha1_from_public_key(hHash, p_new_pkey))
903 if (p_sig.version == 4)
905 free(p_sig.specific.v4.hashed_data);
906 free(p_sig.specific.v4.unhashed_data);
908 free(p_pkey.psz_username);
909 CryptReleaseContext(hCryptProv, 0);
910 free(p_new_pkey->psz_username);
911 if (p_new_pkey->sig.version == 4)
913 free(p_new_pkey->sig.specific.v4.hashed_data);
914 free(p_new_pkey->sig.specific.v4.unhashed_data);
916 free(p_new_pkey);
917 CryptDestroyHash(hHash);
918 return -1;
921 if (check_hash(hHash, &p_new_pkey->sig))
923 if (p_sig.version == 4)
925 free(p_sig.specific.v4.hashed_data);
926 free(p_sig.specific.v4.unhashed_data);
928 free(p_pkey.psz_username);
929 CryptReleaseContext(hCryptProv, 0);
930 free(p_new_pkey->psz_username);
931 if (p_new_pkey->sig.version == 4)
933 free(p_new_pkey->sig.specific.v4.hashed_data);
934 free(p_new_pkey->sig.specific.v4.unhashed_data);
936 free(p_new_pkey);
937 CryptDestroyHash(hHash);
938 return -1;
941 if (verify_signature(hCryptProv, hHash, p_pkey, p_new_pkey->sig))
943 if (p_sig.version == 4)
945 free(p_sig.specific.v4.hashed_data);
946 free(p_sig.specific.v4.unhashed_data);
948 free(p_pkey.psz_username);
949 CryptReleaseContext(hCryptProv, 0);
950 free(p_new_pkey->psz_username);
951 if (p_new_pkey->sig.version == 4)
953 free(p_new_pkey->sig.specific.v4.hashed_data);
954 free(p_new_pkey->sig.specific.v4.unhashed_data);
956 free(p_new_pkey);
957 CryptDestroyHash(hHash);
958 return -1;
960 else
962 CryptDestroyHash(hHash);
963 free(p_pkey.psz_username);
964 p_pkey = *p_new_pkey;
965 if (p_pkey.sig.version == 4)
967 p_pkey.sig.version = 0;
968 free(p_pkey.sig.specific.v4.hashed_data);
969 free(p_pkey.sig.specific.v4.unhashed_data);
971 free(p_new_pkey);
975 int nRetCode = -1;
977 HCRYPTHASH hHash;
978 if (!CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash))
979 goto error;
981 if (hash_sha1_from_file(hHash, filename, &p_sig))
982 goto error;
984 if (check_hash(hHash, &p_sig))
985 goto error;
987 if (verify_signature(hCryptProv, hHash, p_pkey, p_sig))
988 goto error;
990 nRetCode = 0;
992 error:
993 CryptDestroyHash(hHash);
994 CryptReleaseContext(hCryptProv, 0);
996 free(p_pkey.psz_username);
997 if (p_sig.version == 4)
999 free(p_sig.specific.v4.hashed_data);
1000 free(p_sig.specific.v4.unhashed_data);
1003 return nRetCode;