~ubuntu-branches/ubuntu/utopic/freerdp/utopic

« back to all changes in this revision

Viewing changes to libfreerdp-core/certificate.c

  • Committer: Package Import Robot
  • Author(s): Otavio Salvador, Jeremy Bicha
  • Date: 2012-02-11 10:34:05 UTC
  • mfrom: (1.1.7) (9.1.3 sid)
  • Revision ID: package-import@ubuntu.com-20120211103405-mk0gjhjn70eeyxul
Tags: 1.0.1-1
[ Jeremy Bicha ]
* New upstream release. Closes: #659332.
* Updated symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * FreeRDP: A Remote Desktop Protocol Client
3
3
 * Certificate Handling
4
4
 *
 
5
 * Copyright 2011 Jiten Pathy
5
6
 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
7
 *
7
8
 * Licensed under the Apache License, Version 2.0 (the "License");
17
18
 * limitations under the License.
18
19
 */
19
20
 
 
21
#include <errno.h>
 
22
#include <stdio.h>
 
23
#include <string.h>
 
24
 
 
25
#include <openssl/pem.h>
 
26
#include <openssl/rsa.h>
 
27
 
 
28
#include <freerdp/utils/file.h>
 
29
 
 
30
static const char certificate_store_dir[] = "certs";
 
31
static const char certificate_known_hosts_file[] = "known_hosts";
 
32
 
20
33
#include "certificate.h"
21
34
 
22
35
/**
123
136
        int exponent_length;
124
137
 
125
138
        s = stream_new(0);
126
 
        s->p = s->data = cert->data;
 
139
        stream_attach(s, cert->data, cert->length);
127
140
 
128
141
        ber_read_sequence_tag(s, &length); /* Certificate (SEQUENCE) */
129
142
 
188
201
        stream_read(s, &info->exponent[4 - exponent_length], exponent_length);
189
202
        crypto_reverse(info->modulus.data, modulus_length);
190
203
        crypto_reverse(info->exponent, 4);
 
204
 
 
205
        stream_detach(s);
 
206
        stream_free(s);
191
207
}
192
208
 
193
209
/**
217
233
{
218
234
        int i;
219
235
 
220
 
        if (x509_cert_chain == NULL)
221
 
                return;
222
 
 
223
 
        for (i = 0; i < (int) x509_cert_chain->count; i++)
 
236
        if (x509_cert_chain != NULL)
224
237
        {
225
 
                if (x509_cert_chain->array[i].data != NULL)
226
 
                        xfree(x509_cert_chain->array[i].data);
 
238
                for (i = 0; i < (int) x509_cert_chain->count; i++)
 
239
                {
 
240
                        if (x509_cert_chain->array[i].data != NULL)
 
241
                                xfree(x509_cert_chain->array[i].data);
 
242
                }
 
243
 
 
244
                xfree(x509_cert_chain->array);
 
245
                xfree(x509_cert_chain);
227
246
        }
228
 
 
229
 
        xfree(x509_cert_chain);
230
247
}
231
248
 
232
249
static boolean certificate_process_server_public_key(rdpCertificate* certificate, STREAM* s, uint32 length)
251
268
        modlen = keylen - 8;
252
269
        freerdp_blob_alloc(&(certificate->cert_info.modulus), modlen);
253
270
        stream_read(s, certificate->cert_info.modulus.data, modlen);
 
271
        /* 8 bytes of zero padding */
254
272
        stream_seek(s, 8);
255
273
 
256
274
        return true;
257
275
}
258
276
 
259
 
static boolean certificate_process_server_public_signature(rdpCertificate* certificate, STREAM* s, uint32 length)
 
