1 #include "dnscrypt.h"
2 
3 struct SignedCert *
cert_build_cert(const uint8_t * crypt_publickey,int cert_file_expire_seconds,int use_xchacha20)4 cert_build_cert(const uint8_t *crypt_publickey, int cert_file_expire_seconds,
5                 int use_xchacha20)
6 {
7     struct SignedCert *signed_cert = malloc(sizeof(struct SignedCert));
8     if (!signed_cert)
9         return NULL;
10 
11     memcpy(signed_cert->magic_cert, CERT_MAGIC_CERT, 4);
12     signed_cert->version_major[0] = 0;
13     if (use_xchacha20) {
14         signed_cert->version_major[1] = 2;
15     } else {
16         signed_cert->version_major[1] = 1;
17     }
18     signed_cert->version_minor[0] = 0;
19     signed_cert->version_minor[1] = 0;
20 
21     memset(signed_cert->signature, 0, sizeof signed_cert->signature);
22     memcpy(signed_cert->server_publickey, crypt_publickey,
23            crypto_box_PUBLICKEYBYTES);
24     memcpy(signed_cert->magic_query, crypt_publickey,
25            sizeof(signed_cert->magic_query));
26     if (use_xchacha20) {
27         sodium_increment(signed_cert->magic_query, sizeof signed_cert->magic_query);
28     }
29     uint32_t ts_begin = (uint32_t)time(NULL);
30     uint32_t ts_end = ts_begin + cert_file_expire_seconds;
31     if (cert_file_expire_seconds <= 0) {
32         ts_begin = ts_end;
33     }
34     ts_begin = htonl(ts_begin);
35     ts_end = htonl(ts_end);
36     memcpy(signed_cert->serial, &ts_begin, 4);
37     memcpy(signed_cert->ts_begin, &ts_begin, 4);
38     memcpy(signed_cert->ts_end, &ts_end, 4);
39 
40     return signed_cert;
41 }
42 
43 int
cert_sign(struct SignedCert * signed_cert,const uint8_t * provider_secretkey)44 cert_sign(struct SignedCert *signed_cert, const uint8_t *provider_secretkey)
45 {
46     unsigned long long signed_data_len =
47         sizeof(struct SignedCert) - offsetof(struct SignedCert,
48                                              server_publickey);
49 
50     return crypto_sign_detached(signed_cert->signature, NULL,
51                                 signed_cert->server_publickey, signed_data_len,
52                                 provider_secretkey);
53 }
54 
55 void
cert_display_txt_record_tinydns(struct SignedCert * signed_cert)56 cert_display_txt_record_tinydns(struct SignedCert *signed_cert)
57 {
58     size_t i = (size_t) 0U;
59     int c;
60 
61     fputs("'2.dnscrypt-cert:", stdout);
62     while (i < sizeof(struct SignedCert)) {
63         c = (int)*((const uint8_t *) signed_cert + i);
64         if (isprint(c) && c != ':' && c != '\\' && c != '&' && c != '<'
65             && c != '>') {
66             putchar(c);
67         } else {
68             printf("\\%03o", c);
69         }
70         i++;
71     }
72     puts(":86400");
73 }
74 
75 void
cert_display_txt_record(struct SignedCert * signed_cert)76 cert_display_txt_record(struct SignedCert *signed_cert)
77 {
78     size_t i = (size_t) 0U;
79     int c;
80 
81     fputs("2.dnscrypt-cert\t86400\tIN\tTXT\t\"", stdout);
82     while (i < sizeof(struct SignedCert)) {
83         c = (int)*((const uint8_t *) signed_cert + i);
84         if (isprint(c) && c != '"' && c != '\\') {
85             putchar(c);
86         } else {
87             printf("\\%03d", c);
88         }
89         i++;
90     }
91     puts("\"");
92 }
93