277
static boolean certificate_process_server_public_signature(rdpCertificate* certificate, uint8* sigdata, int sigdatalen, STREAM* s, uint32 siglen)
260
278
{
261
 
        stream_seek(s, length);
 
279
        uint8 md5hash[CRYPTO_MD5_DIGEST_LENGTH];
 
280
        uint8 encsig[TSSK_KEY_LENGTH + 8];
 
281
        uint8 sig[TSSK_KEY_LENGTH];
 
282
        CryptoMd5 md5ctx;
 
283
        int i, sum;
 
284
 
 
285
        md5ctx = crypto_md5_init();
 
286
        crypto_md5_update(md5ctx, sigdata, sigdatalen);
 
287
        crypto_md5_final(md5ctx, md5hash);
 
288
 
 
289
        stream_read(s, encsig, siglen);
 
290
 
 
291
        /* Last 8 bytes shall be all zero. */
 
292
 
 
293
        for (sum = 0, i = sizeof(encsig) - 8; i < sizeof(encsig); i++)
 
294
                sum += encsig[i];
 
295
 
 
296
        if (sum != 0)
 
297
        {
 
298
                printf("certificate_process_server_public_signature: invalid signature\n");
 
299
                //return false;
 
300
        }
 
301
 
 
302
        siglen -= 8;
 
303
 
 
304
        crypto_rsa_public_decrypt(encsig, siglen, TSSK_KEY_LENGTH, tssk_modulus, tssk_exponent, sig);
 
305
 
 
306
        /* Verify signature. */
 
307
        if (memcmp(md5hash, sig, sizeof(md5hash)) != 0)
 
308
        {
 
309
                printf("certificate_process_server_public_signature: invalid signature\n");
 
310
                //return false;
 
311
        }
 
312
 
 
313
        /*
 
314
         * Verify rest of decrypted data:
 
315
         * The 17th byte is 0x00.
 
316
         * The 18th through 62nd bytes are each 0xFF.
 
317
         * The 63rd byte is 0x01.
 
318
         */
 
319
 
 
320
        for (sum = 0, i = 17; i < 62; i++)
 
321
                sum += sig[i];
 
322
 
 
323
        if (sig[16] != 0x00 || sum != 0xFF * (62 - 17) || sig[62] != 0x01)
 
324
        {
 
325
                printf("certificate_process_server_public_signature: invalid signature\n");
 
326
                //return false;
 
327
        }
 
328
 
262
329
        return true;
263
330
}
264
331
 
276
343
        uint32 wPublicKeyBlobLen;
277
344
        uint32 wSignatureBlobType;
278
345
        uint32 wSignatureBlobLen;
 
346
        uint8* sigdata;
 
347
        int sigdatalen;
279
348
 
 
349
        /* -4, because we need to include dwVersion */
 
350
        sigdata = stream_get_tail(s) - 4;
280
351
        stream_read_uint32(s, dwSigAlgId);
281
352
        stream_read_uint32(s, dwKeyAlgId);
282
 
        if (!(dwSigAlgId == 1 && dwKeyAlgId == 1))
 
353
        if (!(dwSigAlgId == SIGNATURE_ALG_RSA && dwKeyAlgId == KEY_EXCHANGE_ALG_RSA))
283
354
        {
284
355
                printf("certificate_read_server_proprietary_certificate: parse error 1\n");
285
356
                return false;
296
367
                printf("certificate_read_server_proprietary_certificate: parse error 3\n");
297
368
                return false;
298
369
        }
 
370
        sigdatalen = stream_get_tail(s) - sigdata;
299
371
        stream_read_uint16(s, wSignatureBlobType);
300
372
        if (wSignatureBlobType != BB_RSA_SIGNATURE_BLOB)
301
373
        {
303
375
                return false;
304
376
        }
305
377
        stream_read_uint16(s, wSignatureBlobLen);
306
 
        if (!certificate_process_server_public_signature(certificate, s, wSignatureBlobLen))
 
378
        if (wSignatureBlobLen != 72)
 
379
        {
 
380
                printf("certificate_process_server_public_signature: invalid signature length (got %d, expected %d)\n", wSignatureBlobLen, 64);
 
381
                return false;
 
382
        }
 
383
        if (!certificate_process_server_public_signature(certificate, sigdata, sigdatalen, s, wSignatureBlobLen))
307
384
        {
308
385
                printf("certificate_read_server_proprietary_certificate: parse error 5\n");
309
386
                return false;
346
423
                        DEBUG_CERTIFICATE("License Server Certificate");
347
424
                        certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info);
348
425
                        DEBUG_LICENSE("modulus length:%d", cert_info.modulus.length);
 
426
                        freerdp_blob_free(&cert_info.modulus);
349
427
                }
350
428
                else if (numCertBlobs - i == 1)
351
429
                {
371
449
        uint32 dwVersion;
372
450
 
373
451
        s = stream_new(0);
374
 
        s->p = s->data = server_cert;
 
452
        stream_attach(s, server_cert, length);
375
453
 
376
454
        if (length < 1)
377
455
        {
400
478
        return true;
401
479
}
402
480
 
 
481
rdpKey* key_new(const char* keyfile)
 
482
{
 
483
        rdpKey* key;
 
484
        RSA *rsa;
 
485
        FILE *fp;
 
486
 
 
487
        key = (rdpKey*) xzalloc(sizeof(rdpKey));
 
488
 
 
489
        if (key == NULL)
 
490
                return NULL;
 
491
 
 
492
        fp = fopen(keyfile, "r");
 
493
 
 
494
        if (fp == NULL)
 
495
        {
 
496
                printf("unable to load RSA key from %s: %s.", keyfile, strerror(errno));
 
497
                return NULL;
 
498
        }
 
499
 
 
500
        rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
 
501
 
 
502
        if (rsa == NULL)
 
503
        {
 
504
                ERR_print_errors_fp(stdout);
 
505
                fclose(fp);
 
506
                return NULL;
 
507
        }
 
508
 
 
509
        fclose(fp);
 
510
 
 
511
        switch (RSA_check_key(rsa))
 
512
        {
 
513
                case 0:
 
514
                        RSA_free(rsa);
 
515
                        printf("invalid RSA key in %s", keyfile);
 
516
                        return NULL;
 
517
 
 
518
                case 1:
 
519
                        /* Valid key. */
 
520
                        break;
 
521
 
 
522
                default:
 
523
                        ERR_print_errors_fp(stdout);
 
524
                        RSA_free(rsa);
 
525
                        return NULL;
 
526
        }
 
527
 
 
528
        if (BN_num_bytes(rsa->e) > 4)
 
529
        {
 
530
                RSA_free(rsa);
 
531
                printf("RSA public exponent too large in %s", keyfile);
 
532
                return NULL;
 
533
        }
 
534
 
 
535
        freerdp_blob_alloc(&key->modulus, BN_num_bytes(rsa->n));
 
536
        BN_bn2bin(rsa->n, key->modulus.data);
 
537
        crypto_reverse(key->modulus.data, key->modulus.length);
 
538
        freerdp_blob_alloc(&key->private_exponent, BN_num_bytes(rsa->d));
 
539
        BN_bn2bin(rsa->d, key->private_exponent.data);
 
540
        crypto_reverse(key->private_exponent.data, key->private_exponent.length);
 
541
        memset(key->exponent, 0, sizeof(key->exponent));
 
542
        BN_bn2bin(rsa->e, key->exponent + sizeof(key->exponent) - BN_num_bytes(rsa->e));
 
543
        crypto_reverse(key->exponent, sizeof(key->exponent));
 
544
 
 
545
        RSA_free(rsa);
 
546
 
 
547
        return key;
 
548
}
 
549
 
 
550
void key_free(rdpKey* key)
 
551
{
 
552
        if (key != NULL)
 
553
        {
 
554
                freerdp_blob_free(&key->modulus);
 
555
                freerdp_blob_free(&key->private_exponent);
 
556
                xfree(key);
 
557
        }
 
558
}
 
559
 
 
560
void certificate_store_init(rdpCertificateStore* certificate_store)
 
561
{
 
562
        char* config_path;
 
563
        rdpSettings* settings;
 
564
 
 
565
        settings = certificate_store->settings;
 
566
 
 
567
        config_path = freerdp_get_config_path(settings);
 
568
        certificate_store->path = freerdp_construct_path(config_path, (char*) certificate_store_dir);
 
569
 
 
570
        if (freerdp_check_file_exists(certificate_store->path) == false)
 
571
        {
 
572
                freerdp_mkdir(certificate_store->path);
 
573
                printf("creating directory %s\n", certificate_store->path);
 
574
        }
 
575
 
 
576
        certificate_store->file = freerdp_construct_path(config_path, (char*) certificate_known_hosts_file);
 
577
 
 
578
        if (freerdp_check_file_exists(certificate_store->file) == false)
 
579
        {
 
580
                certificate_store->fp = fopen((char*) certificate_store->file, "w+");
 
581
 
 
582
                if (certificate_store->fp == NULL)
 
583
                {
 
584
                        printf("certificate_store_open: error opening [%s] for writing\n", certificate_store->file);
 
585
                        return;
 
586
                }
 
587
 
 
588
                fflush(certificate_store->fp);
 
589
        }
 
590
        else
 
591
        {
 
592
                certificate_store->fp = fopen((char*) certificate_store->file, "r+");
 
593
        }
 
594
}
 
595
 
 
596
int certificate_data_match(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
 
597
{
 
598
        FILE* fp;
 
599
        int length;
 
600
        char* data;
 
601
        char* pline;
 
602
        int match = 1;
 
603
        long int size;
 
604
 
 
605
        fp = certificate_store->fp;
 
606
 
 
607
        if (!fp)
 
608
                return match;
 
609
 
 
610
        fseek(fp, 0, SEEK_END);
 
611
        size = ftell(fp);
 
612
        fseek(fp, 0, SEEK_SET);
 
613
 
 
614
        if (size < 1)
 
615
                return match;
 
616
 
 
617
        data = (char*) xmalloc(size + 2);
 
618
 
 
619
        if (fread(data, size, 1, fp) != 1)
 
620
        {
 
621
                xfree(data);
 
622
                return match;
 
623
        }
 
624
 
 
625
        data[size] = '\n';
 
626
        data[size + 1] = '\0';
 
627
        pline = strtok(data, "\n");
 
628
 
 
629
        while (pline != NULL)
 
630
        {
 
631
                length = strlen(pline);
 
632
 
 
633
                if (length > 0)
 
634
                {
 
635
                        length = strcspn(pline, " \t");
 
636
                        pline[length] = '\0';
 
637
 
 
638
                        if (strcmp(pline, certificate_data->hostname) == 0)
 
639
                        {
 
640
                                pline = &pline[length + 1];
 
641
 
 
642
                                if (strcmp(pline, certificate_data->fingerprint) == 0)
 
643
                                        match = 0;
 
644
                                else
 
645
                                        match = -1;
 
646
                                break;
 
647
                        }
 
648
                }
 
649
 
 
650
                pline = strtok(NULL, "\n");
 
651
        }
 
652
        xfree(data);
 
653
 
 
654
        return match;
 
655
}
 
656
 
 
657
void certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
 
658
{
 
659
        FILE* fp;
 
660
 
 
661
        /* reopen in append mode */
 
662
        fp = fopen(certificate_store->file, "a");
 
663
 
 
664
        if (!fp)
 
665
                return;
 
666
 
 
667
        fprintf(certificate_store->fp,"%s %s\n", certificate_data->hostname, certificate_data->fingerprint);
 
668
        fclose(fp);
 
669
}
 
670
 
 
671
rdpCertificateData* certificate_data_new(char* hostname, char* fingerprint)
 
672
{
 
673
        rdpCertificateData* certdata;
 
674
 
 
675
        certdata = (rdpCertificateData*) xzalloc(sizeof(rdpCertificateData));
 
676
 
 
677
        if (certdata != NULL)
 
678
        {
 
679
                certdata->hostname = xstrdup(hostname);
 
680
                certdata->fingerprint = xstrdup(fingerprint);
 
681
        }
 
682
 
 
683
        return certdata;
 
684
}
 
685
 
 
686
void certificate_data_free(rdpCertificateData* certificate_data)
 
687
{
 
688
        if (certificate_data != NULL)
 
689
        {
 
690
                xfree(certificate_data->hostname);
 
691
                xfree(certificate_data->fingerprint);
 
692
                xfree(certificate_data);
 
693
        }
 
694
}
 
695
 
 
696
rdpCertificateStore* certificate_store_new(rdpSettings* settings)
 
697
{
 
698
        rdpCertificateStore* certificate_store;
 
699
 
 
700
        certificate_store = (rdpCertificateStore*) xzalloc(sizeof(rdpCertificateStore));
 
701
 
 
702
        if (certificate_store != NULL)
 
703
        {
 
704
                certificate_store->settings = settings;
 
705
                certificate_store_init(certificate_store);
 
706
        }
 
707
 
 
708
        return certificate_store;
 
709
}
 
710
 
 
711
void certificate_store_free(rdpCertificateStore* certstore)
 
712
{
 
713
        if (certstore != NULL)
 
714
        {
 
715
                if (certstore->fp != NULL)
 
716
                        fclose(certstore->fp);
 
717
 
 
718
                xfree(certstore->path);
 
719
                xfree(certstore->file);
 
720
                xfree(certstore);
 
721
        }
 
722
}
 
723
 
403
724
/**
404
725
 * Instantiate new certificate module.\n
405
726
 * @param rdp RDP module
406
727
 * @return new certificate module
407
728
 */
408
729
 
409
 
rdpCertificate* certificate_new(void)
 
730
rdpCertificate* certificate_new()
410
731
{
411
732
        rdpCertificate* certificate;
412
733
 
430
751
        if (certificate != NULL)
431
752
        {
432
753
                certificate_free_x509_certificate_chain(certificate->x509_cert_chain);
 
754
 
 
755
                if (certificate->cert_info.modulus.data != NULL)
 
756
                        freerdp_blob_free(&(certificate->cert_info.modulus));
 
757
 
433
758
                xfree(certificate);
434
759
        }
435
760
}
436